Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!

# Uniform circular motion (moving a sprite along a circular path)

Stephen Bell
Ranch Hand
Posts: 41
Hi all

My game has reached a point now where I need to move a sprite in a circular motion and I'm having some problems with this.

Basically, if I move my sprite along a linear path either left/right or up/down, I use my (fixed) time-delta to determine the relative speed so that for example a sprite will take 10 seconds to cross the
screen regardless of resolution. I do this like so:

So, when I need to move the sprite, I simply do the following:

[Edited to fix line length]

Now, when moving a sprite along a circular path, this is what I have so far:

This kind of works. However, I'm not sure it's correct. My main concern is that a complete revolution takes place in about 1 second.

How can I specify a time in seconds that I wish 1 revolution to take? I'm not clear on how this can be achieved.

All of the suggestions I've seen thus far suggest performing an calculation on the angle variable. However, any change to this variable simply alters the size of the orbit because it's changing the
direction. So, smaller changes mean bigger orbit and bigger changes mean a smaller orbit.

Other reasons I'm not sure what I'm doing is correct is that I'm never specifying a center for rotation. Plus the fact that, unlike my linear movement calculations, this isn't scalable so when I run
at a different resolution, it behaves completely different (ie, faster/slower/larger/smaller).

Would be grateful if someone give me some pointers on what the correct maths would be to achieve what I'm attempting.

Thank you!!

Piet Souris
Rancher
Posts: 1263
26
• 1
hi Stephen,

not the easiest of questions, me thinks. But I'll try to give it a shot.

For your first question, getting a full rotation within a given amount of seconds, there is no alternative other than
calculating the delta angle between two successive frames.

So, say that you want a full rotation in S seconds, and that your framerate is F frames per second, then your
angle between two frames must be:

angle_step = 2 * PI / ( F * S)

But that is the easy part. Now, I am not sure how you define the circular path the sprite must follow. One possibility is:

let a circle C be given by: middlepoint (Cx, Cy) and radius R.
Suppose the sprite has coordinates (Sx, Sy).

Now, translate the circle such that (Sx, Sy) is on the circumference. Then the sprite will follow the circumference of
that translated circle.

Is this a correct assumption? If so, the maths involved are not so very difficult. And we can discuss scaling issues.

HTH.

Greetz,
Piet

Matthew Brown
Bartender
Posts: 4567
8
• 1
You're trying to do a circle with incremental changes to x and y. Which is possible, but does affect the maths a bit. It's probably easier if you do it absolutely. Basically, the equations are these:

x = x_0 + r cos(angle)
y = y_0 + r sin(angle)

That will give you a circle around (x_0, y_0) with radius r, starting from (x_0 + r, y_0) when angle = 0 (negate angle if you want it to go the other direction, or shift it if you want to start somewhere else on the circle).

One complete revolution involves angle going from 0 to 2*PI. So you can fix the time by making sure the step in angle is 2*PI*(time taken per step)/(intended duration). So in this cae

Now, if you want to see how that translates to an incremental calculation, then for constant r (done by differentiating):

(change in x) = -r*sin(angle)*(change in angle)
(change in y) = r*cos(angle)*(change in angle)

Compare that to yours. Firstly, you can see that the centre of the circle doesn't appear. It's going to depend on the initial values of x, y and angle. Secondly, you'll see that your rad variable relates to the radius and the change in angle - so that's why just changing your angle step in that case also changes the size of the orbit. If you're doing the absolute calculation you won't have that problem.

Stephen Bell
Ranch Hand
Posts: 41
Hi Piet,

Thanks very much for this, I'm starting to get somewhere now. I have applied the angle increments as you suggested and it is almost working. I've timed it, and if I specify 5 as time , it does indeed take 5 seconds for a full revolution and then if I specify 10, it takes 10 seconds. However, the problem is that although it takes the specified amounth of time, the orbit gets a lot bigger to accommodate the new time (bigger orbit for bigger time and smaller orbit for smaller time) - how can I keep the orbit size the same while altering the time value?

But that is the easy part. Now, I am not sure how you define the circular path the sprite must follow. One possibility is:

let a circle C be given by: middlepoint (Cx, Cy) and radius R.
Suppose the sprite has coordinates (Sx, Sy).

Now, translate the circle such that (Sx, Sy) is on the circumference. Then the sprite will follow the circumference of
that translated circle.

Is this a correct assumption? If so, the maths involved are not so very difficult. And we can discuss scaling issues.

Yep - that sounds about right!

Stephen Bell
Ranch Hand
Posts: 41
Hi Matthew

Getting closer all the time - thanks so much I've tested your method (specifying the centre of rotation which was one of the things that was confusing me - that I wasn't specifying any centre) and now I can specify a time and a center and the size of the orbit finally stays the same size! :-)

I scale the radius by making it the size of my game-world tiles which are already scaled to display correctly on all resolutions, so, so far all is good.
Again thanks very much for your assistance, it's much appreciated

Piet Souris
Rancher
Posts: 1263
26
• 1
hi Stephan,

what I had in mind was, starting from the (Cx, Cy) and the R, to determine the real centre and the starting angle, as to let you easily determine
the trjactory. Matthew has given you already the maths involved. And you have dealt with the scaling.

So, well done.

Greetz,
Piet

Stephen Bell
Ranch Hand
Posts: 41
Just a couple of questions remain if I can.

How do I place the initial position around the centre of rotation? I would have assumed that setting the angle to 180 would make the sprite appear central and below the centre of rotation however, I can see that my 'angle' is increasing by aprox 0.0261 every tick so, with a time for one revolution of 4 seconds and at 60 ticks per second, I make that 6.2831856 for a full revolution. Does this seems right?

Is there an easy way to work out the initial angle so I can place my sprites starting position wherever I want in the orbit path?

Thanks again

Piet Souris
Rancher
Posts: 1263
26
• 1
6.28... is correct, that is 2*PI, a full rotation when measured in radians.

the sprite follow some trajectory, and then suddenly it starts to circle around some centre?

/********************************/

Suppose you have determined the centre of the circle: (Cx, Cy), and a radius R.
You could now determine a random starting angle alpha, something like:

alpha = Math.random() * 2 * Math.PI;

and from this you can use Matthews first formulae to determine a point on the circumference the sprite.
What point of the sprite that is, is up to you: It could be the centre point of the sprite, or the left top point.

/********************************/

Or you could have an initial position of your sprite to start with. Determine what point of the sprite
you take for this.
Then, you could use the same procedure to determine the centre of the circle, by choosing some starting angle

/********************************/

Or, you could have both a point (Sx, Sy) from the sprite and a centre (Cx, Cy) of the circle.
Then, as radius you could use the distance between these two points, The angle can be determined by

starting_angle = Math.atan2(Sy - Cy, Sx - Cx);

Or you could determine some other radius R by choosing a factor f (0 < f < 1) and calculating:

new_centre_x = (1 - f) * Cx + f * Sx
new_centre_y = (1 - f) * Cy + f * Sy

and calculate the radius again as the distance between S and the new centre.

/***************************************/

I hope this is what you meant.
If so, you have some options here.

Greetings,
Piet

Stephen Bell
Ranch Hand
Posts: 41
Thanks again Piet

Yep, this is what I want to happen, the sprites start out orbiting a defined fixed point with a fixed radius.

What I'm trying to achieve is a almost like a carousel, 4 sprites, one starting at 0 degrees (North), one at 90 (East), one at 180 (South) and another at 270 (East), they will all follow the same orbital path and I need to place them at their respective start positions.

However, I'm still getting used to using radians rather than degrees and that was confusing me, but I see now why the angle variable was increasing in such small steps! So, what I've done is something like:

And then setting the coordinates in the same way as before:

Does this seem acceptable? It appears to work, the only odd thing being that an angle of 0 is 'east' where I would expect 90 degrees to be east (or 1.57 in Radians)

But like I say, it does appear to allow me to set the positions!!

Cheers!

Piet Souris
Rancher
Posts: 1263
26
• 1
It all looks okay.

About angle 0 being the east:

in the normal, standard, pixel coordinate system, where pixel (0,0) is top left, and pixel (width, height)
is bottom right, the positive x-axis goes from left to right, the positive y-axis goes from top to bottom.
Angle 0 is the positive x-axis, so east, and a positive angle rotates in the direction of the positive x-axis
to the positive y-axis, so clockwise.

If you want to rotate anti clockwise, you must use negative angles.

Greetz,
Piet

PS: I forgot to mention that there is a method that converts from degrees to radians.
See the Math class for this, method toRadians(double degrees).

Stephen Bell
Ranch Hand
Posts: 41
Thanks for your help Piet & Mathew

I have a much better understanding of all this now!!