The Basic Controls of a Car
So here we are, this time we are gotta make the basic controls of a car.
I started off by making a car (surprise?), I made it a movieclip and called the instance “car” (there isn’t going to be any explanation about how to do that, if you can’t do this please read the ‘8 way character movement‘ tutorial I made):
So make a new ActionScript class, I made one called MainCar, I don’t really think that needs explanation? Anyway, let it extend MovieClip, this car is going to be keyboard controlled, so lets make some variables and event listeners for that:
public var leftIsPressed = false; public var rightIsPressed = false; public var upIsPressed = false; public var downIsPressed = false; public function MainCar() { stage.addEventListener(KeyboardEvent.KEY_DOWN, atKeyDown); stage.addEventListener(KeyboardEvent.KEY_UP, atKeyUp); } |
Lets make some event handlers for them as well:
function atKeyDown(event:KeyboardEvent) { if ( event.keyCode == 37 || event.keyCode == 65 ) { leftIsPressed = true; } if ( event.keyCode ==38 || event.keyCode == 87 ) { upIsPressed = true; } if ( event.keyCode == 39 || event.keyCode == 68 ) { rightIsPressed = true; } if ( event.keyCode == 40 || event.keyCode == 83 ) { downIsPressed = true; } } function atKeyUp(event:KeyboardEvent) { if ( event.keyCode == 37 || event.keyCode == 65 ) { leftIsPressed = false; } if ( event.keyCode == 38 || event.keyCode == 87 ) { upIsPressed = false; } if ( event.keyCode == 39 || event.keyCode == 68 ) { rightIsPressed = false; } if ( event.keyCode == 40 || event.keyCode == 83 ) { downIsPressed = false; } } |
The keyCodes I’ve used is:
- 37: left arrow key
- 38: up arrow key
- 39: right arrow key
- 40: down arrow key
- 65: A
- 67: D
- 83: S
- 87: W
All we need now is the master loop of the whole thing. Lets start by making the event listener, add this to the constructor function:
stage.addEventListener(Event.ENTER_FRAME, masterLoop); |
WOW, argh? WTF? Did he just use a ENTER_FRAME event listener? Didn’t this guy read that frame based code sucks or doesn’t he understand the game loop?
Well yes, but this is not a tutorial on how to handle any of those problem, I just want to make a smooth animation for my lovely little car. So let’s continue with that shall we? lets add the master loop:
function masterLoop(even:Event):void { if (leftIsPressed) { car.rotation -= 2; } if (rightIsPressed) { car.rotation += 2; } if (upIsPressed) { speed += acceleration; } if (downIsPressed) { speed -= acceleration; } if (speed > maxSpeed) { speed = maxSpeed; } else if ( speed < maxReverse) { speed = maxReverse; } var direction:Number = car.rotation * Math.PI / 180 var xSpeed:Number = Math.cos(direction) * speed; var ySpeed:Number = Math.sin(direction) * speed; car.x += xSpeed; car.y += ySpeed; } |
Whenever we push left and right we will alter the rotation of the car. When we push up and down we will alter the speed by the acceleration. The speed determins how far we go each tick of the master loop. Of course we also need to add the other variables:
public var speed:Number = 0; public var acceleration:Number = 0.2; public var maxSpeed:Number = 20; public var maxReverse:Number = -8; |
also remember to import these:
import flash.display.MovieClip; import flash.events.Event; import flash.events.KeyboardEvent; |
If you do all this and test it you will get something like this (Click to activate):
So it’s getting there, but there are still some problems:
- There is no friction.
- The rotation should depend on the speed, right now it can turn while speed = 0.
The friction part is very easy to add, just add this variable in the beginning:
var friction:Number = 0.95 |
and add this to the loop:
if (speed < acceleration && speed > -acceleration) { speed = 0; } speed = speed * friction; |
The first part checks if the speed is very slow, and if it is the speed should be 0.
We’ll handle our rotation problem like this:
var carRotation:Number = (speed/maxSpeed)*rotSpeed if (leftIsPressed) { car.rotation -= carRotation; } if (rightIsPressed) { car.rotation += carRotation; } |
This will make the current rotation-speed depend on the current speed of the car, so when the car isn’t moving you won’t be able to turn it, and when we’re going fast we can turn very fast – and of course we also need to add the rotSpeed variable at the top:
public var rotSpeed:Number = 15; |
Lets test it (Click to activate):
So now we fixed our problems, but we created a new one:
The car has a very low max speed.
This is caused by this line:
speed = speed * friction; |
When the speed reaches 4 and goes though this line it will become 3.8, which in next tick will be increased to 4 by the acceleration and thereby decreased to 3.8 when it reaches the friction line. We just created an eternal loop – not good! Lets fix it:
add this variable:
public var extraAcceleration:Number = 0.05; |
and change your up and down keys in the loop to this:
if (upIsPressed) { speed += acceleration; if (speed > 0) { speed += extraAcceleration * speed; } } if (downIsPressed) { speed -= acceleration; if (speed < 0) { speed += extraAcceleration * speed; } } |
The reason I only want to add speed while the speed is positive is that else it would make the car go a little backwards. The extraAcceleration as is positive multiplied by speed which is negative would make a negative number. The same goes for reversing.
So we’re finished for now, yay :D Check out the final version below (Click to activate):
You might want to try and change some of the values, these are just some I made up and are not perfect!
I also made a ZIP file for you if you want the source files.