Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Racing game, Actionscript 3, Flash and Game development.

Finally it’s time to start talking about a real Artificial Intelligence algorithm. As said, I won’t use waypoints because I want to focus on “real” artificial intelligence, I want to make cars drive like if they were controlled by a player.

The idea

Let’s imagine you are driving a car, you aren’t blind so you can see the track.

If you see the track has a left turn, you turn left.

If you see the track has a right turn, you turn right.

You always accelerate, unless you see the turn is sharp

The code

This is how I made: the car has a line of sight like the one developed for the survival horror prototype.

This means is have i lines of sight subdivided in j segments.

Every line of sight can be done with all j segments, if it never hits the track boundaries, or with a number n from 0 and j-1 if it hits the track boundaries while drawing the n-th segment.

When I have a line of sight made by j or n segments, I have to determine if this line is on the left or on the right side of the car. This can be easily done because if I have ilines, all lines < i/2 will be on the left and the remaining ones will be on the right.

Now I have the number of segments before I hit track boundaries and I know if it’s on the left or on the right side of the car.

I increase a variable called turn_left by the number of segments if the line is on the left side, or I decrease it if the line is on the right side.

In the ideal situation, when no lines hit track boundaries, turn_left is zero and the car continues straight.

If turn_left is positive, I should turn left, if it’s negative I should turn right, but only if the absolute value is greater than a certain tolerance.

I don’t want my car to turn left and right just because a single line of sight hit the track boundaries.

Same thing for the acceleration: I do not accelerate only if the absolute value of turn_left is greater than a certain tolerance.

Let’s translate it into AS3:

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	public class car_mc extends Sprite {
		public var acceleration:Number=0.4;
		public var speed_decay:Number=0.96;
		public var rotation_step:Number=15;
		public var max_speed:Number=10;
		public var back_speed:Number=1;
		public var speed:Number=0;
		// defining the angle of sight in degrees
		public var angle_of_sight:Number=90;
		// this is just a graphical representation of the line of sight
		public var line_of_sight:Sprite = new Sprite();
		// this is the accuracy: the higher, the better, the slower the simulation
		public var sight_accuracy:int=15;
		// this is the lenght of sight
		public var sight_lenght:int=100;
		// this is the number of steps required to complete the lenght of sight
		public var sight_steps:int=20;
		// this is the turning tolerance
		public var turn_tolerance:int=10;
		public function car_mc(posx:int,posy:int):void {
			addChild(line_of_sight);
			line_of_sight.graphics.lineStyle(1,0x000000);
			line_of_sight.graphics.lineTo(100,100);
			x=posx;
			y=posy;
			addEventListener(Event.ENTER_FRAME,on_enter_frame);
		}
		public function on_enter_frame(e:Event):void {
			var angle_step:Number=angle_of_sight*2/sight_accuracy;
			var sight_point:Point;
			var global_sight_point:Point;
			var par:racing=this.parent as racing;
			// variable to hold line of sight collision results
			var turn_left:int=0;
			// variable to determine if the car is colliding with the ground
			var colliding:Boolean=false;
			line_of_sight.graphics.clear();
			line_of_sight.graphics.lineStyle(1,0x000000);
			for (var i:int=0; i<=sight_accuracy; i++) {
				for (var j:int=1; j<=sight_steps; j++) {
					line_of_sight.graphics.moveTo(0,-15);
					sight_point= new Point(sight_lenght/sight_steps*j*Math.cos((-90-angle_of_sight+angle_step*i)*0.0174532925),sight_lenght/sight_steps*j*Math.sin((-90-angle_of_sight+angle_step*i)*0.0174532925));
					global_sight_point=localToGlobal(sight_point);
					if (par.ground.hitTestPoint(global_sight_point.x,global_sight_point.y,true)) {
						// leaving the loop if the j-th segment of the i-th line of sight
						break;
					}
				}
				// if the line of sight is on the left, add the number of segments to turn_left variable
				if (iturn_tolerance) {
					if (turn_left>0) {
						rotation -= rotation_step*(speed/max_speed);
					} else {
						rotation += rotation_step*(speed/max_speed);
					}
				}
			}
			if (Math.abs(speed)>0.3) {
				speed*=speed_decay;
			} else {
				speed=0;
			}
		}
	}
}

And this is the result:

As you can see, playing with rotation_step, angle_of_sight, sight_accuracy, sight_lenght, sight_steps and turn_tolerance you can have the car run by itself along the track.

The code is way to be perfect, and I know there are some cases it won’t work (but I won’t tell you when :))… anyway if you want to try it by yourself, just copy this new script into car_mc class you can find at step 1.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.