How do I…
Enemy that orbits the player at a distance and tries to keep the distance.
I have done a small showcase video https://youtu.be/8pEg3Zhk3tc
Implementation Details
Enemys need the object variable: orbitAngle
I came up with two code blocks.
One normal event:
One javascript event, as the calculations went into math.
This block keeps enemies rotating and trying to hold a distance to the player, if he moves. The second part was tricky, as we need to calculate target points and reduce the movement vector of the enemy, if the “distance would be too far”. As the enemy would exeed his speed limits.
Its lines with if (distanced > 1.77) that cap the maximum speed of the enemy when orbiting.
var player = runtimeScene.getObjects(“Player”)[0];
var playerX = player.getX();
var playerY = player.getY();
var enemies = runtimeScene.getObjects(‘Enemy’);
const ORBIT_RADIUS = 190;
const ROTATION_SPEED = 0.0085;
const ACTIVATION_DISTANCE = 196;
enemies.forEach(enemy => {
let vars = enemy.getVariables();
let angleVar = vars.get(“orbitAngle”);
var enemyX = enemy.getX();
var enemyY = enemy.getY();
const dx = enemyX - playerX;
const dy = enemyY - playerY;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < ACTIVATION_DISTANCE) {
// Initialize angle if not set
if (angleVar.getAsNumber() === 0) {
angleVar.setNumber(Math.atan2(dy, dx));
}
// Update rotation
const currentAngle = angleVar.getAsNumber();
angleVar.setNumber(currentAngle + ROTATION_SPEED);
// Calculate desired new position
var targetX = playerX + Math.cos(angleVar.getAsNumber()) * ORBIT_RADIUS;
var targetY = playerY + Math.sin(angleVar.getAsNumber()) * ORBIT_RADIUS;
// Calculate vector components
var ndx = targetX - enemyX;
var ndy = targetY - enemyY;
// Calculate actual distance
var distanced = Math.sqrt(ndx * ndx + ndy * ndy);
runtimeScene.getGame().getVariables().get("distancet").setNumber(distanced);
if (distanced > 1.77) {
var scaleFactor = 1.77 / distanced;
targetX = enemyX + ndx * scaleFactor;
targetY = enemyY + ndy * scaleFactor;
}
// Apply final position
enemy.setX(targetX);
enemy.setY(targetY);
} else {
// Reset angle when out of range for fresh calculation next activation
angleVar.setNumber(0);
}
});