Game Development Community

Adding Z Co-Ord to AIPlayer::getAIMove

by Kimberly Unger · in Torque Game Engine · 06/03/2004 (6:56 am) · 68 replies

I need to add vertical (z-coordinate) to getAIMove. What I need is someplace that explains the algorithm (math) used in the function. Can anyone out there point me to somewhere that has this information?

Kim's Programmer Jim
#41
07/18/2004 (7:53 am)
Ok. Located Badguys thread that contains a working dts model. I'll proceed on. :)
#42
07/22/2004 (1:01 pm)
Ok. Here is the link to the zipped up files needed. Read the aiFlight.doc for instructions. I'll await feedback here before I offer as a resource to GG.

Thanks to all whose efforts made it possible.

Enjoy
#43
07/22/2004 (7:52 pm)
Trying it out.. I got a compile error on mDistanceFactor, but the initial results are VERY promising! YAY wendell! saviour of the seven seas of the future!
#44
07/23/2004 (3:23 am)
Humm. Sounds like flyingVehicle.h doesn't have these lines exposing the variable at line 117 of the modified .h
public:
   F32 mDistanceFactor;
private:
Check to see that it is exposed.

There is still lots to do if one wants to use rigid body physics with aiFlying stuff. Flying too fast with the current code (make sure integration is set to 2 or 4) causes all sorts of issues. Maybe one ought to make a lightweight aiClass that doesn't use rigid body physics. That would seem to at least get some controlled if not as realistic components into the game.
#45
07/23/2004 (6:56 am)
I added that myself (with fingers crossed.) :)

I haven't re-integrated the gravity fix, that's my next step.. here's hoping it will still work. The poor warsparrow was desperately trying to climb the banks of the lake and not able to ;)

Sorry, no, there's no mention of mDistanceFactor in the code (*.h)
#46
07/23/2004 (1:51 pm)
Yeah. It was part of the patch process. If you ran the patch file it should have been placed into the .h
#47
07/24/2004 (7:02 am)
I did run the patch process, but I've never run it before.. what I did was type the patch command line, and it came back with no return or no output. Does that mean it didn't actually execute? I wasn't sure.. Since it didn't say "command not found" I thought it had worked

The files are all read-only when you get them from CVS,maybe it couldn't change the file(s) but didn't throw an error?
#48
07/24/2004 (9:38 am)
Hey Wendell!

Really looks cool.

I did a clean-get, ran the patch, and recompiled clean. It's great to see the little guy swoop right in on the campfire, or a tower, or a tree. Seems to work great.

If you input a 2nd move destination after the first he seems to have trouble, tho. He seems to reverse back and not find the heading, get lost at a higher altitude. It seems wherever the first move destination is, he finds it and heads right for it perfectly, but not a 2nd. Is there some reset step I need to put in between move destinations?

I did the clean-get and full compile twice just to be sure. It's VERY promising. I'm going to poke around and see if I can figure out what's going wrong, myself, too.
#49
07/24/2004 (6:38 pm)
Hi Wendell,

Tried it and got to the same place Andrew was before patching. But I have one problem : I have a mac and the patch command won't work.

So could you please tell me what was patched.

TIA
#50
07/25/2004 (4:24 am)
@Bruno - Look at the patch file. It contains everything that needs to change. I'm not hip on walkthroughs as the experience needed to learn a new skill (reading patch files) isn't that hard. There are resources on the net that explain what a patch file is about and how to interpret their chicken scratching, after which even Bruno the great can consider himself a member of the patch file elite. If you really can't find the inform about patch files then I'll see if I can locate info fer ya. It is there, just don't have it bookmarked.

@Andrew - I'll investigate the 2nd move issue. I had my ship get redirected before arrival. I'll admit I didn't think or try a subsequent move after reaching the initial destination. That is why one needs input from others. Thanks. I'll get back soon.
#51
07/25/2004 (6:25 am)
Andrew - replace this function with the code below. Ought to work.

void AIFlyingVehicle::setMoveDestination( const Point3F &location )
{
   mMoveDestination = location;
   mMoveState = ModeMove;
   mAimLocationSet = true;
   mAimLocation = location;
}

Really need to make the code act better if trying to move to something closer by. If the initial momentum is zero and you try to then move to another object closeby it takes forever. Well again, this code isn't supposed to be everything to everyone. My needs don't include that functionality. :)

Edit: .zip file above has been updated for change.
#52
07/25/2004 (11:46 am)
IT WORKS !!!

Thanks Wendell !

I'm going give a deeper look at your code and try to merge it with Badguy's.

In order to help others, I translated the patch file and I'm posting it here
#53
07/25/2004 (11:47 am)
Wendell's Patch file in human language :

Some modifications weren't included since they only contained comments

IN THE ENGINE :

################## In FlyingVehicle.cc

Locate : ( line 32 )
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
 static U32 sClientCollisionMask = sCollisionMoveMask;
 
 static F32 sFlyingVehicleGravity = -20;

replace :
static F32 sFlyingVehicleGravity = 0;

locate : ( line 256 )
FlyingVehicle::FlyingVehicle()
{
   mGenerateShadow = true;

   mSteering.set(0,0);
   mThrottle = 0;
   mJetting = false;

replace :
mJetting = true;

locate : ( line 282 )
bool FlyingVehicle::onAdd()
{
   if(!Parent::onAdd())
      return false;

INSERT :
bool FlyingVehicle::onAdd()
{   
   mDistanceFactor = 1.0f;
   if(!Parent::onAdd())
      return false;

locate : (line 426 )
currPosMat.getColumn(0,&xv);
   currPosMat.getColumn(1,&yv);
   currPosMat.getColumn(2,&zv);
   F32 speed = mRigid.linVelocity.len();

replace :
F32 speed = mRigid.linVelocity.len() * mDistanceFactor;

locate : ( few lines bellow )
// Drag at any speed
   force  -= mRigid.linVelocity * mDataBlock->minDrag;

replace :
F32 slamit = (mDistanceFactor > 1.0) ? 1.0f : 1.0f/(mDistanceFactor*mDistanceFactor+.01);
   slamit = mClampF( slamit, 1.0f, 60.0f);
//      Con::errorf(ConsoleLogEntry::General, "slamit=%f", slamit);
   force  -= mRigid.linVelocity * mDataBlock->minDrag * slamit ;

################## In FlyingVehicle.h

locate : ( line 101 )
class FlyingVehicle: public Vehicle
{
   typedef Vehicle Parent;

   FlyingVehicleData* mDataBlock;

   AUDIOHANDLE mJetSound;
   AUDIOHANDLE mEngineSound;

   enum NetMaskBits {
      InitMask = BIT(0),
      HoverHeight = BIT(1)
   };
   bool createHeightOn;
   F32 mCeilingFactor;

INSERT
public :
	   F32 mDistanceFactor;
private:
#54
07/25/2004 (11:48 am)
IN THE SCRIPTS

################## In /common/server/clientConnection.cs

INSERT ( after the GameConnection::onConnect function )
function GameConnection::onConnectFV( %client, %name )
{
   // Send down the connection error info, the client is
   // responsible for displaying this message if a connection
   // error occures.
   messageClient(%client,'MsgConnectionError',"",$Pref::Server::ConnectionError);

   // Send mission information to the client
   sendLoadInfoToClient( %client );

   // Simulated client lag for testing...
   // %client.setSimulatedNetParams(0.1, 30);

   // if hosting this server, set this client to superAdmin
   if (%client.getAddress() $= "local") {
      %client.isAdmin = true;
      %client.isSuperAdmin = true;
   }

   // Get the client's unique id:
   // %authInfo = %client.getAuthInfo();
   // %client.guid = getField( %authInfo, 3 );
   %client.guid = 0;
   addToServerGuidList( %client.guid );

   // Set admin status
   %client.isAdmin = false;
   %client.isSuperAdmin = false;

   // Save client preferences on the connection object for later use.
   %client.gender = "FV";
   %client.armor = "Fighter";
   %client.race = "Fed";
   %client.skin = addTaggedString( "base" );
   %client.setPlayerName(%name);
   %client.score = 0;

   //
   $instantGroup = ServerGroup;
   $instantGroup = MissionCleanup;
   echo("CADD: " @ %client @ " " @ %client.getAddress());

   // Inform the client of all the other clients
   %count = ClientGroup.getCount();
   for (%cl = 0; %cl < %count; %cl++) {
      %other = ClientGroup.getObject(%cl);
      if ((%other != %client)) {
         // These should be "silent" versions of these messages...
         messageClient(%client, 'MsgClientJoin', "",
               %other.name,
               %other,
               %other.sendGuid,
               %other.score,
               %other.isAIControlled(),
               %other.isAdmin,
               %other.isSuperAdmin);
      }
   }

   // Inform the client we've joined up
   messageClient(%client,
     'MsgClientJoin', '\c2Welcome to the Torque demo app %1.',
      %client.name,
      %client,
      %client.sendGuid,
      %client.score,
      %client.isAiControlled(),
      %client.isAdmin,
      %client.isSuperAdmin);

   // Inform all the other clients of the new guy
   messageAllExcept(%client, -1, 'MsgClientJoin', '\c1%1 joined the game.',
      %client.name,
      %client,
      %client.sendGuid,
      %client.score,
      %client.isAiControlled(),
      %client.isAdmin,
      %client.isSuperAdmin);

   // If the mission is running, go ahead download it to the client
   if ($missionRunning)
      %client.loadMission();
   $Server::PlayerCount++;
}

################## In /(game)/server/scripts/aiPlayer.cs

INSERT the function ( before AIPlayer::spawnOnPath )
function AIFlyingClient::spawnFV()
{
   // An example function which creates a new AIFVPlayer object
   // using the the example WarSparrow datablock.
   %player = new AIFlyingVehicle() {
      dataBlock = WarSparrow;
      aiFVPlayer = true;
   };
   MissionCleanup.add(%player);

   // Player setup
   %player.setMoveSpeed(1);
   %player.setTransform(pickSpawnPoint());
   %player.setEnergyLevel(60);
   %player.setShapeName(%this.name);
}

################## In /(game)/server/scripts/game.cs

INSERT in the onServerCreated() function before $Game::StartTime = $Sim::Time;
exec("./vehicles/Flying/WarSparrow.cs");

MODIFY GameConnection::createPlayer(%this, %spawnPoint) after
// Create the player object

to

// Create a player/fighter object.
   if( %this.gender $= "FV" )
      %this.spawnFV();
   else // Create a player object.
#55
07/25/2004 (5:27 pm)
What Badguy posting? I always like extra code. :) I can merge with the best of 'em.
#56
07/25/2004 (6:07 pm)
Badguy develped an AISteering function at this thread

It did work for WheeledVehicles but I couldn't make it work with flying or hover vehicles.

Actually I never understood why you needed a client connection for your code. Badguy's runs on the standard AIPlayer connection. all you have to do is mount the AIPlayer.

I still have to dive into your code...
#57
07/26/2004 (1:27 am)
My coding is trivial. The biggest hack there was an attempt to have a rigid body vehicle slowdown upon approach to the destination. That hack has its own issues(per above) that I don't care about in my app. I haven't taken the time to research and form a more general solution for any rigid body vehicle. The physics and time interval constraits for performing such maneuvers at a particular velocity/mass just hasn't excited me enough to dig into it. Maybe someone will read this and suggest a good book covering coding differential/integrating functions and physics stuff in general. I have been looking around the net but haven't hit the sweet spot yet about physics.
#58
07/27/2004 (5:40 am)
Ok. I felt like there had to be someone who already has addressed my concerns for decelerating a rigid body in motion at some velocity to a point some distance away at which it should stop. Whew. That was a fingers full of typing. So I went to Gamedev site, searched their forums for an appropriate issue and viola, this thread seems to address both my concerns for setting a distance/radius (mOuterMarker in my code above) that a ship moving could then have a negative acceleration applied to have it stop with velocity=0. Then one could solve for the necessary force needed to apply to make it happen at that distance. Since acceleration = f/m(force/mass), then the force needed to apply would be acc * m.
The second issue being if the ship needs to reach a point within the mOuterMarker distance. As the article above stipulates, one would accelerate for a given distance and then decelerate for an equal distance to arrive at destination being stopped.
So if anyone wants to check my brainstorming out and confirm my observations then we might get a function that can perform the calculations for any given vehicle traveling at any velocity.

Edit: Cleaned up and clarified.
#59
07/27/2004 (5:46 am)
Of course one shouldn't attempt to stop a ship moving at a high velocity at some rediculously short distance. Would be sorta like hitting a brick wall. Whicj is why I called my kludgy attempt at making it stop slamit.
// Drag at any speed
   F32 slamit = (mDistanceFactor > 1.0) ? 1.0f : 1.0f/(mDistanceFactor*mDistanceFactor+.01);
   slamit = mClampF( slamit, 1.0f, 60.0f);
//      Con::errorf(ConsoleLogEntry::General, "slamit=%f", slamit);
   force  -= mRigid.linVelocity * mDataBlock->minDrag * slamit ;
#60
07/29/2004 (3:42 pm)
I'm trying to get the AI vehicle to follow a path. If I get it to work, I'll let you know how :)

Howdy again, folks. Ok, apart from scripting appropriate functions for the AI, I got pathfinding to work. I did have to add a console function for MoveTolerance, since the default 0.1f is a tight for this particular approach..

ConsoleMethod( AIFlyingVehicle, setMoveTolerance, void, 3, 3, "ai.setMoveTolerance( float );" )
{
AIFlyingVehicle *ai = static_cast( object );
ai->setMoveTolerance( dAtof( argv[2] ) );
}

The only other tricky bit was in adding

function WarSparrow::onReachDestination(%this,%obj)
{
echo("HELLO! it's me!");
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "") {
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}

To the vehicle, .. because adding it to AIFlyingVehicle::onReachDestination never gets called.
Happy Flying!