Building a Simple Driving Game with ActionScript 3.0

In this tutorial I'll be going through the steps needed to build a simple driving program. You'll learn how to add keyListeners, eventListeners and a couple of other things using ActionScript 3.0. I originally wrote this program in ActionScript 2.0 and in this tutorial I'll compare the two ActionScript versions as we go along. This should therefore make for an easy tutorial to start moving your way over to ActionScript 3.0.




Step 1: Setting Up the File

Open up a new Flash ActionScript 3.0 document, go to the Properties window (if it's not open go to Window > Properties) and click edit. Change the FPS to 50, the width to 1200px and the height to 800px.

In the timeline window (Window > Timeline) create two more layers, so there are three in total, then name the three: actions, speed, car. Lock the actions layer.

Step 2: Importing the Car Images

In the source files you'll find these three files:

Select the car layer and go to File > Import > Import to Stage and import the carStraight image.

Step 3: Making the Car MovieClip

Select the image and press F8, or Modify > Convert to Symbol. Leave all the settings as their defaults (top-left justified and a movieclip) and name it carMC.

Give the movieclip an instance name of carMC in the Properties window.

Double-click the image, or Rightclick > Edit. Select the image of the car and give it the coordinates x:-100, y:-230.

These can be changed to your liking, but I thought that these seemed to work the best and made the car turns look the most realistic.

Create two more keyframes after the current one.

Select the second keyframe, delete the image of the car and go to File > Import > Import to Stage and import the carLeft image. Then position it at -100,-230.

Do the same thing for the third keyframe and import the carRight image. Position that at -100,-230 as well.

Go into the actions of each keyframe (select the keyframe and hit F9 or Rightclick > Actions) and type in:

stop(); 

Now double-click anywhere where there is nothing, or click on Scene 1 in the top left, to go back to the main artboard.

Because the car is so large compared to the stage, select the carMC and change its width to 100px and height to 189px. This scales down all three images, but allows you to bring the size back up if you need to later.

Next, select the carMC and center it on the stage using the align window.

So far we've set the file up, made a movieclip with three frames, each with an image in it and a stop(); command.

Step 3: Adding the Speedometer

When controlling the car there'll be an indicator on the screen telling you how fast it is going.

Grab the text tool and in your Properties panel (Window > Properties) make sure it says Dynamic Text, not Static or Input Text. Click anywhere on the artboard, where you would want the speedometer to be placed (I chose bottom left) and click. This should make a text box that is about 100 px wide. If it doesn't, or if this isn't wide enough, you can adjust it to a bigger size. Go back to the Properties panel and give the dynamic text and instance name of "speedometer".

Step 4: Taking a Look at all the Code

First I'll give you all the code so you can look over it and then I'll go through it piece by piece explaining it.

var increment:Number = 0; //amount the car moves each frame 
var carRotation:Number = carMC.rotation; //rotation of the car 
var posNeg:Number = 1; 
var acceleration:Number = .05; //acceleration of the car, or the amount increment gets increased by. 
var speed:Number = 0; //the speed of the car that will be displayed on screen 
var maxSpeed:Number = 50; 
//keyboard capture code start 
var keyLeftPressed:Boolean; 
var keyRightPressed:Boolean; 
var keyUpPressed:Boolean; 
var spaceBarPressed:Boolean; 
addEventListener(Event.ENTER_FRAME,onEnterFrameFunction); 
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed); 
stage.addEventListener(KeyboardEvent.KEY_UP,keyReleased); 
//keyboard capture code end 
function onEnterFrameFunction(event:Event)  
//detecting speed 
speed = Math.round((increment)*5); 
speedometer.text = String(speed); 
if ((carMC.rotation  180)&&(carMC.rotation >= 0)) 
carRotation = carMC.rotation; 
posNeg = 1; 
if ((carMC.rotation  0)&&(carMC.rotation > -180)) 
carRotation = -1 * carMC.rotation; 
posNeg = -1; 
//if Right key pressed rotate the car clockwise and change image to carRight 
if (keyRightPressed)  
carMC.rotation += .5*increment; 
carMC.gotoAndStop(3); 
//if Left key pressed rotate the car counterclockwise and change image to carLeft 
if (keyLeftPressed)  
carMC.rotation -= .5*increment; 
carMC.gotoAndStop(2); 
//if neither Left or Right key pressed change image to carStraight 
if (!keyLeftPressed && !keyRightPressed)  
carMC.gotoAndStop(1); 
//When up key is pressed. 
if (keyUpPressed)  
carMC.y -= ((90-carRotation)/90)*increment; 
if (((carMC.rotation > 90)&&(carMC.rotation  180))||((carMC.rotation  -90)&&(carMC.rotation > -180)))  
carMC.x += posNeg * (((((1-(carRotation/360))*360)-180)/90)*increment); 
if (((carMC.rotation  90)&&(carMC.rotation > 0))||((carMC.rotation >= -90)&&(carMC.rotation  -1)))  
carMC.x += posNeg * ((carRotation)/90)*increment; 
if (spaceBarPressed)  
increment -= .5*acceleration; 
if (!spaceBarPressed && speed  maxSpeed)  
increment += acceleration; 
else  
if (increment > 0 && spaceBarPressed)  
carMC.y -= ((90-carRotation)/90)*increment; 
if (((carMC.rotation > 90)&&(carMC.rotation  180))||((carMC.rotation  -90)&&(carMC.rotation > -180)))  
carMC.x += posNeg * (((((1-(carRotation/360))*360)-180)/90)*increment); 
if (((carMC.rotation  90)&&(carMC.rotation > 0))||((carMC.rotation >= -90)&&(carMC.rotation  -1)))  
carMC.x += posNeg * ((carRotation)/90)*increment; 
increment -= 4*acceleration; 
else if (increment > 0)  
carMC.y -= ((90-carRotation)/90)*increment; 
if (((carMC.rotation > 90)&&(carMC.rotation  180))||((carMC.rotation  -90)&&(carMC.rotation > -180)))  
carMC.x += posNeg * (((((1-(carRotation/360))*360)-180)/90)*increment); 
if (((carMC.rotation  90)&&(carMC.rotation > 0))||((carMC.rotation >= -90)&&(carMC.rotation  -1)))  
carMC.x += posNeg * ((carRotation)/90)*increment; 
increment -= 1.5*acceleration; 
else 
increment = 0; 
function keyPressed(event:KeyboardEvent)  
if (event.keyCode == Keyboard.LEFT) 
keyLeftPressed = true; 
if (event.keyCode == Keyboard.RIGHT) 
keyRightPressed = true; 
if (event.keyCode == Keyboard.UP) 
keyUpPressed = true; 
if (event.keyCode == Keyboard.SPACE) 
spaceBarPressed = true; 
function keyReleased(event:KeyboardEvent)  
if (event.keyCode == Keyboard.LEFT) 
keyLeftPressed = false; 
if (event.keyCode == Keyboard.RIGHT) 
keyRightPressed = false; 
if (event.keyCode == Keyboard.UP) 
keyUpPressed = false; 
if (event.keyCode == Keyboard.SPACE) 
spaceBarPressed = false; 

Step 5: Adding Variables

Click on the first frame of the actions layer that you locked earlier and press F9 (or Right click > Actions). Add the code in here.

These are the variables we will need.

var increment:Number = 0; //amount the car moves each frame 
var carRotation:Number = carMC.rotation; //rotation of the car 
var posNeg:Number = 1; 
var acceleration:Number = .05; //acceleration of the car, or the amount increment gets increased by. 
var speed:Number = 0; //the speed of the car that will be displayed on screen 
var maxSpeed:Number = 50; //The max speed the car can travel 

Step 6: Listening for Keypresses

The explanations are all here, except posNeg which I'll explain later.

var keyLeftPressed:Boolean; 
var keyRightPressed:Boolean; 
var keyUpPressed:Boolean; 
var spaceBarPressed:Boolean; 
addEventListener(Event.ENTER_FRAME,onEnterFrameFunction); 
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed); 
stage.addEventListener(KeyboardEvent.KEY_UP,keyReleased); 

When moving over to AS3 this was one of the more confusing parts for me. In AS2 creating functions to be called was much easier to code. You would usually just have an "if" statement inside an onEnterFrame function that looked to see if _____ key was down. In AS3 there is a way to do this similarly, but it doesn't work well with games. The movements aren't smooth and you cannot press two keys at a time.

I did it here with booleans. For my game I'm only looking to see if four keys are pressed: Up, Left, Right, and Space, so I created a boolean for each of them. I then added three listeners.

addEventListener(Event.ENTER_FRAME,onEnterFrameFunction);\ 

This code is pretty much equivalent to onEnterFrame. On every frame (so in our case 50 times a second) it performs the function onEnterFrameFunction. The reason being because it will allow us to continually update variables, like speed, whilst also checking if a key has been pressed (which it does indirectly through a boolean, as you'll see in a second).

stage.addEventListener(KeyboardEvent.KEY_DOWN,keyPressed); 
stage.addEventListener(KeyboardEvent.KEY_UP,keyReleased); 

These are two listeners that are added to the stage. What they do is when a key (any key) is pressed, the function keyPressed gets called. When a key is released, the function keyReleased is called.

function keyPressed(event:KeyboardEvent)  
if (event.keyCode == Keyboard.LEFT) 
keyLeftPressed = true; 
if (event.keyCode == Keyboard.RIGHT) 
keyRightPressed = true; 
if (event.keyCode == Keyboard.UP) 
keyUpPressed = true; 
if (event.keyCode == Keyboard.SPACE) 
spaceBarPressed = true; 
function keyReleased(event:KeyboardEvent)  
if (event.keyCode == Keyboard.LEFT) 
keyLeftPressed = false; 
if (event.keyCode == Keyboard.RIGHT) 
keyRightPressed = false; 
if (event.keyCode == Keyboard.UP) 
keyUpPressed = false; 
if (event.keyCode == Keyboard.SPACE) 
spaceBarPressed = false; 

This code comes at the end of my code, but I am explaining it now because it concerns key presses.

These are the two functions keyPressed and keyReleased. Like I said above, when a key is pressed keyPressed gets called. It checks the four "if" statements to see if the key pressed is any of the four keys my program is looking for. If the key is one of them, it sets the boolean of that key to true.

What keyReleased does is the opposite. When a key is released it checks to see if it is one of the four keys. Should this be the case, it will set the boolean of that key back to false.

Step 7: Understanding How Moving the Car Works

If we were coding a game where hitting the left key moved the car in the -x direction, and hitting the up key moved the car in the +y direction, things would be much simpler. This program is different. As there is no built in function in Flash which will move the car forward based on its current direction, we must create it ourselves. While making this code I had to do a lot of trial and error and I found that working backwards helped the most. I knew that when the card was facing N, or 0 degrees, it should move in the +x direction at full speed. Then should it be facing NE, or 45 degrees, it would move in the +x direction at half speed, and in the +y direction at half speed.

Step 8: Adding onEnterFrame Function

First we'll add the onEnterFrame function. Like I said above, this function will be called on every frame.

function onEnterFrameFunction(event:Event)