Simple AI Vehicle AIWheeledVehicle
by Brian Richardson · 08/16/2004 (10:19 pm) · 46 comments
Download Code File
This would not be possible without Badguy's getSteeringAngle function!
Code archive mirrored here:
http://knowhere.net/gg/aiwheeledvehicle.zip
Steps:
1. Add AIWheeledVehicle.cc and AIWheeledVehicle.h to your torque project.
Copy the files to the engine/game/vehicle directory.
2. In Vehicle.h:
After:
void renderMountedImage(SceneState *state, ShapeImageRenderImage *image);
But before:
public:
Add this line:
virtual bool getAIMove(Move* move);
The full block should look like this:
3. In Vehicle.cc:
In Vehicle::ProcessTick after:
Add (this is equivalent to the code in player.cc):
At the end of the file, add this block:
4. Recompile the engine.
5. Copy the bot.cs into the server/scripts/ directory of your game.
Add this line to server/scripts/game.cs:
6. Finally, to create the bot, add this line to your onMissionLoaded function
in server/scripts/game.cs:
TrackPath is the name of a path you've created with the mission editor. See the
bot path finding tutorial listed in the link above for info on how to create that.
Hope this helps!
Brian Richardson
This would not be possible without Badguy's getSteeringAngle function!
Code archive mirrored here:
http://knowhere.net/gg/aiwheeledvehicle.zip
Steps:
1. Add AIWheeledVehicle.cc and AIWheeledVehicle.h to your torque project.
Copy the files to the engine/game/vehicle directory.
2. In Vehicle.h:
After:
void renderMountedImage(SceneState *state, ShapeImageRenderImage *image);
But before:
public:
Add this line:
virtual bool getAIMove(Move* move);
The full block should look like this:
void renderMountedImage(SceneState *state, ShapeImageRenderImage *image); virtual bool getAIMove(Move* move); public:
3. In Vehicle.cc:
In Vehicle::ProcessTick after:
Parent::ProcessTick(move);
Add (this is equivalent to the code in player.cc):
// If we're not being controlled by a client, let the
// AI sub-module get a chance at producing a move.
Move aiMove(NullMove);
if (!move && isServerObject() && getAIMove(&aiMove))
move = &aiMove; At the end of the file, add this block:
//
// AI stuff
bool Vehicle::getAIMove(Move* move)
{
return false;
}4. Recompile the engine.
5. Copy the bot.cs into the server/scripts/ directory of your game.
Add this line to server/scripts/game.cs:
exec("./bot.cs");6. Finally, to create the bot, add this line to your onMissionLoaded function
in server/scripts/game.cs:
$Bot = CreateAIWheeledVehicle("MasterBlaster", "MissionGroup/TrackPath");TrackPath is the name of a path you've created with the mission editor. See the
bot path finding tutorial listed in the link above for info on how to create that.
Hope this helps!
Brian Richardson
About the author
#2
It might help to mention that the DefaultCar in your bot.cs (line 6) needs to be referred to in the file for the vehicle. I am using buggy.cs from the 'vehicle setup' tutorial at http://www.codesampler.com/torque.htm) and I just changed the 'DefaultBuggy' to 'DefaultCar' in there (about line 110):
//Datablock to describe the vehicle itself
datablock WheeledVehicleData( DefaultCar ) //was 'DefaultBuggy'
Thanks again Brian.
08/10/2004 (6:41 am)
Excellent Brian. Thanks a lot for this!It might help to mention that the DefaultCar in your bot.cs (line 6) needs to be referred to in the file for the vehicle. I am using buggy.cs from the 'vehicle setup' tutorial at http://www.codesampler.com/torque.htm) and I just changed the 'DefaultBuggy' to 'DefaultCar' in there (about line 110):
//Datablock to describe the vehicle itself
datablock WheeledVehicleData( DefaultCar ) //was 'DefaultBuggy'
Thanks again Brian.
#3
08/16/2004 (11:28 pm)
WOO! YOU ROCK! Eric was bugging me to get Car AI into Produce Panic :D
#4
08/17/2004 (3:53 am)
Awesome! Maybe this could be added to head and then update the racing demo with some bots?
#5
08/20/2004 (7:12 am)
This is great! exaclty what i was looking, but not quite :) You see i want this same logic applied to the flyingvehicle class. I have a plane that i want to follow a path and do tricks but not be client controlled. Do you know how i will be able to apply the same logic to change the flyingvehicle class to make it ai controlled. any other resources would be great too! thanks
#6
08/21/2004 (8:04 pm)
Looks fantastic! I'll have to check it out
#7
08/23/2004 (10:04 pm)
Anyone have any idea why adding this to the racing starter pack or changing the player's character into a vehicle (like in codesampler's tutorial for it) would crash Torque during loading the mission? I can't seem to get it to work when the player is a vehicle. Otherwise it works fine with multiple bots. The console doesn't throw any exceptions or errors, just crashes with windows default "program has caused an error and must close" dialog box.
#8
I hope this is helpful!
@Kuni:
There's a thread here about
Flying Vehicle AI. That's where I got the getSteeringAngle function from Badguy. You basically just need to
create a getPitchAngle function that does the same thing as getSteeringAngle does on a different axis. You maybe
able to generalize getSteeringAngle to do both. I'm making a racer, so I haven't looked at doing that. ;)
@Scott:
I'm testing with starter.racing and my player is a vehicle. So it should work. Maybe there's a bad
datablock definition or something?
08/24/2004 (7:57 am)
@All: I hope this is helpful!
@Kuni:
There's a thread here about
Flying Vehicle AI. That's where I got the getSteeringAngle function from Badguy. You basically just need to
create a getPitchAngle function that does the same thing as getSteeringAngle does on a different axis. You maybe
able to generalize getSteeringAngle to do both. I'm making a racer, so I haven't looked at doing that. ;)
@Scott:
I'm testing with starter.racing and my player is a vehicle. So it should work. Maybe there's a bad
datablock definition or something?
#9
How did you add the script portions into the starter.racing and get it to work? Replace the game.cs in starter.racing with the one included in the rar? (which I haven't tried yet) I'm using Head as of this 8/22/04.
08/25/2004 (9:20 am)
@Brian:How did you add the script portions into the starter.racing and get it to work? Replace the game.cs in starter.racing with the one included in the rar? (which I haven't tried yet) I'm using Head as of this 8/22/04.
#10
Yeah, you should be able to just dump the game.cs into starter.racing. I've made a few unrelated changes/fixes, but it should be ok.
08/25/2004 (9:37 am)
@Scott:Yeah, you should be able to just dump the game.cs into starter.racing. I've made a few unrelated changes/fixes, but it should be ok.
#11
How would I add a function to it to reverse the direction for a given number of miliseconds. Like myAIVehicle.driveBackwards(%miliseconds)? I really need this functionality to try to shake them loose if they get stuck.
I also want to be able to control the jet trigger trough scripts. I managed to let them shoot, now I want them to also jet, but I don't know how to adress that trigger (3) trough scripts. Should I add another function to the engine code for this? Or is it accesible already trough scripts?
09/03/2004 (3:35 am)
I have a question about adding stuff to this code, so I think its best to ask them here.How would I add a function to it to reverse the direction for a given number of miliseconds. Like myAIVehicle.driveBackwards(%miliseconds)? I really need this functionality to try to shake them loose if they get stuck.
I also want to be able to control the jet trigger trough scripts. I managed to let them shoot, now I want them to also jet, but I don't know how to adress that trigger (3) trough scripts. Should I add another function to the engine code for this? Or is it accesible already trough scripts?
#12
It'd be simple to add the ability to go backwards. Look for two lines that look like this in AIWheeledVehicle.cc:
movePtr->y = value; // (location.y > mMoveDestination.y)? -value : value;
If value is negative, the car will go backwards. You could expose a function to script to allow the car to go backwards. I just needed forward motion for now.
I'd imagine that jetting would be similiar to firing. I haven't looked at it yet. I hope to be back on my racer soon so I can run into these problems! Let me know when you find out the solution to that.
09/03/2004 (6:24 am)
@Ward:It'd be simple to add the ability to go backwards. Look for two lines that look like this in AIWheeledVehicle.cc:
movePtr->y = value; // (location.y > mMoveDestination.y)? -value : value;
If value is negative, the car will go backwards. You could expose a function to script to allow the car to go backwards. I just needed forward motion for now.
I'd imagine that jetting would be similiar to firing. I haven't looked at it yet. I hope to be back on my racer soon so I can run into these problems! Let me know when you find out the solution to that.
#13
First of all, I'd need to have a bool value to keep track if the direction is inverted, right. Then I need to add a function to invert this boolean, and this needs to be exposed to the scripts.
And about the jetting, there's a boolean mJetting in wheeledVehicle, so I think one could just expose a function that sets this value to true...
Can someone please help me?
09/03/2004 (1:34 pm)
Hmmz, this should be easy, but I hardly ever touch the engine code. How exactly would I do this... I tried, but i get compile errors and I don't really see what i could be doing wrong.First of all, I'd need to have a bool value to keep track if the direction is inverted, right. Then I need to add a function to invert this boolean, and this needs to be exposed to the scripts.
And about the jetting, there's a boolean mJetting in wheeledVehicle, so I think one could just expose a function that sets this value to true...
Can someone please help me?
#14
10/31/2004 (11:03 am)
I was wondering if anyone attempted to write some code so the vehicle slow down on sharp turns, I know this is a common problem in a race game im working on. The bots are unable to make the turn and crash. I edited this code a bit and think i found a way to fix the problem, but i don't think its the best way to approach this problem. The code i wrote basicly performs some checks and if it detects the bot is not making the turn it slows it down by X much. I'd rather write up some forumla to basicly predict the best speed for the turn, but this is some complex phsyics that i've been having a hard time to get working.
#15
11/10/2004 (9:06 pm)
I was having problems with this code and i noticed this hunk of code.... i took it out and it basicly fixed all the problems... it does some strange things If you miss the path it starts changing the movePtr x and y values, while this will realign a person, it wont work for a vehicle so i basicly just cut it out and it works 100 times better...// Build move direction in world space
if (isZero(xDiff))
movePtr->y = (location.y > mMoveDestination.y)? -1 : 1;
else
if (isZero(yDiff))
movePtr->x = (location.x > mMoveDestination.x)? -1 : 1;
else
if (mFabs(xDiff) > mFabs(yDiff)) {
F32 value = mFabs(yDiff / xDiff);
movePtr->y = value; // (location.y > mMoveDestination.y)? -value : value;
movePtr->x = (location.x > mMoveDestination.x)? -1 : 1;
}
else {
F32 value = mFabs(xDiff / yDiff);
movePtr->x = (location.x > mMoveDestination.x)? -value : value;
movePtr->y = 1; // (location.y > mMoveDestination.y)? -1 : 1;
}
// Rotate the move into object space (this really only needs
// a 2D matrix)
Point3F newMove;
MatrixF moveMatrix;
moveMatrix.set(EulerF(0, 0, -(rotation.z + movePtr->yaw)));
moveMatrix.mulV( Point3F( movePtr->x, movePtr->y, 0 ), &newMove );
movePtr->x = newMove.x;
movePtr->y = newMove.y;
#16
Yep, you're right there's a huge chunk of code in there which should be ripped out. I've been meaning to update the resource with a much simplfied version of getAIMove. It seems like you've figured this out, but to anyone else reading this: The basic idea behind the car's move is the movePtr->x is the steering value, and movePtr->y is the throttle. So you could get away with movePtr->x = getSteeringValue(); and movePtr->y = 1;
After you take out that confusing block of code in the middle that XoClutch pasted up, it becomes easier to visualize what to do if you want to control the speed based on turning angle, or distance to target, etc..
I'll try to post the new resource code up tonight.
11/11/2004 (8:49 am)
@XoClutch;Yep, you're right there's a huge chunk of code in there which should be ripped out. I've been meaning to update the resource with a much simplfied version of getAIMove. It seems like you've figured this out, but to anyone else reading this: The basic idea behind the car's move is the movePtr->x is the steering value, and movePtr->y is the throttle. So you could get away with movePtr->x = getSteeringValue(); and movePtr->y = 1;
After you take out that confusing block of code in the middle that XoClutch pasted up, it becomes easier to visualize what to do if you want to control the speed based on turning angle, or distance to target, etc..
I'll try to post the new resource code up tonight.
#17
Well y is the throttle, but yaw is current set to steer the car... i've messed around with x, But with vehicle i don't think it effects anything... i could be wrong tho.
Here is what i changed the GetAIMove Function too, it seems to work much better.
11/11/2004 (9:32 am)
@brian;Well y is the throttle, but yaw is current set to steer the car... i've messed around with x, But with vehicle i don't think it effects anything... i could be wrong tho.
Here is what i changed the GetAIMove Function too, it seems to work much better.
bool AIWheeledVehicle::getAIMove(Move *movePtr)
{
*movePtr = NullMove;
if (!mDisableMove)
{
// Use the eye as the current position.
MatrixF eye;
getEyeTransform(&eye);
Point3F location = getPosition();
Point4F rotation;
getTransform().getColumn(1, &rotation);
// Orient towards our destination.
if (mMoveState == ModeMove || mMoveState == ModeReverse)
{
movePtr->yaw = getSteeringAngle();
}
// Move towards the destination
if (mMoveState == ModeMove)
{
F32 xDiff = mMoveDestination.x - location.x;
F32 yDiff = mMoveDestination.y - location.y;
movePtr->y = 1;
// Check if we should mMove, or if we are 'close enough'
if (mFabs(xDiff) < mMoveTolerance && mFabs(yDiff) < mMoveTolerance) {
mMoveState = ModeStop;
throwCallback("onReachDestination");
}
// Set movement speed. We'll slow down once we get close
// to try and stop on the spot...
if (mMoveSlowdown)
{
F32 speed = mMoveSpeed;
F32 dist = mSqrt(xDiff*xDiff + yDiff*yDiff);
F32 maxDist = 5;
if (dist < maxDist)
speed *= dist / maxDist;
movePtr->y *= speed;
}
else
{
movePtr->y *= mMoveSpeed;
}
}
else if(mMoveState == ModeReverse)
{
movePtr->y = -1 * mMoveSpeed;
}
else if(mMoveState == ModeStop)
{
movePtr->y = 0;
}
}
else
{
mRigid.setAtRest();
}
return true;
}
#18
11/11/2004 (9:48 am)
Yeah, yaw! Not x, thanks for correcting that! I'll update the resource tonight!
#19
i am just a newbie and get it not to work.
I have the new Synapse Lighting Pack that is packed together with tge 1.3 so i do not bring them together by myself.
But there is no racing starter kit, only the fps starter kit is there.
So can i use your code together with the Lighting pack and the fps starter kit?
If yes, what must i do besides your description wich i have followed true?
I have done what you wrote but it will not work.
I have tryed some other things that do not work also bit want not to mention them now becouse maybe it is better you discribe shortly what i must do after i have done what you wrote above.
(I have the files here from the codesampler vehicle tutorial, maybe this can help.
The vehicle setup codesampler tutorial and the bot pathfinding tutorial are working today.)
Thank you
Mathias
01/18/2005 (12:19 pm)
Sorry,i am just a newbie and get it not to work.
I have the new Synapse Lighting Pack that is packed together with tge 1.3 so i do not bring them together by myself.
But there is no racing starter kit, only the fps starter kit is there.
So can i use your code together with the Lighting pack and the fps starter kit?
If yes, what must i do besides your description wich i have followed true?
I have done what you wrote but it will not work.
I have tryed some other things that do not work also bit want not to mention them now becouse maybe it is better you discribe shortly what i must do after i have done what you wrote above.
(I have the files here from the codesampler vehicle tutorial, maybe this can help.
The vehicle setup codesampler tutorial and the bot pathfinding tutorial are working today.)
Thank you
Mathias
#20
It appears that the server runs through its list of updatePos() calls in its processTick(), then the client does and then the server picks up right where it left off. Only problem is, the client side processing moved the vehicle farther down the road so on the first call on the server side again, the car gets reset to its last position according to the server's info.
How would I resolve this?
03/23/2005 (11:58 am)
I am seeing an issue where the car seems to hiccup as it drives.It appears that the server runs through its list of updatePos() calls in its processTick(), then the client does and then the server picks up right where it left off. Only problem is, the client side processing moved the vehicle farther down the road so on the first call on the server side again, the car gets reset to its last position according to the server's info.
How would I resolve this?

Torque Owner Sam3d
$Bot.followPath("MissionGroup/TrackPath",-1);
Thanks Brian.