Monday, November 2, 2009

Speed, Velocity, and Acceleration

Speed, Velocity, and Acceleration


You may not know the difference between speed and velocity, but you probably have at least some idea of what speed, velocity, and acceleration are. In this section I'll introduce you to these concepts and point out the differences between them.


Speed and Velocity


Velocity is a vector; speed is the magnitude of that vector. In Chapter 3, "Trigonometry 101," we introduced vectors. If you're a linear reader, this concept may be fresh in your mind. But to review, vectors are mathematical objects that contain two pieces of information: a magnitude (also called a scalar value) and a direction. For instance, the velocity 30 kilometers per hour (kph) southeast is a vector. Its magnitude (the speed) is 30, and its direction is southeast.


Let's dig a little deeper into the definitions of these important concepts.


Speed:
The ratio of distance covered and the time taken to cover this distance. Mathematically, this is written as the equation speed = distance/time. For example, if a car travels 30 kilometers in 2 hours, then its speed is 30 kilometers/2 hours = 15 kilometers/hour.


TIP
As defined above, speed is distance divided by time. When you read "15 kilometers/hour," you say "15 kilometers per hour."


Velocity:
A vector formed by combining speed with a direction.


Now let's see how to use this concept of speed and velocity to find the distance traveled in a certain amount of time. If we know the speed at which a car is traveling, how do we know how far it has traveled in, say, 3 hours? Above we said:



speed = distance/time

By doing simple algebra (multiplying both sides by time), we arrive at this equation:



distance = speed*time

With this equation we can find how far a car (or any object) traveled if we know its speed and the amount of time it moved. In the same way, if we know how far the car traveled and the speed of the car, then we can calculate the travel time using the final permutation of this equation:



time = distance/speed

Applying Speed with ActionScript


So now you understand what speed and velocity are. And you understand how if you know any two of the following variables�speed, distance, or time�you can find the remaining value. In many games you are going to need to program movie clips (such as a ball, a car, or a rocket ship) to move. So how do you apply speed to a movie clip? You are about to find out.


We have been talking and thinking about speed as being measured in units of distance/time (distance divided by time). But Flash is not a time-based environment�it is a frame-based environment. To Flash users, one frame can be assumed to be one unit of time. So (as you'll see on your screen if all goes well), it is OK for us to replace every occurrence of a time variable in equations with a variable for frames. For instance, if distance = speed*time, then the new form is distance = speed*frames. (In other words, speed is no longer 10 miles/hour, it's 10 units/frame.) In Flash we are going to change the definition of speed by replacing time with frames. So let's look at our definition of speed again, this time with our new twist:


Speed:
The ratio of distance covered and the frames taken to cover this distance. Mathematically, this is written as the equation speed = distance/frames. For example, if a movie clip travels 30 units in two frames, then its speed is 30 units/2 frames = 15 units/frame.


As seen in the new definition above, the unit of distance measurement is not meters but simply units, or pixels. (I prefer to use the word unit, because if the Flash movie is scaled to a larger or smaller size, then unit is the only word that still applies.) At a scaled size, the pixel dimensions do not change, but the unit dimensions do.



ON THE CD
To see a simple application of speed, open up car1.fla in the Chapter04 directory on the CD-ROM. Notice that the frame rate has been set to 24 frames per second (fps) to ensure smooth playback. On the stage you'll see one movie clip with an instance name of Car. There are a few lines of ActionScript on frame 1 of the Actions layer. They read as follows:


1 xmov = 3;
2 _root.onEnterFrame = function () {
3 car._x += xmov;
4 }

TIP
Throughout the rest of the book, you'll see that I call all x direction speeds xmov and all y direction speeds ymov, or some variation of these basic names (such as tempxmov or xmov1).

Line 1 sets a variable for the speed called xmov with a value of 3. Line 2 sets up an onEnterFrame clip event. All of the actions listed within an onEnterFrame event are called one time in every frame. Line 3 is where we apply the speed to the object. It takes the current position of the car�car._x�and adds the value of the speed to it. Remember that the speed is units per frame. So a speed of 3 means that we will move the car along the x-axis three units in every frame.



When you generate a SWF file to test this movie, you will see the car move relatively smoothly. Actually, the car is being redrawn in a new position 24 times per second. In that way, it's a lot like one of those flip books you might have had when you were a kid, with static images giving the illusion of movement. The frame rate is the vehicle (no pun intended) through which we trick the human eye into seeing what appears to be a continuously moving car, although the movement is actually happening in discrete chunks.



ON THE CD
Now, what if you want to make this car move in two directions at once? To see how you'd add a second dimension, y speed, open car2.fla. This FLA file has the same setup as the previous example. The only difference you'll find is in the ActionScript used. Open the Actions panel to view the ActionScript on frame 1.


1 xmov = 3;
2 ymov = 2;
3 _root.onEnterFrame = function () {
4 car._x += xmov;
5 car._y += ymov;
6 }

This differs from the ActionScript in the previous example by two lines of code. Line 2 defines a variable to represent the speed in the y direction, and line 5 controls the placement of the car by adding the value of ymov to the car's y position. This is done 24 times a second, so the result is what looks like a moving car.



You may have already picked up on a visual problem in this case, though. The car is moving diagonally, but it's facing horizontally. To see how to get the car to face the correct direction, open car3.fla. You will notice that, once more, there are two new lines of code just before the onEnterFrame event. They are:



1 angle = Math.atan2(ymov, xmov)*180/Math.PI;
2 car._rotation = angle;

In short, line 1 calculates the angle that the car should be rotated, and line 2 rotates the car. Summoning up what we discussed in the last chapter (remember trigonometry?), we know that we can use two sides of a right triangle to find the angle made by the trajectory of the car with the x-axis. The key is to think about the horizontal and vertical sides of the triangle as the ones made by xmov and ymov, respectively.


Before rotation, the car forms an angle of 0° with the x-axis. Here we are figuring out how much the car needs to be rotated in order to point in the direction in which it is moving. Knowing the x side length (the x speed) and the y side length (the y speed), we can find the angle using the inverse tangent Math.atan2(). This returns an angle in radians�the angle we'll use to rotate the movie clip. To do this, we must use the _rotation property. Simple enough�but just to keep things interesting, the _rotation property only accepts angles in degrees! That's what's going on in line 1; we're converting the angle into degrees by multiplying by the conversion factor 180/Math.PI.


ON THE CD
For a slightly more advanced practical example, see shooter.fla in the Chapter04 directory on the CD.



Acceleration


Put quite simply, acceleration occurs whenever the velocity changes. Remember that velocity contains a speed and a direction. So if the speed or the direction of something changes, then it has accelerated.


Acceleration, like velocity, is a vector. It has a magnitude and a direction. More specifically, it's a vector with a magnitude that is the ratio of the difference in velocity and the difference in time over which this difference occurred, and the direction in which the acceleration occurred. (If this sounds like three items instead of two, read it again with careful obedience to the commas.)



Acceleration = (velocity2 - velocity1)/(time2 - time1)

where velocity2 is the velocity at time2, and velocity1 is the velocity at time1. The units of acceleration are measured as distance/time2.



If you know the acceleration of an object and its current velocity, then you can find or project the velocity of that object at any time in the future. Here is the equation to do this:



velocity_future = velocity_now + acceleration*time

The quantity time in the equation above is how far into the future you are looking. Remember that both velocity and acceleration are vectors. In Flash, we have to resolve vectors into their x and y components before we can use them. After we find the xspeed, yspeed, xacceleration, and yacceleration (using the techniques used in Chapter 3 and reintroduced earlier in this section), then we can write the following equations:



xspeed_future = xspeed_now + xacceleration*time

and



yspeed_future=yspeed_now + yacceleration*time

If you know the current position and velocity of an object, then you can find its position at any time in the future. You can find the future position by using the following equations:



xposition_future = xposition_now + xspeed_now*time
+ 1/2*(xacceleration)*time2

and



yposition_future = yposition_now + yspeed_now*time
+ 1/2*(yacceleration)*time2

Applying Acceleration with ActionScript


The equations you've just been looking at may seem messy, but their application in Flash is quite easy. Remember that we can replace time with frames in all of our equations. We will always be calculating new values for just one frame later. This is good news for us, because it means we can replace the time with 1 everywhere. Using that trick, we can rewrite the four x- and y-component equations shown in the previous section.


For future speed:



xspeed_future = xspeed_now + xacceleration

and



yspeed_future = yspeed_now + yacceleration

For future position:



xposition_future = xposition_now + xspeed_now
+ 1/2*(xacceleration)

and



yposition_future = yposition_now + yspeed_now
+ 1/2*(yacceleration)

As you probably know, you cannot add two quantities that have different units. For instance, 10 meters plus 12 ounces makes … no sense. In the above equations, we appear to be adding quantities that have different units (with apologies to any physicists, mathematicians, and engineers out there). What happened is that we dropped the frame variable from the equations. We're getting away with this because we assumed the value of the frame variable is always going to be 1 (see the previous paragraph), and since multiplying anything by 1 gives a result of the original value (3*1 = 3), then we just left out that factor. So if you were concerned about the units, you can now rest assured that things are consistent.


After all this theoretical discussion of acceleration, now it's time to apply it within the context of your games. To use acceleration in programming, here is what you should do.








  1. Create a variable to contain the acceleration. For instance, accel = 2.
  2. Create initial velocity variables for the x and y directions. For instance:



    xmov = 0;
    ymov = 0;

  3. When acceleration should be applied (such as when a certain key is being pressed), modify the speed. For instance:



    xmov += accel;
    ymov += accel;

  4. For every frame, set the new position of the object.



    car._x += xmov;
    car._y += ymov;


ON THE CD
Open up car4.fla from the Chapter04 directory on the CD. This is the next evolutionary step in the chain of car examples given earlier in this chapter. Here, the car starts with a slow initial speed and accelerates when the up arrow key is pressed. (As you might expect, when the down arrow key is pressed, the car decelerates.) Here is the ActionScript that accomplishes this.


1 xmov = 1;
2 ymov = 1;
3 accel = 2;
4 angle = Math.atan2(ymov, xmov)*180/Math.PI;
5 car._rotation = angle;
6 _root.onEnterFrame =function () {
7 if(Key.isDown(Key.UP)) {
8 xmov += accel;
9 ymov += accel;
10 } else if (Key.isDown(Key.DOWN)) {
11 xmov -= accel;
12 ymov -= accel;
13 }
14 car._x += xmov;
15 car._y += ymov;
16 }

Line 3 initializes the acceleration variable. Other than that, the only differences between this example and car3.fla are in lines 7�13. That's where the ActionScript dictates that if the up arrow key is pressed, then the xmov and ymov variables are increased by the value of the accel variable. If the down arrow key is pressed, then the xmov and ymov variables are decreased by the value of the accel variable.







No comments: