Getting Cars To Follow A Track


Imerion

Member
Joined
Feb 24, 2005
Messages
218
I am currently working on an overhead Micro Machines-style racer for GP2X and Dreamcast. However, I can't get AI-cars to work well. I was thinking about using points on the track which the ai-cars would follow. Simply checking for the next point, rotate the car towards it and make it go there. But it wont work. Also, the cars will not make a smooth turn. I might be able to fix that though. But what I wonder is, how to I make the cars follow points set on the map? This is my current code : I have a process called aicar which will do that.

Code:
program racer ;



global

rot;
col;
acc;
lap;
lc=1;
armor;
endrace;
anim;
finish;
finish2;
rot2;
acc2;
armor2;
second=0;
lc2;
lap2;
endrace2;
spa;
point=0;
pointx;
pointy;

begin

timer=0;
set_mode(640,480,8);
load_fpg("scroll.fpg");

coll();
goal();
check();
arm();
arm2();
car(160,120);
aicar(160,160);
lamp(747,250);
lamp(282,250);
lamp(748,488);
lamp(282,488);

end



process car(x,y)
begin
graph=2;
z=1;
start_scroll(0,0,3,0,0,0);
scroll.camera=id;
ctype=c_scroll;
write_int(0,160,20,0,&lap);
write_int(0,160,40,0,&second);

loop

    frame;

    timer++;

    if (timer>100)
      timer=0;
      second++;
    end



    if (rot==360000)
      rot=0;
    end

    if (rot==-360000)
      rot=0;
    end

    angle=rot;


    if (key(_control))
      acc=acc+2;
      if (acc>14)
        acc=14;
      end
    end

    if (acc>0)
      acc=acc-1;
      advance(acc);
      if(COLLISION(type coll));
        advance(-acc-6);
        armor=armor+1;
        spark(x,y,1,rot);
        spark(x,y,2,rot);
        spark(x,y,3,rot);
        spark(x,y,4,rot);
      end
    end

    if (key(_right))
      rot=rot-5000;
      if(COLLISION(type coll));
        rot=rot+7000;
      end

      if(COLLISION(type coll));
        advance(-acc-6);
        armor=armor+1;
        spark(x,y,1,rot);
        spark(x,y,2,rot);
        spark(x,y,3,rot);
        spark(x,y,4,rot);
      end
    end



    if (key(_left))
      rot=rot+5000;
      if(COLLISION(type coll));
        rot=rot-7000;
      end

      if(COLLISION(type coll));
        advance(-acc-6);
        armor=armor+1;
        spark(x,y,1,rot);
        spark(x,y,2,rot);
        spark(x,y,3,rot);
        spark(x,y,4,rot);
      end
    end



    if(COLLISION(type goal));
      if (lc==1)
        lap=lap+1;
        lc=2;
      end
    end

    

    if(COLLISION(type check));
        lc=1;
    end

    
    if (armor>15 and endrace==0)
      explode(x,y);
      endrace=1;
      break;
    end

    
    if (lap==5)
      finish=1;
      break;
    end


end
end



process aicar(x,y)
begin
graph=2;
ctype=c_scroll;
loop



frame;
get_point(0,3,point,&x,&y);
end
end



process coll();
begin
z=2;
ctype=c_scroll;
x=512;
y=384;
graph=3;
loop
frame;
end
end

process goal();
begin
z=2;
ctype=c_scroll;
x=500;
y=150;
graph=1;
loop
frame;
end
end


process check();
begin
ctype=c_scroll;
x=505;
y=595;
graph=4;
loop
frame;
end
end


process lamp(x,y);
begin
ctype=c_scroll;
flags=4;
graph=5;
loop
frame;
end
end


process explode(x,y);
begin
anim=0;
ctype=c_scroll;
repeat

 graph=6+anim;
 anim=anim+1;
 frame;
until (anim==9)
end

process arm();
begin
graph=16;
y=0;
loop
x=-10*armor;
frame;
end
end


process arm2();
begin
graph=17;
y=0;
x=0;
loop
frame;
end
end


process spark(x,y,t,ang);
begin
graph=19;
angle=ang;
advance(24);
spa=0;
repeat
spa=spa+1;

if (t==1)
x=x+4;
y=y+4;
end

if (t==2)
x=x+4;
y=y-4;
end

if (t==3)
x=x-4;
y=y+4;
end

if (t==4)
x=x-4;
y=y-4;
end

frame;
until (spa==30)
end


Any help with that is appreciated. If you want to test it, the graphicsfile can be found here : http://www.freewebtown.com/Imerion/racer.fpg
Please note that most of that graphics is temporal and will be replaced with better looking stuff.
 
Imerion posted on Mar 23 2006 at 12:43 AM said:
I am currently working on an overhead Micro Machines-style racer for GP2X and Dreamcast. However, I can't get AI-cars to work well. I was thinking about using points on the track which the ai-cars would follow. Simply checking for the next point, rotate the car towards it and make it go there. But it wont work. Also, the cars will not make a smooth turn. I might be able to fix that though. But what I wonder is, how to I make the cars follow points set on the map? This is my current code : I have a process called aicar which will do that.

For good tracking there are lots of possible methods... For quick fix you might consider just adding more checkpoints so AI wouldn't be getting lost so easily.

For smoother turning you will have to add more sophisticated physical model to your cars. An inertia effect for rotational movement is mandatory if you want to have smooth turning.
 
Last edited by a moderator:
Easiest way is to make an array of points the car has to drive through, and then let the AI car follow those. I felt frisky so I wrote a small AI car.

Add this to the globals section:
Code:
struct checkpoints[3]
  int x;
  int y;
end
lastCheckpoint = 3;

Add this in the initiation part before you call all the processes.
Code:
//Set checkpoints
checkpoints[0].x = 850;
checkpoints[0].y = 150;
checkpoints[1].x = 850;
checkpoints[1].y = 600;
checkpoints[2].x = 200;
checkpoints[2].y = 600;
checkpoints[3].x = 200;
checkpoints[3].y = 150;

The process:
Code:
process aiCar(x,y)

private
  int nextCheckpoint;
  int lapsToGo = 5;
  int carSpeed;
  int lapCheck;

  //Maximum speeds
  int cornerSpeed = 8;
  int straightSpeed = 14;
  //Minimum distance to the checkpoint to move to the next one
  int minRadius = 30;

begin
  graph=2;
  ctype=c_scroll;

  while(lapsToGo > 0)

    angle = near_angle(angle,fget_angle(x,y,checkpoints[nextCheckpoint].x,checkpoints[nextCheckpoint].y),5000);

    if(angle == fget_angle(x,y,checkpoints[nextCheckpoint].x,checkpoints[nextCheckpoint].y))
      //Current angle equals the angle towards the next checkpoint, so it's straight ahead in front of the car.
      if(carSpeed < straightSpeed)
        carSpeed += 2;
      end
    else
      //Not yet pointing in the correct direction, so cornering speed is the max.
      if(carSpeed < cornerSpeed)
        carSpeed += 2;
      else
        carSpeed--;
      end
    end

    //Checkpoints
    if(fget_dist(x,y,checkpoints[nextCheckpoint].x,checkpoints[nextCheckpoint].y) < minRadius)
      //Near enough to a checkpoint, so go to the next one.
      nextCheckpoint++;
      if(nextCheckpoint > lastCheckpoint)
        nextCheckpoint = 0;
      end
    end


    //Laps code
    if(collision(type goal) and lapCheck)
      lapCheck = false;
      lapsToGo--;
    end
    if(collision(type check))
      lapCheck = true;
    end


    carSpeed--;
    advance(carSpeed);

    frame;
  end

  //Finished driving 5 laps.
end

Hope this gets you going, if not, feel free to ask.
 
Thanks a lot. Ill try it next time ill work on the game. Since Im making this game to learn, this is perfect. I managed to do a working routine myself, but this is a lot better.
 
Imerion posted on Mar 24 2006 at 06:25 PM said:
Thanks a lot. Ill try it next time ill work on the game. Since Im making this game to learn, this is perfect. I managed to do a working routine myself, but this is a lot better.
frankly, i think it's a bit ambitious for a first game. start with simple things where making the game fun, and making some computer opponent (if needed) is easy...

making a racegame is indeed a fun project, but the collision can be tricky, the handling of the cars can be hard to make it feel good, and a good ai is also pretty hard...

i ofcourse wish you good luck on the project, i've had quite some troubles writing an AI for my scorched GP game, just going over all possibilities was way too slow, and calculating a shot was also pretty hard (with wind, obstacles, ...), but after some trying i ended up with a decent AI :)
 
Last edited by a moderator:
Its not really my first Fenix-game. I made Istappen and Vanguard Wars before this one. But I feel I can do this. I noticed collision-detection was hard, but it works quite fine now. (On the version on my HD that is). I also did manage to implement a car following points. But looking at Moogle's routine made my realize I missed a few things. So Ill use that one instead. Or use parts from it. Its cleaner and nicer. :)
 
Back
Top