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):
car

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):
(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

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):
(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

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):

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

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.

Posted on August 2nd, 2009
Filed under ActionScript 3, Flash, Tutorial |

8 Responses to “The Basic Controls of a Car”

  1. Mushyrulez
    August 3rd, 2009 at 01:21

    Gonna make a racing game next? :P

  2. Rasmus Wriedt Larsen
    August 3rd, 2009 at 11:46

    I haven’t really planned that yet, but I might just do that :)

  3. MichaelJW
    August 5th, 2009 at 03:40

    Cool!

    Hahaha I loved this part: “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?”

  4. rocketman
    September 12th, 2009 at 20:39

    http://www.bit-101.com/blog/?p=910

    Enter frame and timers are basically the same. Dont be fooled :)

  5. Respect
    November 2nd, 2009 at 08:15

    “The rotation should depend on the speed, right now it can turn while speed = 0.”

    Force of rotation is called Torque.

    wiki
    http://en.wikipedia.org/wiki/Torque

  6. JimE
    January 8th, 2010 at 22:43

    Very good stuff.

    Interestingly if you have rotated the car at all even just once … then move the car forward and backward … there is like a minuscule drift perhaps one pixel to the left. Always seems to be to the left and never to the right. And if you have not ever rotated the car it does not seem to occur .. ?

    Any ideas ?

  7. Rasmus Wriedt Larsen
    January 8th, 2010 at 23:45

    Hi JimE

    Thanks a lot, that is very nice spotted. I will get right to it :)

  8. JimE
    January 9th, 2010 at 03:19

    I had dropped it into a parking game I have been working on and while parking my car I kept moving out of the parking space is only way I caught it. :)

    Thought for a little while was the beer but was only like noon and had not had one today so figured I would check it out here too…!

Leave a Reply