private GlobalHelper() { curLevelTileGrid_ = null; }
public void setCurrentLevelTileGrid(TileGrid grid) { curLevelTileGrid_ = grid; }
private static TileIndex getNearest(TileGrid grid, TileIndex start, TileIndex destination, float radius, Height height) { radius = radius / (TileGrid.TILEHEIGHT + TileGrid.TILEWIDTH) / 2; Tile dest = grid.getTile(destination); if (!dest.collides(height, radius)) { return destination; } short manhattan = 1; // Expand outward by increasing the manhattan distance // Until finding some subset of tiles which we can walk on // TODO // Don't use heap space here List<TileIndex> closest = new List<TileIndex>(); while (closest.Count == 0) { Tile cur; int newX; int newY; for (short i = 0; i < manhattan - 1; i++) { // Quadrant I newX = destination.x_ + i; newY = destination.y_ + (manhattan - i); cur = grid.getTile(newX, newY); if (!cur.collides(height, radius)) { closest.Add(new TileIndex((short)newX, (short)newY)); } // Quadrant II newX = destination.x_ - i; newY = destination.y_ + (manhattan - i); cur = grid.getTile(newX, newY); if (!cur.collides(height, radius)) { closest.Add(new TileIndex((short)newX, (short)newY)); } // Quadrant III newX = destination.x_ - i; newY = destination.y_ - (manhattan - i); cur = grid.getTile(newX, newY); if (!cur.collides(height, radius)) { closest.Add(new TileIndex((short)newX, (short)newY)); } // Quadrant IV newX = destination.x_ + i; newY = destination.y_ - (manhattan - i); cur = grid.getTile(newX, newY); if (!cur.collides(height, radius)) { closest.Add(new TileIndex((short)newX, (short)newY)); } } manhattan++; if (manhattan > 10) { return new TileIndex(-1, -1); } } // We've found walkable tiles, and they are all the same manhattan // distance from the destination, so pick closest to the start // TODO // Determine whether it's better to pick closest real distance to // destination first TileIndex best = new TileIndex(-1, -1); float bestScore = float.MaxValue; for (int i = 0; i < closest.Count; i++) { float score = CommonFunctions.distance(closest[i], start); if (score < bestScore) { bestScore = score; best = closest[i]; } } return best; }
protected static void setupSearch(TileGrid grid, TileIndex start, TileIndex destination, float radius, Height height) { // Initialize the static structures used by the search reset(); start_ = start; goal_ = destination; // Project our start and goal nodes into the search space, if possible // TODO // For now, if they are farther apart than the size of the search space in // any dimension, we give up - in the future, they will try to get as close // as possible short manhattanX = (short)Math.Abs(start_.x_ - goal_.x_); short manhattanY = (short)Math.Abs(start_.y_ - goal_.y_); short leftOffset = (short)Math.Floor((SEARCH_SPACE_WIDTH - manhattanX) / 2.0f); short rightOffset = (short)Math.Ceiling((SEARCH_SPACE_WIDTH - manhattanX) / 2.0f); short bottomOffset = (short)Math.Floor((SEARCH_SPACE_HEIGHT - manhattanY) / 2.0f); short topOffset = (short)Math.Ceiling((SEARCH_SPACE_HEIGHT - manhattanY) / 2.0f); gridXOffset_ = (short)(Math.Min(start_.x_, goal_.x_) - leftOffset); gridYOffset_ = (short)(Math.Min(start_.y_, goal_.y_) - topOffset); if (gridXOffset_ < 0) gridXOffset_ = 0; if (gridYOffset_ < 0) gridYOffset_ = 0; start_.x_ -= gridXOffset_; start_.y_ -= gridYOffset_; goal_.x_ -= gridXOffset_; goal_.y_ -= gridYOffset_; searchRadius_ = (float)(radius / ((TileGrid.TILEWIDTH + TileGrid.TILEHEIGHT) / 2.0f)); grid_ = grid; searchHeight_ = height; }
public static List<TileIndex> calculateNearbyPath(TileGrid grid, Vector2 start, Vector2 destination, float radius, Height height) { return calculateNearbyPath(grid, grid.getTileIndex(start), grid.getTileIndex(destination), radius, height); }
public static List<TileIndex> calculateNearbyPath(TileGrid grid, TileIndex start, TileIndex destination, float radius, Height height) { TileIndex newdest = getNearest(grid, start, destination, radius, height); if (newdest.x_ == -1 || newdest.y_ == -1) { //throw new Exception("AStarPathfinder failed to find a nearest tile!"); return null; } return calculateExactPath(grid, start, newdest, radius, height); }
/// <summary> /// Run the A* algorithm to get a navigation path. /// </summary> /// <param name="grid">The area being searched</param> /// <param name="start">Index of the start tile.</param> /// <param name="destination">Index of the destination tile.</param> /// <param name="radius">Radius of the character performing the search</param> /// <param name="tileHeight">Height of the character performing the search</param> /// <returns>Waypoints which should allow the character to reach the goal.</returns> public static List<TileIndex> calculateExactPath(TileGrid grid, TileIndex start, TileIndex destination, float radius, Height height) { #if DEBUG clock.Start(); #endif setupSearch(grid, start, destination, radius, height); //Console.WriteLine("Pathfind Start: " + start_.x_ + "," + start_.y_); //Console.WriteLine("Pathfind Goal: " + goal_.x_ + "," + goal_.y_); TileIndex cur = start_; searchSpace_[cur.x_, cur.y_].g = 0; searchSpace_[cur.x_, cur.y_].f = heuristicDistance(cur.x_, cur.y_); searchSpace_[cur.x_, cur.y_].parent = new TileIndex(-1, -1); // stack touched_[cur.x_, cur.y_] = true; // As long as we aren't at the goal, keep expanding outward and checking // the next most promising node while (!TileIndex.equals(goal_, cur)) { searchSpace_[cur.x_, cur.y_].open = false; expand(ref cur, searchSpace_[cur.x_, cur.y_].g); // If we are out of nodes to check, no path exists if (openlist_.Count == 0) { #if DEBUG clock.Stop(); #endif return null; } else { cur = getNext(); } } #if DEBUG clock.Stop(); #endif return recreatePath(); }