Game Development Community

T2D Tutorial Creating a Path Point System

by Matthew Langley · 04/25/2005 (1:52 am) · 5 comments

Creating a Path Point System

note: this is using T2D version 1.02 :)

First: This tutorial will build off of this tutorial (moveTo)

Overview: This tutorial will take the moveTo function you created in the above tutorial and add a path point system to it.

At the end of this tutorial what will I have? Well at the end of this tutorial you will be able to click your mouse anywhere, a red dot will come onto screen at that point and your specified object will move to it... you can then click in multiple places and place multiple dots and it will proceed to each in order. This is not pathfinding though this can assist when you do add pathfinding. Basically this adds a path queueing system to your objects :)

double check you have these from the moveTo tutorial:

-moveTo.cs
-exec.cs
-onStartUp.cs


Ok lets get started

Lets create a new .cs file in the same folder as your client.cs and call it pathPoint.cs

then be sure to add this

exec("./pathPoint.cs");

into your exec.cs

go to your onStartUp.cs and ensure it looks like this

function onStartUp()
{
	moveToDemo();
}

We'll simply build off of the previous moveTo startup :)

ok first function we will want to create is the addPathPoint function... so add this into your pathPoint.cs

function fxSceneObject2D::addPathPoint(%this, %path)
{

you should know by now that this will add this function to all fxSceneObject2D's... we will pass it the %path when calling it

lets add a friendly little debug message

if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);

remember debug messages are our friends lol... it never hurts, I often run into problems, so I just start placing a lot of debug messages to figure out where the problem is... once you get used to it this can be a very quick way to debug things

ok now lets add a check to ensure that we are not passing an empty string... statements like this are very important, this ensures if you run into a problem in your game you can pinpoint where its at... I highly suggest going back through any script/code and adding multiple checks, usually when you go back to script you see where the checks are needed as well

if(%path !$= "")
	{

then add this

if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

ok this starts off with a check... we check if .pathPointCount is either empty (haven't done anything with it yet) or if its less than zero... if so we set it to zero... this ensures our pathPointCount will keep within bounds

now add
%this.pathPoints[%this.pathPointCount] = %path;
		%this.pathPointCount++;
	}
}

ok here we set the value "%this.pathPoints[%this.pathPointCount]" equal to whatever we pass into %path
so if this were the first path point and say you call the function passing in addPathPoint("5 5"); it would do this
%this.pathPoints[0] = "5 5";
so we are simply creating an array to store the pathPoints in... the next line
%this.pathPointCount++;

will incriment the path point count so the next time we add a path point it gets put into the next array slot... in this case that would be 1...

ok... now your funciton should look like this

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;
		%this.pathPointCount++;
	}
}

what do you say we test this out... fire up T2D... you should see a basic screen with a box in the center (like the moveTo tutorial)

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint1.JPG
ok bring up the console with the "~" tilde key... then type this command in

$player.addPathPoint("5 5");

press enter, you should get no error messages... then run this command

$player.dump();

you should see something like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint2.JPG
scroll up a little until you see something like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint3.JPG
as you can see the pathPoint0 was added correctly... as well as the pathPointCount of 1... ok so far so good

lets test this a bit more... in the console press the up arrow... it should bring the $player.dump(); command up... press the up arrow again... this should bring up the $player.addPathPoint("5 5"); up... press enter... then press the up one and enter again to insert a third path point... do this two more times... (note the console keeps track of what command you've scrolled to, quite handy)

now either type the command "$player.dump();" in or press the down arrow and press enter to run the command... scroll up until you see the same pathPoints properties you saw last time and it should look like this now

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint4.JPG
ok so this looks good... we have 0-4 path points... and the count is correct at a total of 5... ok time to move on

next we need to create a getNextPathPoint(); function
...
now this function is a bit trickier than it seems. The first thought you may think of is simply returning the pathPoints0... however we need to do more than that, for one we need to get rid of the path point after we return it, then we need to cycle each of the preceding points down to fill in the gap.

ok lets start with this

function fxSceneObject2D::getNextPathPoint(%this)
{
	if(%this.pathPoints[0] !$= "")
	{	
		if($debugMsg::pathDebug)
			echo("getting next path point");

This you should be used to from me by now lol... just a basic function start and then a check to ensure there is a path point... and of course a debug statement ;)

now add this


%path = %this.pathPoints[0];
		%pathCount = %this.pathPointCount;

ok first we grab the lowest path point and throw it in a temp variable named %path... that is what we will return in the end... now since we stored the path point its ok to get rid of it later... notice we also store the pathPointCount in %pathCount so we can do whatever we want with the pathPointCount and still have the former count

ok lets add a loop
for(%i=0;%i<%pathCount;%i++)
		{
			%this.pathPoints[%i] = %this.pathPoints[%i+1];
		}
		%this.pathPointCount--;

Here we cycle from 0 to the %pathCount... that way we cycle through every pathPoint we have...
then we set

%this.pathPoints[%i] = %this.pathPoints[%i+1];

this way we set each pathPoints to the next one, effectively eliminating the first pathPoint that we won't need anymore... note this also fills in the gap... after the loop we derease the pathPointCount by one to accurately reflect the changes

ok lets finish this function up

if(%this.pathPointCount < 0)
		{
			return -1;
		}	
		
		return %path;
	}
}

ok now this if statement is another error check... we are checking to make sure we haven't decreased the pathPointCount below zero... if so we return -1... this allows us to handle errors better just incase this were to happen...

finally we return the %path that we have now removed from the pathPoints array list...

right now your entire pathPoints.cs file should look like this

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;
		%this.pathPointCount++;
	}
}

function fxSceneObject2D::getNextPathPoint(%this)
{
	if(%this.pathPoints[0] !$= "")
	{	
		if($debugMsg::pathDebug)
			echo("getting next path point");
	
		%path = %this.pathPoints[0];
		%pathCount = %this.pathPointCount;
	
		for(%i=0;%i<%pathCount;%i++)
		{
			%this.pathPoints[%i] = %this.pathPoints[%i+1];
		}
		%this.pathPointCount--;	
		
		if(%this.pathPointCount < 0)
		{
			return -1;
		}	
		
		return %path;
	}
}


ok so time to test this one out... fire up T2D... run these commands in the console

$player.addPathPoint("1 1");
$player.addPathPoint("2 2");
$player.addPathPoint("3 3");

run $player.dump();
scroll up so you can see the pathPoints... it should look like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint5.JPG
ok now run this command

echo($player.getNextPathPoint());

you should see something like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint6.JPG
ok so it worked... well at least the first part, now we need to ensure all of the path points updated correctly

run the $player.dump(); command again... scroll up and you should see something like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint7.JPG
ok so it not only returned the first pathPoint, but it removed it properly and reduced the pathPointCount properly :)
so it works!

ok... now these numbers are oohh soo exciting (lame sarcasm I know) so lets actually do something with this...

ok add this function

function fxSceneObject2D::followPath(%this)
{
	if(!%this.followingPath)
	{
		%this.followingPath = true;

		if($debugMsg::pathDebug)
			echo("following path");
		
		if(%this.speed $= "")		
			%this.speed = 10;

		%this.moveTo(%this.getNextPathPoint(), %this.speed);
	}
}

This function is basically the translation between our moveTo system and the pathPoint system... we call this and it checks if its already following a path, if not it sets it to true and then we have our friendly little debug statement.

It checks if it already has a speed set, if not it sets it to 10... then it calls our previously made moveTo function passing the next path point and sets the move speed to the objects speed...

so to start it on following a path we simply call followPath();

ok now we need to handle the transition when it reaches a path point... we need to tell it to follow the path again. If you remember from the moveTo tutorial we created a nifty little callback from script called "onReachDestination()"... this is where that will really come in handy... so add this fnction

function fxSceneObject2D::onReachDestination(%this)
{
	if(%this.followingPath)
	{
		%this.followingPath = false;

		if(%this.pathPointCount > 0)
		{
			%this.followPath();
		} 
		
	}
}

first we check if its following a path... if so we set followingPath to false then check if its pathPointCount is higher than 0... if so we tell it to follow the path... if not it has reached the last path point ... ok we are almost ready to test this...

the final step is to add this

function sceneWindow2D::onRightMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	$player.addPathPoint(%worldPos);
	if(!$player.followingPath)
		$player.followPath();
}

ok, this will not only make testing easier, but it will allow you to see a practicaly application of this...

we set an onRightMouseDown event... so when we right click it adds a path point at the position we clicked... it then checks if its already following a path, if not it tells it to follow the path :)... ok save and fire up T2D to give this a whirl.

right click at random places on the screen and watch your box follow the points in order!

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint8.JPG
ok so it works! if yours doesn't work compare your whole file to this

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;
		%this.pathPointCount++;
	}
}

function fxSceneObject2D::getNextPathPoint(%this)
{
	if(%this.pathPoints[0] !$= "")
	{	
		if($debugMsg::pathDebug)
			echo("getting next path point");
	
		%path = %this.pathPoints[0];
		%pathCount = %this.pathPointCount;
	
		for(%i=0;%i<%pathCount;%i++)
		{
			%this.pathPoints[%i] = %this.pathPoints[%i+1];
		}
		%this.pathPointCount--;	
		
		if(%this.pathPointCount < 0)
		{
			return -1;
		}	
		
		return %path;
	}
}

function fxSceneObject2D::followPath(%this)
{
	if(!%this.followingPath)
	{
		%this.followingPath = true;		

		if($debugMsg::pathDebug)
			echo("following path");
		
		if(%this.speed $= "")		
			%this.speed = 10;

		%this.moveTo(%this.getNextPathPoint(), %this.speed);
	}
}

function fxSceneObject2D::onReachDestination(%this)
{
	if(%this.followingPath)
	{
		%this.followingPath = false;

		if(%this.pathPointCount > 0)
		{
			%this.followPath();
		} 
		
	}
}

function sceneWindow2D::onRightMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	$player.addPathPoint(%worldPos);
	if(!$player.followingPath)
		$player.followPath();
}


though we can't see the path points visually... so lets add a dot system that will insert a dot at those path points then remove them when we're done!

these will be similar to the pathPoint functions... add this

function fxSceneObject2D::addRedDot(%this, %loc)
{	
	if(%loc !$= "")
	{	
		%size = "3 3";
		
		if((%this.dotCount $= "") || (%this.dotCount < 0))
			%this.dotCount = 0;
		
		%this.dot[%this.dotCount] = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
		%this.dot[%this.dotCount].setImageMap(tileMapImageMap, 1);
		%this.dot[%this.dotCount].setPosition(%loc);
		%this.dot[%this.dotCount].setSize( %size );
		%this.dot[%this.dotCount].type = "dot";

		%this.dotCount++;
	}
}

ok first we do the usual check to see if the %loc passed actually has something... we then set the size to "3 3"... I did this so you can easily configure the size of the dots to be created...

we then do the same thing with the dotCount as we did with the pathPointCount... we check to see if its empty or if its less than zero, if so we set it to zero, this keeps everything valid

then we set the dot array item to a static sprite (since we are placing images instead of storing path points)... we set the imagemap ( you can change this to whatever you want)... we set its position to the %loc passed, its %size to the size we specified... then we set its type to "dot"... like I said this function is very similar to the one we created for the path points

the next function is identical to our getNextPathPoint() except its changed for the dots (so I won't explain it)

add this

function fxSceneObject2D::getNextRedDot(%this)
{
	if(%this.dot[0] !$= "")
	{	
		%dot = %this.dot[0];
		%redDotCount = %this.dotCount;
	
		for(%i=0;%i<%redDotCount;%i++)
		{
			%this.dot[%i] = %this.dot[%i+1];
		}
		%this.dotCount--;	
		
		if(%this.dotCount < 0)
		{
			return -1;
		}
		return %dot;
	}
}

ok so we have a dot queueing system... To integrate our dot system into our path point system we need to add code to two places... first we need to add the dots when the points get added so change your addPathPoint() function from

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;

		%this.pathPointCount++;
	}
}


to this

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;

		%this.addRedDot(%path);

		%this.pathPointCount++;
	}
}


then we need to remove the dots when we reach the destination, so in your onReachDestination change it from

function fxSceneObject2D::onReachDestination(%this)
{
	if(%this.followingPath)
	{
		%this.followingPath = false;

		if(%this.pathPointCount > 0)
		{
			%this.followPath();
		} 
		
	}
}

to this

function fxSceneObject2D::onReachDestination(%this)
{
	if(%this.followingPath)
	{
		%this.followingPath = false;

		%dot = %this.getNextRedDot();
		%dot.safeDelete();

		if(%this.pathPointCount > 0)
		{
			%this.followPath();
		} 
		
	}
}

ok now save it and fire up T2D... right click at random places like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint9.JPG
and it should go to each path point and eat them up like this

razedskyz.com/games/torque/tutorials/T2D/pathPoint/pathPoint10.JPG
if not compare your entire pathPoint.cs to this

function fxSceneObject2D::addPathPoint(%this, %path)
{
	if($debugMsg::pathDebug)
		echo("Attempting to add this path point:" SPC %path);
	
	if(%path !$= "")
	{		
		if((%this.pathPointCount $= "") || (%this.pathPointCount < 0))
			%this.pathPointCount = 0;

		%this.pathPoints[%this.pathPointCount] = %path;

		%this.addRedDot(%path);

		%this.pathPointCount++;
	}
}

function fxSceneObject2D::getNextPathPoint(%this)
{
	if(%this.pathPoints[0] !$= "")
	{	
		if($debugMsg::pathDebug)
			echo("getting next path point");
	
		%path = %this.pathPoints[0];
		%pathCount = %this.pathPointCount;
	
		for(%i=0;%i<%pathCount;%i++)
		{
			%this.pathPoints[%i] = %this.pathPoints[%i+1];
		}
		%this.pathPointCount--;	
		
		if(%this.pathPointCount < 0)
		{
			return -1;
		}	
		
		return %path;
	}
}

function fxSceneObject2D::followPath(%this)
{
	if(!%this.followingPath)
	{
		%this.followingPath = true;		

		if($debugMsg::pathDebug)
			echo("following path");
		
		if(%this.speed $= "")		
			%this.speed = 10;

		%this.moveTo(%this.getNextPathPoint(), %this.speed);
	}
}

function fxSceneObject2D::onReachDestination(%this)
{
	if(%this.followingPath)
	{
		%this.followingPath = false;

		%dot = %this.getNextRedDot();
		%dot.safeDelete();

		if(%this.pathPointCount > 0)
		{
			%this.followPath();
		} 
		
	}
}

function sceneWindow2D::onRightMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	$player.addPathPoint(%worldPos);
	if(!$player.followingPath)
		$player.followPath();
}

function fxSceneObject2D::addRedDot(%this, %loc)
{	
	if(%loc !$= "")
	{	
		%size = "3 3";
		
		if((%this.dotCount $= "") || (%this.dotCount < 0))
			%this.dotCount = 0;
		
		%this.dot[%this.dotCount] = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };
		%this.dot[%this.dotCount].setImageMap(tileMapImageMap, 1);
		%this.dot[%this.dotCount].setPosition(%loc);
		%this.dot[%this.dotCount].setSize( %size );
		%this.dot[%this.dotCount].type = "dot";

		%this.dotCount++;
	}
}

function fxSceneObject2D::getNextRedDot(%this)
{
	if(%this.dot[0] !$= "")
	{	
		%dot = %this.dot[0];
		%redDotCount = %this.dotCount;
	
		for(%i=0;%i<%redDotCount;%i++)
		{
			%this.dot[%i] = %this.dot[%i+1];
		}
		%this.dotCount--;	
		
		if(%this.dotCount < 0)
		{
			return -1;
		}
		return %dot;
	}
}


ok so we got a simple path queueing system up! Good work... hope you enjoyed and learned something from this :)

-Matthew "King Tut(orial) BoB" Langley

About the author

I Manage and Lead Tool Development for Torque 3D and R&D 3D tool products at GarageGames


#1
04/24/2005 (6:40 pm)
Thanks.
#2
04/25/2005 (1:13 pm)
Wow. This is awesome Matt! Great job again. Where do you find the time... :)
#3
04/26/2005 (3:08 pm)
Thx, glad you both enjoyed it :)

lol I think I started this one at 2-3 am saturday morning and finished it about 5:30 am... Couldn't sleep so figure I'd be productive
#5
09/09/2005 (4:28 pm)
You can now get this tutorial along with 9 others in a T2D "Tutorial Pack"... in this pack each tutorial is an external html file so you can use them offline :)