Create a Flash racing game tutorial – Artificial intelligence
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 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 (i<sight_accuracy/2) { turn_left+=j; } else { // if the line of sight is on the right, add the number of segments to turn_left variable turn_left-=j; } line_of_sight.graphics.lineTo(sight_point.x,sight_point.y); } // accelerate if turn_left is smaller than turn_tolerance*2 if (speed<max_speed&&Math.abs(turn_left)<turn_tolerance*2) { speed+=acceleration; } var speed_x:Number=Math.sin(rotation*0.0174532925)*speed; var speed_y:Number=- Math.cos(rotation*0.0174532925)*speed; y+=speed_y; x+=speed_x; var point_left:Point=new Point(-9,0); var point_right:Point=new Point(9,0); var point_front:Point=new Point(0,-13); var point_back:Point=new Point(0,13); point_left=localToGlobal(point_left); point_right=localToGlobal(point_right); point_front=localToGlobal(point_front); point_back=localToGlobal(point_back); // car versus track boundaries collision management if (par.ground.hitTestPoint(point_left.x,point_left.y,true)&&par.ground.hitTestPoint(point_front.x,point_front.y,true)) { rotation+=5; speed*=0.85; colliding=true; } if (par.ground.hitTestPoint(point_right.x,point_right.y,true)&&par.ground.hitTestPoint(point_front.x,point_front.y,true)) { rotation-=5; speed*=0.85; colliding=true; } if (par.ground.hitTestPoint(point_front.x,point_front.y,true)) { speed*=0.55; colliding=true; } if (par.ground.hitTestPoint(point_back.x,point_back.y,true)) { speed*=0.55; colliding=true; } if (! colliding) { // turn left or right according to tolerance and turn_left value if the car is not colliding with track boundaries if (Math.abs(turn_left)>turn_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.
They can be easily customized to meet the unique requirements of your project.















(33 votes, average: 4.73 out of 5)









This post has 31 comments
Kaustav
That is quite awesome.
Kaustav
If a little CPU expensive…=)
szataniol
Majority of AI algorithms use some extra data, like waypoints or terrain map. The fact you are not using it doesn’t mean you do it better or more real. As a matter of fact your approach creates only limits.
It is much more cpu consuming.
You can’t determine wheter you’re going wrong way.
You can’t tell how much distance you have left to the finish line or other cars.
You can’t store any extra data like sensors, weapon pickup points, different types of terrain, shortcuts and so on.
Artificial Intelligence NEED that kind of stuff. All you can do with this approach is car blindly going forward. If you would like to implement anything more complex and sophisticated you’ll get stuck.
Cheers,
szataniol
Ozren
You rule !!
Emanuele Feronato
terrain map is the next feature I am going to develop. With line of sight, I can avoid other cars too.
pablopp
szataniol, why are you so concerned about this? As far as I understand, those experiments are not meant to end up as a real game, Emanuele is just trying out some interesting approaches, or am I missing the point here?
Og2t
@pablopp Exactly!
I like the experiment and idea, I’d use getObjectsUnderPoint instead of using hitTest and physical lines though. That way it could be used in conjunction with different tiles (terrain map approach).
Keep it going Emanuele!
elthing
Szataniol, it looks like you’re little bit jealous. Try to stick to your own job. Maybe use some glue ;)
Monkios
In intelligence there is the possibility of error.
This is awesome but it’s not AI.
szataniol
I’m sorry if you percive my post like this. I just wanted to point that waypoints are inevitable if you are thinking about more complex AI. Sorry if anyone feel offended.
Jacob
I gotta say your a pretty smart cookie. That was a genius idea. So it’s not the AI we usually see. It def is a form of artificial intelligence.
Kaustav
On the other hand, waypoints have their problems too.
What if the terrain gets changed (new road/blockages)? If there are oil slicks or mines or any other fancy traps?
Waypoints are predictable, which causes problems with playability. If weapons are added, AIs have to move out of their path to shoot the player, then what happens?
Emanuele Feronato
Anyway Szataniol is right, you MUST use waypoints in some cases (just think about a track with a “8″ shape) unless you don’t want to flag (and permanently save) every mistake CPU car makes in order to have a more and more accurate driving model… too much for just a Flash game.
I could try a waypoint approach in conjunction with line of sight.
Thomas
I’d like to see this optimised to take the fastest line. Can it be done in any way so it always hits the apex of the curve? Then you’ve got the perfect AI – so, it’s a challenge for you, to prove you can beat waypoints! (Then you have to add imperfections, hooray.)
Robert
hey how is the road created..i cant find insid the sourvce..no movieclip or code that creates it
Robert
and how can i change the graphics in the movieclips??
Robert
nevermind…library was jsut messing up
Cornelius
How are you calling your packages? I’ve tried to look at the source fla file, but I get an “Unexpected file error” when I attempt to open it.
szataniol
@Kaustav – Waypoints doesn’t necessarily have to be x,y points. For example in a racing game the best approach I’ve seen is using convex sectors which consists of few x,y points, that allow you to precisely tell where is the car and what steps should it take next. You should check out this book:
http://www.aiwisdom.com/bookshelf_aiwisdom.html
I can honestly recommend it to anyone who’s interested in artificial intelligence for games.
Cheers
szataniol
Straffehond
Love this. I wonder what the car does if the road splits ip. Will it go lefty, righty, or will it crash?
Robert
jsut tested it..you can do figure 8 tracs..it works great to…they dont get mixed up
Weekly Digest for July 11th — Hello. My name is Václav Van?ura.
[...] Create a Flash racing game tutorial – Artificial intelligence – Emanuele Feronato [...]
suresh
hi admin,
i like this script, i want to create racing car game for user view the track into the car , please give tutorials.
thanks,
suresh
jose
too perfect the car’s trayectory no errors no little desviations look like it had a train track
Neru Tu Kaze
Finally, Something that might will work as a heat tracing/targeting/homing missile!!! It was not what i where looking for right now. But this will work on my other project that i almost gave up, thanks!… I might be able to do some more stuff with this too :D …External code,AS 3.0 …Everything that i need ;D
Thank you so much!, i have no idea how much time i’ve used trying to find a code that is in AS 3.0 and that works!
Ivan
Looks intelligent alrighty! :D
Dmillos
HI Emanuele, nice test, I really liked how it looks in the end, I made a very similar test a couple of months ago and it turned out pretty nice as well, in the end I had to add a couple of points so that the car would know which way to go in case he crashed or something, you can check it out here if you want:
http://impudia.blogspot.com/search/label/Project%20Schumacher
anyways, thanks for the blog, it is really cool
-Daniel
amarnath
fantastic
amarnath
fantastic….simply superb
Jay
How do I use this I dont know, When I download the step 1, then try to open the .fla file it wont open it says ‘unexpected file format’. Therefore how can i use the AI on my other racing game. Please help me I really need it.
Cássio
The aproach used here is interesting, but you should try out something like neural networks, I developed one that could navigate well with only 3 “lines of sight” (I call them sensors)