3
\$\begingroup\$

I am creating a 2D action platformer and want to create some steering behavior for a mage enemy.

Basically, I want the mage to smoothly wander inside an annulus centered on my player.

Below is an image depicting an example path the mage could follow.

enter image description here

The enemy currently has simple seek behavior. It simply accelerates toward whatever is set as its target.

I tried choosing a random target point in the annulus every so often, but when you do this, the enemy sometimes drifts across the center of the annulus to reach a point chosen on the other side.

So my question is, how can I achieve the desired movement?

\$\endgroup\$
2
\$\begingroup\$

If you are using steering behaviors to guide your objects, you could add a repellant force in the center of the circle.

A repellant force is a vector that points in the direction from the center of the circle to the object. The length of the vector is in inverse relation to the distance of the object from the cente (closer: bigger force, distant near zero force). You can tweak the repellant strength to suit your needs.

If you add this force to your steering behaviors and your object will avoid the center and move nicely around your character.

\$\endgroup\$
2
\$\begingroup\$

Give your mage a movement direction vector. When mage moves, turn it around slowly - this will give you wiggling movement. If mage goes outside of allowed range, or gets close to it, turn direction vector towards the center. If it gets too close, turn it away from center. Depending on how fast and how often you change direction vector, you may get the loops like on your image.

\$\endgroup\$
2
\$\begingroup\$

First let me preface this by saying, I think there's a better way to approach this problem by using a different metric (i.e. something like using polar coordinates rather than euclidean X,Y coordinates).

That said, using standard X,Y coords, the easiest way I can see to approach this problem is a test and reject pattern:

  1. Randomly generate a potential new destination (see note below about this step)
  2. Test if the line between the current position and the current destination under consideration clips the center circle. If so, reject the current point & go back to step 1.
  3. Otherwise the current destination is valid & should be used as the next random heading.

While easy to implement, test and reject strategies should always be throughly vetted before use. They don't always work well in situations where you need an immense amount of solutions (i.e. trying to solve multiple instances of the problem repeatedly in real time) or in situations with lots of constraints (i.e. avoiding other obstacles, maintaining line of sight on enemies, etc). That said, they often give answers that are good enough, quickly enough to allow you to focus on the more interesting parts of the game, so don't be too put ooff by the potential ineffiecency.

Regarding the generation of random points: beware of simply picking a random angle & distance, as this will result in a bias towards points near the center. The solution to this problem is to take the square root of the radius which will skew the selection back to a uniform distribution.

\$\endgroup\$
  • 1
    \$\begingroup\$ Thanks for the advice about the choosing a random point in a circle! I was doing it the naive way before you warned me. \$\endgroup\$ – GoldenGremlin Feb 7 at 2:50
  • 1
    \$\begingroup\$ An easy way to get an unbiased 2d vector (inside unit circle) is a similar test-and-reject approach. Generate a pair of random numbers uniformly distributed on the range [-1, +1]. Call them x and y. Now you have a point on a square. Take the distance from the origin to (x, y). If it is grater than 1, reject and try again. This gives you points uniformly distributed inside the unit circle. If you want them on the unit circle just normalize the position vectors. In 2d each iteration has a 79% chance of being in the circle. In 3d it is a bit lower, even more so in 4d. \$\endgroup\$ – Craig Reynolds Apr 29 at 22:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.