Enemy orbiting the player at a distance

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

Enemy Sprite/Object needs to be created with variable: orbitAngle
Player Sprite/Object needs to be created.

Solution contains one normal event, one javascript event.
Calculations went into math and use force vectors.
It keeps enemies rotating while trying to hold a orbit 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 enemy would exceed his speed limits.

Its lines with if (distanced > 2.87) that cap the maximum speed of the enemy when orbiting.

The following events can be copy&Pasted. Hope some of you find this useful.

{"000kind":"GDEVELOP_EventsAndInstructions_CLIPBOARD_KIND-jsBdHbLy912y8Rc","content":{"eventsList":[{"type":"BuiltinCommonInstructions::ForEach","object":"Enemy","conditions":[{"type":{"inverted":true,"value":"Distance"},"parameters":["Enemy","Player","194",""]}],"actions":[{"type":{"value":"AddForceVersPos"},"parameters":["Enemy","Player.X()","Player.Y()","90","0"]}]},{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["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.01385;","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 > 2.87) {","            var scaleFactor = 2.87 / 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);","    }","});",""],"parameterObjects":"","useStrict":true,"eventsSheetExpanded":false}],"eventsCount":2,"actionsList":[],"actionsCount":0,"conditionsList":[],"conditionsCount":0}}

Could you have made use of the “Put Enemy around Player...” action? Or am I missing something here?

1 Like

That was also my initial idea
But then i watched video he linked and that looks more like mix between put object around another and boids behavior
And idk how to do it with boids

My most stupid idea would be to push enemies away if they are too close to player and pull them if they are in some range
And between too close and too far keep some range where they orbit
But i assumed it would look way too robotic to suggest it

1 Like

I updated the events, they can be copy and pasted. Gave some more insights. In fact the solution uses force movement vectors, similar as how boids are steered. Its not using physics behavior.

Possible extensions:
1.The update frequence to javascript calculations can be limited if you use a timer e.g. In the code it will just always trigger.
2. You can use 2d physics behvior (0 gravity scale for starships) on both player and enemy. recommending circle collision box. then they will not overlap while moving.

1 Like