I have a basic algorithm to rotate an enemy around a 200 unit radius circle with center 0. This is how I'm achieving that:

if (position.Y <= 0 && position.X > -200)
   position.X -= 2;
   position.Y = 0 - (float)Math.Sqrt((200 * 200) - (position.X * position.X));
   position.X += 2;
   position.Y = (float)Math.Sqrt((200 * 200) - (position.X * position.X));

It does work, and I've ensured that at no point does either X or Y equal NaN. However, when Y approaches 0, it seems to go significantly faster. This surprises me, because the Y values are locked to the X, which is being incremented by a steady amount. What can I do to smooth the speed?


The problem here is that sqrt(aa + bb) is non behaving in the way you expected it is non-linear as you can clearly see here:


I don't see any immidiate way on how to fix this. (To be honest I'm surprised this worked in the first place). But I can give you the standard algorithm to accomplish this. This will also keep speed constant and you can use the values of the cos and sin operations later to rotate the player towards the center of your circle.

float time; //use gameTime.TotalGameTime.TotalSeconds and update it every frame
float speed = MathHelper.PiOver2; // in radians per second, this is 1/4 of a circle per second atm
float radius = 200.0f;
Vector2 origin = Vector2.Zero; // change this if you want your circle's origin elsewhere

position.X = (float)(Math.Cos(time * speed) * radius + origin.X);
position.Y = (float)(Math.Sin(time*speed) * radius + origin.Y);
  • \$\begingroup\$ This is about as efficient as calculating the derivate position.X -= speed * (Math.Sin(time*speed) * radius \$\endgroup\$
    – MSalters
    Sep 21 '12 at 14:51
  • \$\begingroup\$ I derived my original function from (x−h)^2+(y−k)^2=r^2, though I suppose that since that function is to plot a circle and not necessarily navigate a circle, it wasn't the best choice. Yours worked much better. \$\endgroup\$
    – Fibericon
    Sep 21 '12 at 15:40
  • \$\begingroup\$ Ah of course, now I see :) \$\endgroup\$
    – Roy T.
    Sep 21 '12 at 15:49

Y values are locked to f(x). f(X) does not equal X therefore Y is not locked to X.

You need a constant angular delta, which can be achieved by using a pair of sin/cos functions:

x = sin( time * speed + offset ) * radius + center_x;
y = cos( time * speed + offset ) * radius + center_y;
x = cos( time * speed + offset ) * radius + center_x;
y = sin( time * speed + offset ) * radius + center_y;

Both ways are valid (first one - logically, like a clock, second - mathematically), they just change starting point (top for first, right side for second) and default direction (when speed is positive, clockwise for first, counter-clockwise for second). Speed and offset are measured in radians.


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.