/// <summary> /// Find one nonobstacle neighbor at destinationTilePosition. /// If destinationTilePosition is not obstacle, destinationTilePosition is not changed, return ture. /// Otherwise return ture if finded one nonobstacle neighbor and destinationTilePosition is assigned to that neighbor's tile position. /// Return false if not finded. /// </summary> /// <param name="finder">The finder</param> /// <param name="destinationTilePosition"></param> /// <returns></returns> public static bool FindNonobstacleNeighborOrItself(Character finder, ref Vector2 destinationTilePosition) { if (finder.HasObstacle(destinationTilePosition) || MapBase.Instance.IsObstacleForCharacter(destinationTilePosition)) { var neighbors = FindAllNeighbors(destinationTilePosition); foreach (var neighbor in neighbors) { if (!finder.HasObstacle(neighbor) && !MapBase.Instance.IsObstacleForCharacter(neighbor)) { destinationTilePosition = neighbor; return(true); } } return(false); } return(true); }
//Returned path is in pixel position public static LinkedList <Vector2> FindPathSimple(Character finder, Vector2 startTile, Vector2 endTile, int maxTry) { if (startTile == endTile) { return(null); } if (MapBase.Instance.IsObstacleForCharacter(endTile)) { return(null); } var cameFrom = new Dictionary <Vector2, Vector2>(); var frontier = new C5.IntervalHeap <Node <Vector2> >(); frontier.Add(new Node <Vector2>(startTile, 0f)); var tryCount = 0; while (!frontier.IsEmpty) { if (tryCount++ > maxTry) { break; } var current = frontier.DeleteMin().Location; if (current == endTile) { break; } if (finder.HasObstacle(current) && current != startTile) { continue; } foreach (var neighbor in FindNeighbors(current, finder.CanMoveDirCount)) { if (!cameFrom.ContainsKey(neighbor)) { var priority = GetTilePositionCost(neighbor, endTile); frontier.Add(new Node <Vector2>(neighbor, priority)); cameFrom[neighbor] = current; } } } return(GetPath(cameFrom, startTile, endTile)); }
/// <summary> /// If finder can move linearly, return the path. /// </summary> /// <param name="finder"></param> /// <param name="fromTilePosition"></param> /// <param name="toTilePosition"></param> /// <returns></returns> public static LinkedList <Vector2> GetLinearlyMovePath(Character finder, Vector2 fromTilePosition, Vector2 toTilePosition) { if (fromTilePosition == toTilePosition) { return(null); } if (finder.HasObstacle(toTilePosition)) { return(null); } var tileDistance = GetPathTileDistance(fromTilePosition, toTilePosition); var path = FindPathPerfect(finder, fromTilePosition, toTilePosition, tileDistance * 16); if (path != null && (path.Count - 1) == tileDistance) { return(path); } return(null); }
/// <summary> /// Test finder can move linearly. /// </summary> /// <param name="finder"></param> /// <param name="fromTilePosition"></param> /// <param name="toTilePosition"></param> /// <returns></returns> public static bool CanLinearlyMove(Character finder, Vector2 fromTilePosition, Vector2 toTilePosition) { if (fromTilePosition == toTilePosition) { return(true); } if (finder.HasObstacle(toTilePosition)) { return(false); } var tileDistance = GetPathTileDistance(fromTilePosition, toTilePosition); var path = FindPathPerfect(finder, fromTilePosition, toTilePosition, tileDistance * 16); if (path != null && (path.Count - 1) == tileDistance) { return(true); } return(false); }
//Returned path is in pixel position public static LinkedList <Vector2> FindPathPerfect(Character finder, Vector2 startTile, Vector2 endTile, int maxTryCount) { if (startTile == endTile) { return(null); } if (MapBase.Instance.IsObstacleForCharacter(endTile)) { return(null); } var cameFrom = new Dictionary <Vector2, Vector2>(); var costSoFar = new Dictionary <Vector2, float>(); var frontier = new C5.IntervalHeap <Node <Vector2> >(); frontier.Add(new Node <Vector2>(startTile, 0f)); costSoFar[startTile] = 0f; var tryCount = 0; //For performance //Decrease max try count when fps low //switch ((Fps.FpsValue+5)/10) //{ // case 5: // maxTryCount = 30; // break; // case 4: // case 2: // case 1: // case 0: // maxTryCount = 15; // break; //} while (!frontier.IsEmpty) { if (maxTryCount != -1 && tryCount++ > maxTryCount) { break; } var current = frontier.DeleteMin().Location; if (current.Equals(endTile)) { break; } if (finder.HasObstacle(current) && current != startTile) { continue; } foreach (var next in FindNeighbors(current, finder.CanMoveDirCount)) { var newCost = costSoFar[current] + GetTilePositionCost(current, next); if (!costSoFar.ContainsKey(next) || newCost < costSoFar[next]) { costSoFar[next] = newCost; var priority = newCost + GetTilePositionCost(endTile, next); frontier.Add(new Node <Vector2>(next, priority)); cameFrom[next] = current; } } } return(GetPath(cameFrom, startTile, endTile));; }
public static bool HasObstacle(Character finder, Vector2 tilePosition) { return(finder.HasObstacle(tilePosition) || MapBase.Instance.IsObstacleForCharacter(tilePosition)); }
public static bool HasObstacle(Character finder, Vector2 tilePosition) { return(finder.HasObstacle(tilePosition) || Globals.TheMap.IsObstacleForCharacter(tilePosition)); }