Game Development Community

AI respawn at starting point after reaching end of path

by Bullitt Sesariza · in Torque Game Engine · 12/10/2007 (10:13 am) · 1 replies

I recently need to use a moving vehicles for the obstacles in my game. So, I made them AIWheeledVehicles that move inside their own assigned path. After they reached the end of the path, they will respawn and retrace their path again. Currently, I have only tried making 2 objects. Here's the script:
function CarDataLane1::onReachDestination(%this,%obj)
{
   if (%obj.path !$= "") {
      if (%obj.currentNode == %obj.targetNode)
         %this.onEndOfPath(%obj,%obj.path);
      else
         %obj.moveToNextNode();
   }
}

function CarDataLane1::onEndOfPath(%this,%obj,%path)
{
[b]	%node = %path.getObject(0);
	%obj.setTransform(%node.getTransform());
	%obj.followPath(%path,-1);[/b]
        %obj.nextTask();
}

function CarDataLane1::onEndSequence(%this,%obj,%slot)
{
   error("Sequence Done!");
   %obj.stopThread(%slot);
   %obj.nextTask();
}

//-----------------------------------
function CarDataLane2::onReachDestination(%this,%obj)
{
   if (%obj.path !$= "") {
      if (%obj.currentNode == %obj.targetNode)
         %this.onEndOfPath(%obj,%obj.path);
      else
         %obj.moveToNextNode();
   }
}

function CarDataLane2::onEndOfPath(%this,%obj,%path)
{
[b]	%node = %path.getObject(0);
	%obj.setTransform(%node.getTransform());
	%obj.followPath(%path,-1);[/b]
        %obj.nextTask();
}

function CarDataLane2::onEndSequence(%this,%obj,%slot)
{
   error("Sequence Done!");
   %obj.stopThread(%slot);
   %obj.nextTask();
}

//-------------------------

function AIWheeledVehicle::spawn(%name,%spawnPoint)
{
   // Create the demo player object
   %vehicle = new AIWheeledVehicle() {
      dataBlock = %name;
      path = "";
   };
   MissionCleanup.add(%vehicle);
   %vehicle.setTransform(%spawnPoint);
   return %vehicle;
}

function AIWheeledVehicle::spawnOnPath(%name,%path)
{
   // Spawn a player and place him on the first node of the path
   if (!isObject(%path))
      return 0;
   %node = %path.getObject(0);
   %vehicle = AIWheeledVehicle::spawn(%name,%node.getTransform());
   return %vehicle;
}

function AIWheeledVehicle::followPath(%this,%path,%node)
{
   // Start the player following a path
   %this.stopThread(0);
   if (!isObject(%path)) {
	  error( "AIWheeledVehicle::followPath failed - Bad Path!" );
      %this.path = "";
      return;
   }
   if ((%node == -1) || (%node > %path.getCount() - 1))
      %this.targetNode = %path.getCount() - 1;
   else
      %this.targetNode = %node;
   if (%this.path $= %path)
      %this.moveToNode(%this.currentNode);
   else {
      %this.path = %path;
      %this.moveToNode(0);
   }
}

function AIWheeledVehicle::moveToNextNode(%this)
{
   if (%this.targetNode < 0 || %this.currentNode < %this.targetNode) {
      if (%this.currentNode < %this.path.getCount() - 1)
         %this.moveToNode(%this.currentNode + 1);
      else
         %this.moveToNode(0);
   }
   else
      if (%this.currentNode == 0)
         %this.moveToNode(%this.path.getCount() - 1);
      else
         %this.moveToNode(%this.currentNode - 1);
}

function AIWheeledVehicle::moveToNode(%this,%index)
{
   // Move to the given path node index
   %this.currentNode = %index;
   %node = %this.path.getObject(%index);
   %this.setMoveDestination(%node.getTransform(), %index == %this.targetNode);
}
...

#1
12/10/2007 (10:14 am)
It looks like I've reached the max char. Here's the rest of the code:
//-----------------------------------------------------------------------------

function AIWheeledVehicle::pushTask(%this,%method)
{
   if (%this.taskIndex $= "") {
      %this.taskIndex = 0;
      %this.taskCurrent = -1;
   }
   %this.task[%this.taskIndex] = %method; 
   %this.taskIndex++;
   if (%this.taskCurrent == -1)
      %this.executeTask(%this.taskIndex - 1);
}

function AIWheeledVehicle::clearTasks(%this)
{
   %this.taskIndex = 0;
   %this.taskCurrent = -1;
}

function AIWheeledVehicle::nextTask(%this)
{
   if (%this.taskCurrent != -1)
      if (%this.taskCurrent < %this.taskIndex - 1)
         %this.executeTask(%this.taskCurrent++);
      else
         %this.taskCurrent = -1;
}

function AIWheeledVehicle::executeTask(%this,%index)
{
   %this.taskCurrent = %index;
   eval(%this.getId() @ "." @ %this.task[%index] @ ";");
}

function AIWheeledVehicle::wait(%this,%time)
{
   %this.schedule(%time * 1000,"nextTask");
}

function AIWheeledVehicle::done(%this,%time)
{
   %this.schedule(0,"delete");
}

function AIWheeledVehicle::animate(%this,%seq)
{
   //%this.stopThread(0);
   //%this.playThread(0,%seq);
   %this.setActionThread(%seq);
}
//-----------------------------------------------------------------------------

function AIManager::think(%this)
{
   if (!isObject(%this.player))
	{
      %this.player = %this.spawn();
    }
    if (!isObject(%this.player2))
	{
      %this.player2 = %this.spawn2();
    }
   %this.schedule(500,think);
}

function AIManager::spawn(%this)
{
   %player = AIWheeledVehicle::spawnOnPath("CarDataLane1","MissionGroup/Paths/PathLane1");
   
   if (isObject(%player))
   {
      %player.followPath("MissionGroup/Paths/PathLane1",-1);

	  return %player;
   }
   else
   {
	  error("AIVehicle:spawn failed! Object not found!");
      return 0;
   }
}

function AIManager::spawn2(%this)
{
   %player = AIWheeledVehicle::spawnOnPath("CarDataLane2","MissionGroup/Paths/PathLane2");
   
   if (isObject(%player))
   {
      %player.followPath("MissionGroup/Paths/PathLane2",-1);

	  return %player;
   }
   else
   {
	  error("AIVehicle:spawn failed! Object not found!");
      return 0;
   }
}


The path mission objects:
new SimGroup(Paths) {
      canSaveDynamicFields = "1";

      new Path(PathLane1) {
         canSaveDynamicFields = "1";
         isLooping = "1";

         new Marker() {
            canSaveDynamicFields = "1";
            position = "-1.72 -480.029 3.73724";
            rotation = "1 0 0 0";
            scale = "1 1 1";
            seqNum = "1";
            type = "Normal";
            msToNext = "1000";
            smoothingType = "Spline";
         };
         new Marker() {
            canSaveDynamicFields = "1";
            position = "-1.72 -360.029 3.73724";
            rotation = "1 0 0 0";
            scale = "1 1 1";
            seqNum = "2";
            type = "Normal";
            msToNext = "1000";
            smoothingType = "Spline";
         };
      };
      new Path(PathLane2) {
         canSaveDynamicFields = "1";
         isLooping = "1";

         new Marker() {
            canSaveDynamicFields = "1";
            position = "-21.72 -480.029 3.73724";
            rotation = "1 0 0 0";
            scale = "1 1 1";
            seqNum = "1";
            type = "Normal";
            msToNext = "1000";
            smoothingType = "Spline";
         };
         new Marker() {
            canSaveDynamicFields = "1";
            position = "-21.72 -340.029 3.73724";
            rotation = "1 0 0 0";
            scale = "1 1 1";
            seqNum = "2";
            type = "Normal";
            msToNext = "1000";
            smoothingType = "Spline";
         };
      };
   };

The problems are:
1. It can only work on 1 object, the first / CarLane1 object. CarLane1 will always be respawned / retransformed to its path's first marker and then will retrace its path again. But the CarLane2 isn't. It will move normally at first, and then after it reached the end of its path, it will move weirdly.
2. Although CarLane1 can be respawned (by calling setTransform(%node.getTransform());) to the transformation coordinate of the first marker in its path, it didn't transformed smoothly. It seems like it was dragged at high speed to the first marker's position. So it looks like a light speed car moving backwards from the end of the path to the start of the path. Does all setTransform() function behave like this? I mean it won't change the coordinate and rotation of the object instantly but gradually?

While we're at it, I have a few more questions:
1. Can I make 2 or more objects in a path? I need to make 2 or more obstacles that will move in the same lane, same speed, and same direction.
2. The gap between 1 obstacle to the other will have to be EXACTLY as I want it to be. E.g. after the first car move for about 5 points, the second car will begin moving, etc. How do I do that?

Does anybody have any suggestion about a way to solve these problems?

Thanks a lot in advance.