Original Post
Hello.
I'm currently using this code as my pathfinding algorithm for an RTS. However, I find it too slow.
What would you recommend me to optimize it? I'm looking both for general ideas or articles (like grouping nearby tiles into one for pathfinding purposes?) and for specific optimization pertaining to the code (using classes slows it down? using generic lists slows it down?
Thank you in advance.
[source lang="csharp"]
private List FindPath(Creature c, Tile targetTile)
{
List open = new List(); // A* open list
List closed = new List(); // A* closed list
Tile targetFound = null;
if (targetTile.BlocksMovement) return null;
// The heuristics used is 10 times horizontal distance to target + 10 times vertical distance to target
// Setting the cost of the starting tile to 0
Map[c.TileX][c.TileY].Pathfinding_G = 0;
Map[c.TileX][c.TileY].Pathfinding_H = Math.Abs(targetTile.X - c.TileX) * 10 + Math.Abs(targetTile.Y - c.TileY) * 10;
Map[c.TileX][c.TileY].Pathfinding_F = Map[c.TileX][c.TileY].Pathfinding_G + Map[c.TileX][c.TileY].Pathfinding_H;
Map[c.TileX][c.TileY].Pathfinding_Parent = null;
open.Add(Map[c.TileX][c.TileY]);
while (open.Count != 0)
{
// Choosing the tile with lowest "F" value (cost + heuristics)
int lowestF = Int32.MaxValue;
Tile currentTile = null;
foreach (Tile t in open)
{
if (t.Pathfinding_F < lowestF)
{
lowestF = t.Pathfinding_F;
currentTile = t;
}
}
// End if target is found
if (currentTile == targetTile)
{
targetFound = targetTile;
break;
}
// Determines the cost to all adjacent tiles and if it is smaller than the existing one, overwrites
foreach (Tile adjacent in currentTile.Neighbours)
{
if (closed.Contains(adjacent)) continue;
// If this is the first time we ran into the tile, we reset its cost to maximum and calculate the heuristic.
if (!open.Contains(adjacent))
{
adjacent.Pathfinding_G = Int32.MaxValue;
adjacent.Pathfinding_H = Math.Abs(targetTile.X - adjacent.X) * 10 + Math.Abs(targetTile.Y - adjacent.Y) * 10;
adjacent.Pathfinding_F = adjacent.Pathfinding_G + adjacent.Pathfinding_H;
open.Add(adjacent);
}
int Gfromhere = currentTile.Pathfinding_G + 10;
if (Math.Abs(currentTile.X - adjacent.X) + Math.Abs(currentTile.Y - adjacent.Y) == 2) Gfromhere += 4;
if (Gfromhere < adjacent.Pathfinding_G)
{
adjacent.Pathfinding_G = Gfromhere;
adjacent.Pathfinding_F = adjacent.Pathfinding_G + adjacent.Pathfinding_H;
adjacent.Pathfinding_Parent = currentTile;
}
}
open.Remove(currentTile);
closed.Add(currentTile);
}
// Backtracking to form a path
if (targetFound == null)
return null;
else
{
List res = new List();
while (targetFound.Pathfinding_Parent != null)
{
res.Insert(0, targetFound);
targetFound = targetFound.Pathfinding_Parent;
}
return res;
}
}
[/source]
I'm currently using this code as my pathfinding algorithm for an RTS. However, I find it too slow.
What would you recommend me to optimize it? I'm looking both for general ideas or articles (like grouping nearby tiles into one for pathfinding purposes?) and for specific optimization pertaining to the code (using classes slows it down? using generic lists slows it down?
Thank you in advance.
[source lang="csharp"]
private List
{
List
List
Tile targetFound = null;
if (targetTile.BlocksMovement) return null;
// The heuristics used is 10 times horizontal distance to target + 10 times vertical distance to target
// Setting the cost of the starting tile to 0
Map[c.TileX][c.TileY].Pathfinding_G = 0;
Map[c.TileX][c.TileY].Pathfinding_H = Math.Abs(targetTile.X - c.TileX) * 10 + Math.Abs(targetTile.Y - c.TileY) * 10;
Map[c.TileX][c.TileY].Pathfinding_F = Map[c.TileX][c.TileY].Pathfinding_G + Map[c.TileX][c.TileY].Pathfinding_H;
Map[c.TileX][c.TileY].Pathfinding_Parent = null;
open.Add(Map[c.TileX][c.TileY]);
while (open.Count != 0)
{
// Choosing the tile with lowest "F" value (cost + heuristics)
int lowestF = Int32.MaxValue;
Tile currentTile = null;
foreach (Tile t in open)
{
if (t.Pathfinding_F < lowestF)
{
lowestF = t.Pathfinding_F;
currentTile = t;
}
}
// End if target is found
if (currentTile == targetTile)
{
targetFound = targetTile;
break;
}
// Determines the cost to all adjacent tiles and if it is smaller than the existing one, overwrites
foreach (Tile adjacent in currentTile.Neighbours)
{
if (closed.Contains(adjacent)) continue;
// If this is the first time we ran into the tile, we reset its cost to maximum and calculate the heuristic.
if (!open.Contains(adjacent))
{
adjacent.Pathfinding_G = Int32.MaxValue;
adjacent.Pathfinding_H = Math.Abs(targetTile.X - adjacent.X) * 10 + Math.Abs(targetTile.Y - adjacent.Y) * 10;
adjacent.Pathfinding_F = adjacent.Pathfinding_G + adjacent.Pathfinding_H;
open.Add(adjacent);
}
int Gfromhere = currentTile.Pathfinding_G + 10;
if (Math.Abs(currentTile.X - adjacent.X) + Math.Abs(currentTile.Y - adjacent.Y) == 2) Gfromhere += 4;
if (Gfromhere < adjacent.Pathfinding_G)
{
adjacent.Pathfinding_G = Gfromhere;
adjacent.Pathfinding_F = adjacent.Pathfinding_G + adjacent.Pathfinding_H;
adjacent.Pathfinding_Parent = currentTile;
}
}
open.Remove(currentTile);
closed.Add(currentTile);
}
// Backtracking to form a path
if (targetFound == null)
return null;
else
{
List
while (targetFound.Pathfinding_Parent != null)
{
res.Insert(0, targetFound);
targetFound = targetFound.Pathfinding_Parent;
}
return res;
}
}
[/source]