// maybe should just return the next position // this method is super slow, need to rebuild so it isn't public Vector2i GetPath(int startX, int startY, int endX, int endY, CostCallback costFn) { clearBuffer(); floodHeight(endX, endY, 1, ref buffer, costFn); int lowestNeighbor = -1; int lowestNeighborDir = 0; for (int i = 0; i < 4; i++) { int tx = startX + nDir[i, 0]; int ty = startY + nDir[i, 1]; if (tx >= 0 && tx < buffer.GetLength(0) && ty >= 0 && ty < buffer.GetLength(1) && IsOpenTile(tx, ty) && //!ContainsSnake(tx, ty) && // need to have a delegate for calculating tile movement costs, perhaps pass into the flood height as well (lowestNeighbor == -1 || lowestNeighbor > buffer[tx, ty]) ) { lowestNeighbor = buffer[tx, ty]; lowestNeighborDir = i; } } if (lowestNeighbor == -1) { // return out of map for invalid tile new Vector2i(new int[] { -1, -1 }); } return(new Vector2i(startX + nDir [lowestNeighborDir, 0], startY + nDir [lowestNeighborDir, 1])); }
void floodHeight(int x, int y, int marker, ref int[,] buffer, CostCallback fn) { // make sure to only visit each cell once buffer[x, y] = marker; for (int i = 0; i < 4; i++) { int tx = x + nDir[i, 0]; int ty = y + nDir[i, 1]; if (tx >= 0 && tx < buffer.GetLength(0) && ty >= 0 && ty < buffer.GetLength(1) && layout[tx, ty] == TileType.OPEN && (buffer[tx, ty] == 0 || (marker + fn(tx, ty)) < buffer[tx, ty])) { floodHeight(tx, ty, marker + fn(tx, ty), ref buffer, fn); } } }
public List <Vector2i> FindPath(Vector2i start, Vector2i end, CostCallback costFn, Map map) { if (start.Equals(end)) { return(new List <Vector2i> ()); } // clear the lists openList = new Dictionary <ulong, Node> (); closedList = new Dictionary <ulong, Node> (); Node startNode = new Node(start); openList [startNode.Key] = startNode; bool pathfound = false; int searchCount = 0; while (!pathfound && openList.Count > 0 && searchCount < 500) { Node lowestCost = findLowestCost(); openList.Remove(lowestCost.Key); closedList[lowestCost.Key] = lowestCost; if (lowestCost.position.Equals(end)) { pathfound = true; break; } for (int i = 0; i < 4; i++) { Vector2i neighborPosition = new Vector2i(lowestCost.position.x + Map.nDir [i, 0], lowestCost.position.y + Map.nDir [i, 1]); int newCost = lowestCost.distanceCost + costFn(neighborPosition.x, neighborPosition.y); if (map.IsOpenTile(neighborPosition.x, neighborPosition.y) && !openList.ContainsKey(Node.KeyFromPostion(neighborPosition))) { Node newPosition = new Node(neighborPosition); newPosition.heuristicCost = (int)Math.Abs(neighborPosition.x - end.x) + (int)Math.Abs(neighborPosition.y - end.y); newPosition.distanceCost = newCost; newPosition.parent = lowestCost; openList[newPosition.Key] = newPosition; } else if (openList.ContainsKey(Node.KeyFromPostion(neighborPosition)) && openList[Node.KeyFromPostion(neighborPosition)].distanceCost > newCost) { openList [Node.KeyFromPostion(neighborPosition)].distanceCost = newCost; openList [Node.KeyFromPostion(neighborPosition)].parent = lowestCost; } } searchCount++; } Node nextn = null; // couldn't find a path to the end if (!closedList.ContainsKey(Node.KeyFromPostion(end))) { // just build a short list containing the neighbor tiles. // eventually this should find "as near as possible" type tiles to move towards // I guess it depends on the application though startNode = new Node(start); Node lowestCost = startNode; for (int i = 0; i < 4; i++) { Vector2i neighborPosition = new Vector2i(lowestCost.position.x + Map.nDir [i, 0], lowestCost.position.y + Map.nDir [i, 1]); int newCost = lowestCost.distanceCost + costFn(neighborPosition.x, neighborPosition.y); if (map.IsOpenTile(neighborPosition.x, neighborPosition.y) && !openList.ContainsKey(Node.KeyFromPostion(neighborPosition))) { Node newPosition = new Node(neighborPosition); newPosition.heuristicCost = (int)Math.Abs(neighborPosition.x - end.x) + (int)Math.Abs(neighborPosition.y - end.y); newPosition.distanceCost = newCost; newPosition.parent = lowestCost; openList [newPosition.Key] = newPosition; } } nextn = findLowestCost(); } else { nextn = closedList [Node.KeyFromPostion(end)]; } // build the step list List <Vector2i> returnList = new List <Vector2i> (); while (nextn != null) { returnList.Add(nextn.position); nextn = nextn.parent; } returnList.Reverse(); return(returnList); }
public List<Vector2i> FindPath(Vector2i start, Vector2i end, CostCallback costFn, Map map) { if (start.Equals (end)) { return new List<Vector2i> (); } // clear the lists openList = new Dictionary<ulong, Node> (); closedList = new Dictionary<ulong, Node> (); Node startNode = new Node (start); openList [startNode.Key] = startNode; bool pathfound = false; int searchCount = 0; while (!pathfound && openList.Count > 0 && searchCount < 500) { Node lowestCost = findLowestCost (); openList.Remove (lowestCost.Key); closedList[lowestCost.Key] = lowestCost; if (lowestCost.position.Equals (end)) { pathfound = true; break; } for (int i = 0; i < 4; i++) { Vector2i neighborPosition = new Vector2i (lowestCost.position.x + Map.nDir [i, 0], lowestCost.position.y + Map.nDir [i, 1]); int newCost = lowestCost.distanceCost + costFn (neighborPosition.x, neighborPosition.y); if (map.IsOpenTile (neighborPosition.x, neighborPosition.y) && !openList.ContainsKey (Node.KeyFromPostion (neighborPosition))) { Node newPosition = new Node (neighborPosition); newPosition.heuristicCost = (int)Math.Abs (neighborPosition.x - end.x) + (int)Math.Abs (neighborPosition.y - end.y); newPosition.distanceCost = newCost; newPosition.parent = lowestCost; openList[newPosition.Key] = newPosition; } else if (openList.ContainsKey (Node.KeyFromPostion (neighborPosition)) && openList[Node.KeyFromPostion (neighborPosition)].distanceCost > newCost) { openList [Node.KeyFromPostion (neighborPosition)].distanceCost = newCost; openList [Node.KeyFromPostion (neighborPosition)].parent = lowestCost; } } searchCount++; } Node nextn = null; // couldn't find a path to the end if (!closedList.ContainsKey (Node.KeyFromPostion (end))) { // just build a short list containing the neighbor tiles. // eventually this should find "as near as possible" type tiles to move towards // I guess it depends on the application though startNode = new Node (start); Node lowestCost = startNode; for (int i = 0; i < 4; i++) { Vector2i neighborPosition = new Vector2i (lowestCost.position.x + Map.nDir [i, 0], lowestCost.position.y + Map.nDir [i, 1]); int newCost = lowestCost.distanceCost + costFn (neighborPosition.x, neighborPosition.y); if (map.IsOpenTile (neighborPosition.x, neighborPosition.y) && !openList.ContainsKey (Node.KeyFromPostion (neighborPosition))) { Node newPosition = new Node (neighborPosition); newPosition.heuristicCost = (int)Math.Abs (neighborPosition.x - end.x) + (int)Math.Abs (neighborPosition.y - end.y); newPosition.distanceCost = newCost; newPosition.parent = lowestCost; openList [newPosition.Key] = newPosition; } } nextn = findLowestCost (); } else { nextn = closedList [Node.KeyFromPostion (end)]; } // build the step list List<Vector2i> returnList = new List<Vector2i> (); while (nextn != null) { returnList.Add (nextn.position); nextn = nextn.parent; } returnList.Reverse (); return returnList; }
void floodHeight(int x, int y, int marker, ref int[,] buffer, CostCallback fn) { // make sure to only visit each cell once buffer[x,y] = marker; for(int i=0;i<4;i++){ int tx = x+nDir[i,0]; int ty = y+nDir[i,1]; if(tx>=0&&tx<buffer.GetLength(0)&&ty>=0&&ty<buffer.GetLength(1) && layout[tx,ty] == TileType.OPEN && (buffer[tx, ty]==0 || (marker+fn(tx, ty)) < buffer[tx,ty]) ) { floodHeight(tx, ty, marker+fn(tx, ty), ref buffer, fn); } } }
// maybe should just return the next position // this method is super slow, need to rebuild so it isn't public Vector2i GetPath(int startX, int startY, int endX, int endY, CostCallback costFn) { clearBuffer(); floodHeight(endX, endY, 1, ref buffer, costFn); int lowestNeighbor = -1; int lowestNeighborDir = 0; for(int i=0;i<4;i++){ int tx = startX+nDir[i,0]; int ty = startY+nDir[i,1]; if(tx>=0&&tx<buffer.GetLength(0)&&ty>=0&&ty<buffer.GetLength(1) && IsOpenTile(tx, ty) && //!ContainsSnake(tx, ty) && // need to have a delegate for calculating tile movement costs, perhaps pass into the flood height as well (lowestNeighbor == -1 || lowestNeighbor > buffer[tx, ty]) ){ lowestNeighbor = buffer[tx, ty]; lowestNeighborDir = i; } } if (lowestNeighbor == -1) { // return out of map for invalid tile new Vector2i(new int[]{-1, -1}); } return new Vector2i (startX + nDir [lowestNeighborDir, 0], startY + nDir [lowestNeighborDir, 1]); }