Tutorial Info

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.

Table of Contents:

Step 1: Car movement

Step 2: Collisions

Step 3: Laps and Timing

Step 4: Final Graphic Touches

Step Info

Next Below: In this part of the tutorial you will learn about collisions.

Not collisions with other cars (not yet) but collisions with the track.

Flash Racing Game Tutorial - Part I Car Movement & Collisions - Step 2

Download racing_part1_step2.fla

1. We all know why collisions are important in a Racing Game... Because we don't want the car to leave the track, because we want to force the player to use a specific way, because we want him/her to avoid collisions in order to get the best time (or win the race).

Collisions are a very important part of a racing game and 70% of the game feeling and success depends on good collisions.

We don't want the car to get stuck in the non accessible areas (NAA), we don't want it to lose all speed although it hardly touches those areas and we definitely don't want it to bounce back (by reversing the speed).

In other words we don't want to give the player a hard time, but on the contrary, an enjoyable game. So when the car touches the NAA we must try to correct it's trajectory and of course apply a speed penalty depending on the angle of collision and collision duration.

2. Open the racing_part1_step2.fla file provided with this tutorial.

3. Before we go back to the "step" function, I will explain how the collisions will work.

Using four points to detect collisions

As you can see in the attached picture, we will pick four points, one on every side of the car and check to see if any of them "touches" the NAA.

For example if the Left Side Point is inside the NAA (hits the NAA) then we will have to apply a speed penalty and increase the angle (_rotation) of the car. Why do we do that? Because of what we discussed earlier: we must try to correct the car's trajectory. So what we do here is force the car to steer right.

OK, I guess everything is clear up to this point. And since we are speaking of points, let's see how we calculate their coordinates. To simplify things we will take the Left Side Point as an example.

When the car's rotation is 0 our job is very simple: the LSP coordinates are x=car._x-20 (20 pixels to the left of the car's center point) and y=car._y

But the car will not always have an angle of 0. Well, here comes the tricky part. There are a few ways to calculate the four points even if the angle is not 0 (for example you can use the sine and the cosine functions) and for this tutorial I chose the simple way (I don't know if it's the optimum way, but it's very simple):

We define the Left Side Point as if the car's rotation was 0:

car.pointLeft = {x:-20, y:0}; //this is an Object

and then we transform the point's coordinated from local (related to the car's clip) to global (related to the _root clip where we will test the collisions):

car.localToGlobal(car.pointLeft);

Now we have our Left Side Point coordinates that we can use to check the collision:

car.pointLeft.x and car.pointLeft.y

Can it get any simpler? :)

4. And again back to our Actions Window. Click on the first frame of the "actions" layer and if the Actions Window is not open press F9 to display it.

You will notice that I added a few lines to the "step" function and you probably already know what those lines do :) but still I will go into a few details.

//the collisions //define the four collision points _root["car"+who].pointLeft = {x:-20, y:0};
_root["car"+who].localToGlobal(_root["car"+who].pointLeft);
_root["car"+who].pointRight = {x:20, y:0};
_root["car"+who].localToGlobal(_root["car"+who].pointRight);
_root["car"+who].pointFront = {x:0, y:-25};
_root["car"+who].localToGlobal(_root["car"+who].pointFront);
_root["car"+who].pointBack = {x:0, y:25};
_root["car"+who].localToGlobal(_root["car"+who].pointBack);
//let's use some shorter variable names :) - this is just for better understanding and to simplify the code this["lpx"+who] = _root["car"+who].pointLeft.x;
this["lpy"+who] = _root["car"+who].pointLeft.y;
this["rpx"+who] = _root["car"+who].pointRight.x;
this["rpy"+who] = _root["car"+who].pointRight.y;
this["fpx"+who] = _root["car"+who].pointFront.x;
this["fpy"+who] = _root["car"+who].pointFront.y;
this["bpx"+who] = _root["car"+who].pointBack.x;
this["bpy"+who] = _root["car"+who].pointBack.y;
//check for collisions - we check the collisions using the Flash built in hitTest method. This methods can be used to compare the x and y coordinates to the shape or bounding box of the specified instance (in our case _root.terrain), according to the shape flag (the third parameter: true-shape / false - bounding box) setting or to check if the bounding boxes of the target and the specified instance overlap. We use the first one. if (_root.terrain.hitTest(this["lpx"+who], this["lpy"+who], true)){
//steer right _root["car"+who]._rotation += 5; //speed penalty this["speed"+who] *= 0.85;
}
if (_root.terrain.hitTest(this["rpx"+who], this["rpy"+who], true)){
//steer left _root["car"+who]._rotation -= 5; //speed penalty this["speed"+who] *= 0.85;
}
if (_root.terrain.hitTest(this["fpx"+who], this["fpy"+who], true)){
//stop the car this["speed"+who] = -1;
}
if (_root.terrain.hitTest(this["bpx"+who], this["bpy"+who], true)){
//stop the car this["speed"+who] = 1;
}

Hard? Not so hard :) And the next two steps are even simpler.

« Previous Step   Next Step »
© Witchhut LLC All Rights Reserved