So you've just followed a tutorial on how to make a ball bounce. As fantastic as this is, and an important stepping stone, you soon realise the shortcomings of this feat - you ball moves in perfectly straight lines.
While this is great to teach you the basics of a "game" loop and other important aspects of creating a game, or animating in general, you will eventual come across the need to make your objects move in a curved motion. For example, like creating a top down racing car game (unless you want your car to turn at right angles - but I don't think you do!).
What you've currently got
First, let's recap what you're probably doing right now. You've likely got an x and y variable. These hold the current position of your ball:
var x = 100; var y = 200;
You've probably also got dx and dy variables. These are your speed and direction. You're adding these values to x and y, respectively. The higher your value, the faster your object moves. x controls left and right movements and y controls your up and down. Negtive moves left, positive moves right. Simple.
var dx = 3; var dy = 3;
This process takes place in each cycle of your game loop. Once you have your new x and y values, and you've cleared the canvas, you redraw your object at the new x and y location.
Making it smooth
Using curve movements instead of straight movements requires a little change in how you think about moving an object over the previous code. The example above does a good job in showing the curved motion but fails to show one thing. Direction. If those balls were cars, would they always be driving headlights first? (I really should update those balls to cars!)
Let's think about this problem in two parts:
- moving the object in a curved motion.
- keeping the object facing the direction it's moving (just like a person walking faces forward when they walk, regardless if it's in a straight line or curved line.
The other important thing we need is a speed value. So to begin, we will need the following variables:
var x = 100; var y = 200; var direction = 90; var speed = 3;
x and y are the co-ordinates of our starting position. Direction is just that, and is defined in degrees. And speed is how many pixels we move forward with each cycle/loop.
Let's tackle the second problem first: keeping the object facing the direction its moving. First, a definition:The radian is the standard unit of angular measure.
Perfect! that's exactly what we want - a unit of angular measure. And we can do that with simple high school maths (I say simple but I know very well you've forgotten ;) ).
var rad = (direction * Math.PI / 180);
The formula above is simply converting degrees to radians. Want some maths? Ok. As you know; a circle, in degrees, has 360 degrees. A circle, in radians, has 2*PI radians. So to convert degrees to radians, divide by 360 and multiply by 2 * PI, or equivalently, divide by 180 and multiply by PI.
If you don't understand the maths, don't worry - just plug the direction value into the formula above.
The variable rad can now be used to rotate your object by an amount you specify in degrees, thus allowing it to always face forward.
Back to the first problem of calculating your x and y position to create movement in a circular direction, we use some more maths and the radian value we've just calculated. The two kids we use here are sine and cosine. This may bring back memories of that wave like graph you had to plot in high school.
So how do we use them? Like so:
x += speed*Math.sin(rad); y += speed*Math.cos(rad);
Our object will now turn in a circular movement, incrementing each iteration by our speed value. It will face the direction specified by our direction value (in degrees) - assuming you use some kind of rotate() method. And that's really all there is to it.
Just want the formula? Here it is.
var rad = (direction * Math.PI / 180); x += speed*Math.sin(rad); y += speed*Math.cos(rad);
And there you have it. It's one of those things that you don't know it until you've done it once. Let me know your thoughts in the comments below. Happy animating!