**Level:** Beginner / Intermediate

**Flash Version:** MX, MX 2004

**Total Time:** 1 & 1/2 Hours

**Description:** This is a "time trial" racing game tutorial. After completing it, you will be able to make your own racing game with custom tracks and cars, smooth collisions, lap records and more.

**Next Below:** During step 1 of the Racing Game Tutorial you will learn about car movement.

In other words you will learn how to simulate acceleration, speed, steering, breaking and moving backwards (reverse).

That's it. Let's go on with the tutorial.

Download racing_part1_step1.fla

**1.** Car movement is not the most difficult part of a racing game, but if you want to simulate realistic (almost realistic) movement you have to take in consideration some of the aspects described below.

**2.** Open the **racing_part1_step1.fla** file provided with this tutorial.

**3.** Click on the first frame (the only frame) of the "defs" layer and press F9 to display the Actions Window for this frame. Now let's see what these variables do:

car1.code = "player"; //this variable will decide if the specified car is controlled by a human player or by the computer (in Part II of this tutorial you will learn how to add opponents and this variable will come in handy)

acceleration = 0.4; //the acceleration variable will add to the speed variable on every enterFrame event (in this case 24 times per second); a higher value translates in a faster acceleration of the car

speedDecay = 0.96; //when the car is not accelerated (the UP Key is released), the car will have to slow down smoothly; the speed will multiply with this value (less than 1); the lower this value is, the faster the car will slow down

rotationStep = 10;//this is the number of degrees that will increase or decrease the car's rotation (angle) when the left or right keys are pressed

maxSpeed = 10;//this is the speed limit on our track; increase it if you want the car to go faster

backSpeed = 1;//this is the speed limit when going backwards

acceleration = 0.4; //the acceleration variable will add to the speed variable on every enterFrame event (in this case 24 times per second); a higher value translates in a faster acceleration of the car

speedDecay = 0.96; //when the car is not accelerated (the UP Key is released), the car will have to slow down smoothly; the speed will multiply with this value (less than 1); the lower this value is, the faster the car will slow down

rotationStep = 10;//this is the number of degrees that will increase or decrease the car's rotation (angle) when the left or right keys are pressed

maxSpeed = 10;//this is the speed limit on our track; increase it if you want the car to go faster

backSpeed = 1;//this is the speed limit when going backwards

**4.** OK! Now let's get back to school :) and see what we can do with these variables.

Click on the first frame of the second layer ("actions") and if the Actions windows is not open, press F9 to display it.

We will discuss this script in a few moments, but first let's see how Flash "understands" movement and coordinates.

**Just a bit of trigonometry and Flash**

Flash is using the classic Cartesian Coordinate System (a grid based system with a horizontal axis OX and a vertical axis OY).

You notice in the attached picture that in Flash the Y axis is inverted meaning that the negative side of the Y axis is positioned higher than the positive side. So the lower a coordinate is, the higher it's value will be.

Because Flash understand only horizontal and vertical vectors we will have to calculate the horizontal and the vertical components of the actual "speed".

So, from trigonometry we know (in this case) that:

*sin(angle) = speedx/speed * and

*cos(angle) = speedy/speed *

so... we know the angle (angle=car._rotation) and we know the speed. That's all we need know. Is it? No. You need to know one more thing:

The Math class implemented in Macromedia Flash does not work with angles measured in degrees. Instead we will have to provide angles measured in radians (an alternative unit measurement for angles).

The only case in which you will use degrees is when actually rotating the movieclips.

Using the simple equation below you will be able to transform degrees into radians:

angle_radians = angle_degrees * (PI/180)

Now we can easily calculate the X and Y components of the car's speed:

speedx = Math.sin(_rotation*(Math.PI/180))*speed;

speedy = Math.cos(_rotation*(Math.PI/180))*speed*-1;

speedy = Math.cos(_rotation*(Math.PI/180))*speed*-1;

Well, you already figured out why the sign of the Y component has to be inverted ;)

And now let's get back to Flash and our Actions Window. Next I will explain what the "step" function is all about. The "step" function will be executed on every enterFrame event (on the "stepper" layer you will find an empty movieclip the executes the onClipEvent (enterFrame) routine).

function step(who) {

//check to see if the car in question is controlled by the player or by the computer

if (_root["car"+who].code == "player") {

if (_root["car"+who].code == "player") {

//we will constantly decrease speed by multiplying it with a number below 1, but only if speed if higher than 0.3; a lower value will only consume resources and movement will not even be noticed so we will set the speed variable to 0

if (this["speed"+who]>0.3) {

//the car will react to certain key presses that we will capture using the Key.isDown method as follows

//accelerate - we add a certain value to the speed variable if the UP key is pressed and the speed is lower than it's maximum alowed value

if (Key.isDown(Key.UP) && this["speed"+who]<_root.maxSpeed) {

//brake (reverse) - same thing, but here we subtract

if (Key.isDown(Key.DOWN)) {

//steer left - well, we could simply add or subtract a fixed angle (in degrees) to/from the car's rotation, but that's not good enough. In order to simulate a natural movement, steering must depend on speed, otherwise you will be able to rotate your car even if it's almost stopped and it will look like a propeller :)

if (Key.isDown(Key.LEFT) && this["speed"+who]>0.3) {

//steer right - you already know what happens here

if (Key.isDown(Key.RIGHT) && this["speed"+who]>0.3) {

this["rotation"+who] = _root["car"+who]._rotation;

//we calculate the two components of speed (X axis and Y axis) - we have already discussed this part of the function above

this["speedx"+who] = Math.sin(this["rotation"+who]*(Math.PI/180))*this["speed"+who];

this["speedy"+who] = Math.cos(this["rotation"+who]*(Math.PI/180))*this["speed"+who]*-1;

//apply the components on the actual position of the car - we add the X component of the speed to the X coordinate of the car and the Y component of the speed to the Y coordinate

_root["car"+who]._x += this["speedx"+who];

_root["car"+who]._y += this["speedy"+who];

//position the shadow of the car - when the car steers, we want the shadow to keep it X and Y coordinates and always stay on one side of the car (whatever side that would be)

_root["shadow"+who]._x = _root["car"+who]._x-4;

_root["shadow"+who]._y = _root["car"+who]._y+2;

_root["shadow"+who]._rotation = _root["car"+who]._rotation;

}

if (this["speed"+who]>0.3) {

this["speed"+who] *= _root.speedDecay;

} else { this["speed"+who] = 0;

}//the car will react to certain key presses that we will capture using the Key.isDown method as follows

//accelerate - we add a certain value to the speed variable if the UP key is pressed and the speed is lower than it's maximum alowed value

if (Key.isDown(Key.UP) && this["speed"+who]<_root.maxSpeed) {

this["speed"+who] += _root.acceleration;

}//brake (reverse) - same thing, but here we subtract

if (Key.isDown(Key.DOWN)) {

this["speed"+who] -= _root.backSpeed;

}//steer left - well, we could simply add or subtract a fixed angle (in degrees) to/from the car's rotation, but that's not good enough. In order to simulate a natural movement, steering must depend on speed, otherwise you will be able to rotate your car even if it's almost stopped and it will look like a propeller :)

if (Key.isDown(Key.LEFT) && this["speed"+who]>0.3) {

_root["car"+who]._rotation -= _root.rotationStep*(this["speed"+who]/_root.maxSpeed);

}//steer right - you already know what happens here

if (Key.isDown(Key.RIGHT) && this["speed"+who]>0.3) {

_root["car"+who]._rotation += _root.rotationStep*(this["speed"+who]/_root.maxSpeed);

}this["rotation"+who] = _root["car"+who]._rotation;

//we calculate the two components of speed (X axis and Y axis) - we have already discussed this part of the function above

this["speedx"+who] = Math.sin(this["rotation"+who]*(Math.PI/180))*this["speed"+who];

this["speedy"+who] = Math.cos(this["rotation"+who]*(Math.PI/180))*this["speed"+who]*-1;

//apply the components on the actual position of the car - we add the X component of the speed to the X coordinate of the car and the Y component of the speed to the Y coordinate

_root["car"+who]._x += this["speedx"+who];

_root["car"+who]._y += this["speedy"+who];

//position the shadow of the car - when the car steers, we want the shadow to keep it X and Y coordinates and always stay on one side of the car (whatever side that would be)

_root["shadow"+who]._x = _root["car"+who]._x-4;

_root["shadow"+who]._y = _root["car"+who]._y+2;

_root["shadow"+who]._rotation = _root["car"+who]._rotation;

}

if (_root["car"+who].code == "computer") {

}
//in our next tutorial "Racing Game Part II" we will add opponents to make the game more dynamic and interactive

}That's it! We already have a moving car. Now we can move on to collisions.

© Witchhut LLC All Rights Reserved