///Flash Race Car Tutorial

Flash Race Car Tutorial

Making a car

I’ll leave all of the making the car fun up to you. Design it however
you want. Mine is going to be a rectangle. Not very aerodynamic, but it
will do the trick. Be sure to set the Actionscript Class name of the
car to “Racecar” and check the “Export for Actionscript” box in the Properties menu.

Start your engines

The first step is to set up the car’s controls. To allow keyboard buttons to control the car, we need to create a KeyListener object. The KeyListener catches key press and release events similar to the way Flash Button object catches the mouse press and release events. When a key is pressed or released the KeyListener
will see that event and show us what key the action happened on. We
will program the listener to only pay attention to the arrow keys and
call the appropriate function on our car when one is pressed or
released.

We are setting up the KeyListener to alert us when the control keys are pressed and when they are released. For instance, when the UP arrow key is pressed, the car will accelerate until it is release. By listening for both the Press action and the Release action we will be able to control the car. I won’t bore you too much with all of the details of how the KeyListener works. Instead I’ll throw you the code and let you see it yourself.

Sidenote:
When I’m debugging KeyListeners, I usually put trace statements in my code to make sure the right functions are linked to the right keys. Add trace statements when you are first writing up the code to save yourself a lot of headaches.

// Create key listener
var keyListener:Object = new Object();
keyListener.onKeyDown = function () {
switch ( Key.getCode() ) {
case Key.UP:
_root.mainCar.ForwardOn();
break;
case Key.DOWN:
_root.mainCar.ReverseOn();
break;
case Key.RIGHT:
_root.mainCar.RightTurnOn();
break;
case Key.LEFT:
_root.mainCar.LeftTurnOn();
break;
}
}
keyListener.onKeyUp = function () {
switch ( Key.getCode() ) {
case Key.UP:
_root.mainCar.ForwardOff();
break;
case Key.DOWN:
_root.mainCar.ReverseOff();
break;
case Key.RIGHT:
_root.mainCar.RightTurnOff();
break;
case Key.LEFT:
_root.mainCar.LeftTurnOff();
break;
}
}
Key.addListener(keyListener);

Let’s burn some rubber

Now that we have a car and some controls, let’s get that car moving!

To run everything, we will be writing (or copying) the Racecar Class. Everything the car does will be controlled by this class.

To start out, I’m going to just throw a bunch of code at you. This code sets up the Racecar class as an extension of the MovieClip class. All we are doing here is setting a bunch of variables to be used later and defining the functions we used in the KeyListener earlier.

class Racecar extends MovieClip {

private static var MASS_CONST:Number = 10;
private static var MIN_SPIN:Number = 1;
private static var MAX_TORQUE:Number = 1;

private var maxaccel:Number; // px. per frame. squared
private var drag:Number; // ratio
private var turnRadius:Number; // px

private var _turn:Number; // 1, 0, -1
private var _accel:Number; // 1, 0, -1
private var vel:flash.geom.Point; // px. per frame
private var heading:Number; // radians
private var spin:Number; // radians per frame

// Initialize all the car variables
function Racecar() {
// car characteristics
this.maxaccel = 1;
this.turnRadius = 100;
this.drag = 0.05;

// state info
this.vel = new flash.geom.Point(0, 0);
this.heading = 0;
this.spin = 0;
this._accel = 0;
this._turn = 0;

this.onEnterFrame = Update;
}

// Updates car state
private function Update() {
// *** We'll discuss this function later
}

/// - - - - - - - - - - - - - - ///
/// CAR CONTROL FUNCTIONS ///
/// - - - - - - - - - - - - - - ///

// Forward and reverse
public function ForwardOn() {
this._accel = 1;
}
public function ForwardOff() {
this._accel = 0;
}
public function ReverseOn() {
this._accel = -1;
}
public function ReverseOff() {
this._accel = 0;
}

// Left and right turn
public function RightTurnOn() {
this._turn = 1;
}
public function RightTurnOff() {
this._turn = 0;
}
public function LeftTurnOn() {
this._turn = -1;
}
public function LeftTurnOff() {
this._turn = 0;
}

}

As you can see, the control functions are pretty simple. They just set the _accel and _turn
variables. Rather than bore you with the details of this chunk of code,
I wanted to jump straight into the most important part, the Update function. If there is anything here that is confusing to you, or that you’d like explained, feel free to post a comment or send me an email. Hopefully it will all make sense once you see the full code. Each part of the Update function will be explained in detail. Hopefully I don’t bore you to death.

The first step is to get the car’s heading in radians. All of the Math functions in Flash use radians, but the _rotation property is in degrees.

// get the heading
this.heading = Math.PI / 180 * this._rotation;

The next thing we’ll do is update the car’s velocity. First, I apply
drag to the car. If the car is not accelerating it will slowly come to
a stop. The larger the value of drag, the faster the car loses speed. It only takes a little drag to slow the car down, so don’t set that value too high.

Also, if the car is accelerating, we increase the velocity in the direction it is pointing. The sin and cos of the car’s heading calculates how much of the acceleration should be applied to the x and y direction. The _accel is set by the car control functions and determines whether we are accelerating forward or reverse. The maxaccel
variable is how fast the car accelerates. Again, a small value goes a
long way here. Set this too high and your car will shoot off the
screen. The most important thing is to get your + and - signs right. Otherwise the car will have some interesting behavior.

// Add drag
this.vel.x *= (1 - this.drag);
this.vel.y *= (1 - this.drag);

// Add acceleration
this.vel.x += Math.sin( this.heading ) * this._accel * this.maxaccel;
this.vel.y -= Math.cos( this.heading ) * this._accel * this.maxaccel;

The trickiest part of this code is getting the car to turn. A car
turns based on how fast it is moving. If it isn’t moving at all, it
isn’t going to turn. The faster you go, the faster it turns. We’ll have
to calculate how fast the car turns based on how fast it is moving.

Real cars can turn at varying rates depending on how much you crank
the steering wheel. To simplify things, this car will only turn at a
fixed rate. We “turn” the car by changing its rotation. Based on the
speed of the car and the direction it is turning, we’ll rotate it. Here
is the code that does it. Notice the turnRadius variable. The smaller this number is, the sharper the turn the car will make.

		
var velMag:Number = Math.sqrt(this.vel.x * this.vel.x + this.vel.y * this.vel.y);
this.spin = velMag / this.turnRadius * this._turn;
var newHeading:Number = this.heading + this.spin;

Just pointing the car in the right direction isn’t enough, though.
We also have to change it’s velocity to match. I’ve added an additional
feature that allows the car to spin-out if it is turning too fast.

First we calculate how much the velocity will change to get the car
moving in the direction it is pointed. I’m calling this value torque.
Next we check the magnitude of this torque against a maximum value. If
it is greater than the maximum torque allowed, we limit it. This
results in the car spinning out. And finally we modify the velocity by
the torque.

If you don’t want your car to spin out, simply remove the code in the if statement or set MAX_TORQUE very high.

// calculate torque (turning the car changes the direction it travels)
var torque:flash.geom.Point = new flash.geom.Point(0,0);
torque.x = Math.sin(newHeading) * velMag - this.vel.x;
torque.y = -Math.cos(newHeading) * velMag - this.vel.y;
var torqueMag = Math.sqrt(Math.pow(torque.x,2) + Math.pow(torque.y,2));

// limit torque, so the car will "spin out" if turning too fast
if (torqueMag > MAX_TORQUE) {
torque.x = MAX_TORQUE * torque.x / torqueMag;
torque.y = MAX_TORQUE * torque.y / torqueMag;
}

// apply torque to velocity
this.vel.x += torque.x;
this.vel.y += torque.y;

And finally we update the car’s position and heading. Not much here, we just set the _x, _y, and _rotation values based on the calculations above.

// update position and heading
this._x += this.vel.x;
this._y += this.vel.y;
this.heading = newHeading;
this._rotation = this.heading * 180 / Math.PI;

And there you have it! A keyboard controlled car of your very own.
It might not be as cool as that remote control car that the neighbor
has, but this one never runs out of batteries.

Keyboard Controlled Racecar

The Flash plugin is required to view this example.

Feel free to download the full project and play around with the
Actionscript files. The best way to learn this stuff is to jump in and
experiment, so go for it. I hope you found this tutorial helpful.

2010-05-25T22:49:14+00:00 December 15th, 2007|Flash|0 Comments

About the Author:

 

Leave A Comment