aStar with Tile Line-of-Sight
by Kevin J Hawkins · in Torque Game Builder · 06/23/2011 (5:55 pm) · 5 replies
I decided today to take a look at Torque 2Ds aStar capabilities. Although its fairly complete, there were some documentation hurdles before I worked all of the bugs out. I'm now extremely happy at how easy it is to prototype a game. One feature that I needed in combination with pathfinding was a way to do a simple raycast (to check for line of sight) between tiles. Since this was not a part of torque2d I added it.
To get everything up and running:
Open the torque source project. For me it was "engine/compilers/VisualStudio 2008/T2D SDK.sln"
Now open t2dTileMap.h and add the following in a public portion of the t2dTileLayer class
Rebuild the project. Make sure it is set for Release and not Debug
If everything went okay and nothing failed go ahead and close your IDE.
Create a new TGB project (choose to copy the executable), save it, and close the TGB Editor
Copy aiclass.cs, aStarActor.cs, and aStarPath.cs to the gameScripts folder
Copy shooterControls.cs and velocityRotate.cs to the behaviours folder
Copy the images to data/images
Open the TGB project again and add the images as static sprites under the Create pane
Drag a Tilemap onto the scene and set the tile count to 32 x 32
Click Size Object to Layer and align the TileMap how you wish
Click Edit Tile Layer and scroll down to the Tile Editing pane.
In the Custom Data box leave it at None to leave the tile unweighted.
Set the Custom Data from 0.1 to 9.9 to add a "weight" to the tile, which makes enemies want to avoid the tile.
Set the Custom Data to 10 to make the tile as a wall. Setting the Custom Data to 10 also makes the Line-of-Sight test return false if one of these tiles are in the way.
Paint some tiles with the grass at None, sand at 3.0, and walls at 10
Scroll down to Scripting and set the name to myTileMap and the class to pathLayer
Save your layer and go to the Create pane.
Drag a player and a couple of enemies onto the scene (over the top of the tile map).
Click on the player and add the Shooter Controls and Rotate by Velocity behaviours.
Scroll down to Scripting and set the name to pPlayer
For each enemy add the Rotate by Velocity behaviour
Also, for each enemy set the class to AIClass and the superclass to aStarActor
Save everything and close the TGB editor
In the game folder open main.cs
Above the line "exec("./gameScripts/game.cs");" add the following
That's it, run the game from TGB and the enemies should now follow you after they see you.
The line of sight function is a member function for the TileMap object which takes 4 parameters.
Example:
%cansee = myTileMap.TileLOS( %enemyTilePosition.x, %enemyTilePosition.y, %playerTilePosition.x, %playerTilePosition.y );
This will return true or false. The pickTile function is an easy way to get coordinates for TileLOS
t2daStarLOSfiles.zip
Mirror:t2daStarLOSfiles.zip
Demo included with the files.

To get everything up and running:
Open the torque source project. For me it was "engine/compilers/VisualStudio 2008/T2D SDK.sln"
Now open t2dTileMap.h and add the following in a public portion of the t2dTileLayer class
// Line of sight check bool TileLOS( const U32 tileOrigX, const U32 tileOrigY, const U32 tileDestX, const U32 tileDestY );Next open t2dTileMap.cc and add this to the very end of the file
//Bresenham algorithm
ConsoleMethod( t2dTileLayer, TileLOS, bool, 6, 6, "(int tileOriginX, int tileOriginY, int tileDestX, int tileDestY) - Checks Line of Sight between tiles.n"
"@param tileX The X coordinate of the origin tilen"
"@param tileY The Y coordinate of the origin tilen"
"@param tileY The X coordinate of the destination tilen"
"@param tileY The Y coordinate of the destination tilen"
"@return Return true if the line contains no tiles with Custom Data set to 10" )
{
int x0 = dAtoi(argv[2]);
int y0 = dAtoi(argv[3]);
int x1 = dAtoi(argv[4]);
int y1 = dAtoi(argv[5]);
int dx = abs(x1-x0);
int dy = abs(y1-y0);
int sx;
if(x0 < x1)
sx = 1;
else
sx = -1;
int sy;
if(y0 < y1)
sy = 1;
else
sy = -1;
int err = dx-dy;
while(true)
{
const char* customData = object->getTileCustomData(x0, y0);
if( customData && customData[0] == '1' && customData[1] == '0' )
return false;
if(x0 == x1 && y0 == y1)
return true;
int e2 = 2*err;
if(e2 > -dy)
{
err = err - dy;
x0 = x0 + sx;
}
if(e2 < dx)
{
err = err + dx;
y0 = y0 + sy ;
}
}
}Rebuild the project. Make sure it is set for Release and not Debug
If everything went okay and nothing failed go ahead and close your IDE.
Create a new TGB project (choose to copy the executable), save it, and close the TGB Editor
Copy aiclass.cs, aStarActor.cs, and aStarPath.cs to the gameScripts folder
Copy shooterControls.cs and velocityRotate.cs to the behaviours folder
Copy the images to data/images
Open the TGB project again and add the images as static sprites under the Create pane
Drag a Tilemap onto the scene and set the tile count to 32 x 32
Click Size Object to Layer and align the TileMap how you wish
Click Edit Tile Layer and scroll down to the Tile Editing pane.
In the Custom Data box leave it at None to leave the tile unweighted.
Set the Custom Data from 0.1 to 9.9 to add a "weight" to the tile, which makes enemies want to avoid the tile.
Set the Custom Data to 10 to make the tile as a wall. Setting the Custom Data to 10 also makes the Line-of-Sight test return false if one of these tiles are in the way.
Paint some tiles with the grass at None, sand at 3.0, and walls at 10
Scroll down to Scripting and set the name to myTileMap and the class to pathLayer
Save your layer and go to the Create pane.
Drag a player and a couple of enemies onto the scene (over the top of the tile map).
Click on the player and add the Shooter Controls and Rotate by Velocity behaviours.
Scroll down to Scripting and set the name to pPlayer
For each enemy add the Rotate by Velocity behaviour
Also, for each enemy set the class to AIClass and the superclass to aStarActor
Save everything and close the TGB editor
In the game folder open main.cs
Above the line "exec("./gameScripts/game.cs");" add the following
exec("./gameScripts/aStarPath.cs");
exec("./gameScripts/aStarActor.cs");
exec("./gameScripts/aiclass.cs");That's it, run the game from TGB and the enemies should now follow you after they see you.
The line of sight function is a member function for the TileMap object which takes 4 parameters.
Example:
%cansee = myTileMap.TileLOS( %enemyTilePosition.x, %enemyTilePosition.y, %playerTilePosition.x, %playerTilePosition.y );
This will return true or false. The pickTile function is an easy way to get coordinates for TileLOS
t2daStarLOSfiles.zip
Mirror:t2daStarLOSfiles.zip
Demo included with the files.

#2
07/01/2011 (6:51 pm)
Repacked the files with a demo and reuploaded as requested. I've never submitted anything as a resource so I'll look into that sometime.
#3
Thanks!
07/02/2011 (10:36 pm)
Kevin, I'm about to download this demo -- looks really cool from the screenshot! It makes me want to create a roguelike game for sure. Did roguelikes inspire this project of yours?Thanks!
#4
I'm working on a tile based zombie survival game, so that's where this project stemmed from.
Just a note. Smaller tiles will make for more accurate results. To do that you'll probably want to use very small objects on the tile map with graphics mounted on top. If you place objects larger than the tiles, then I'm pretty sure that they get stuck.
07/03/2011 (12:10 am)
I think Line-of-Sight is a must have for creating any realistic AI for enemies. Especially in a rogue-type game.I'm working on a tile based zombie survival game, so that's where this project stemmed from.
Just a note. Smaller tiles will make for more accurate results. To do that you'll probably want to use very small objects on the tile map with graphics mounted on top. If you place objects larger than the tiles, then I'm pretty sure that they get stuck.
#5
This is exactly the thing I was needing to make my AI scan for targets.
11/16/2011 (11:49 am)
THANK YOU!This is exactly the thing I was needing to make my AI scan for targets.
Torque Owner Kevin James
It'd be so chill if you would upload a demo of this in action. The link on the bottom of your thread is broken. You could also submit this as a sick resource.
Sweet