/* * Handle a collision between a unit and wall */ public void CheckWallCollision(GameUnit unit, Map map) { List<Vector2> dirs = new List<Vector2>(); dirs.Add(new Vector2(0, 1)); dirs.Add(new Vector2(1, 0)); dirs.Add(new Vector2(0, -1)); dirs.Add(new Vector2(-1, 0)); dirs.Add(new Vector2(1, 1)); dirs.Add(new Vector2(1, -1)); dirs.Add(new Vector2(-1, 1)); dirs.Add(new Vector2(-1, -1)); foreach (Vector2 dir in dirs) { if(!map.canMoveToWorldPos(unit.Position + dir * unit.Size/2)) { int i = 0; while (i++ < unit.Size && !map.canMoveToWorldPos(unit.Position + dir * unit.Size/2)) { unit.Position -= dir; } } } }
/* * Finds the tile based path from start to end, given in world coordinates */ public static List<Vector2> findPath(Map map, Vector2 start, Vector2 end, int limit, bool exploreAll) { if (!map.canMoveToWorldPos(end)) { return null; } BinaryHeap<PathNode> node_queue = new BinaryHeap<PathNode>(new NodeCompararer()); // use comparator HashSet<PathNode> visited = new HashSet<PathNode>(); Vector2 mapStart = map.translateWorldToMap(start); Vector2 mapEnd = map.translateWorldToMap(end); Point startPoint = new Point((int)mapStart.X, (int)mapStart.Y); Point endPoint = new Point((int)mapEnd.X, (int)mapEnd.Y); PathNode startNode = new PathNode(startPoint); startNode.G_score = 0; startNode.H_score = calculateHeuristic(startPoint, endPoint); node_queue.Insert(startNode); while (node_queue.Count > 0) { PathNode current = node_queue.RemoveRoot(); // O(logn) PathNode current2 = getMin(node_queue.GetList()); if (!exploreAll && current.Pos.Equals(endPoint)) { return constructPath(current); } if (current.G_score + 1 > limit) // Don't explore tiles too far { continue; } visited.Add(current); List<Point> adj = getAdjacent(current.Pos); foreach (Point position in adj) { if (visited.Contains(new PathNode(position)) || !map.canMoveTo(position.X, position.Y)) { continue; } PathNode node = nodeAtPosition(node_queue, position); // O(n) if (node != null && current.G_score + 1 < node.G_score) { node.G_score = current.G_score + 1; node.Parent = current; node_queue.RemoveNode(node); // O(n) node_queue.Insert(node); // O(logn) } else if(node == null) { node = new PathNode(position); node.G_score = current.G_score + 1; node.H_score = calculateHeuristic(node.Pos, endPoint); node.Parent = current; node_queue.Insert(node); // O(logn) } } } if (!exploreAll) return null; // Populate the point location map, initialize with (-1, -1) pointLocMap = new Vector2[map.HeightTiles, map.WidthTiles]; for (int i = 0; i < pointLocMap.GetLength(0); i++) { for (int j = 0; j < pointLocMap.GetLength(1); j++) { pointLocMap[i, j] = new Vector2(-1, -1); } } pointLocMap[(int)mapStart.Y, (int)mapStart.X] = mapStart; foreach(PathNode node in visited) { if (pointLocMap[node.Pos.Y, node.Pos.X] == new Vector2(-1, -1)) { Vector2 nodePos = new Vector2(node.Pos.X * Map.TILE_SIZE + Map.TILE_SIZE/2, node.Pos.Y * Map.TILE_SIZE + Map.TILE_SIZE/2); if (map.rayCastHasObstacle(nodePos, end, Map.TILE_SIZE/3)) { pointLocMap[node.Pos.Y, node.Pos.X] = new Vector2(node.Parent.Pos.X, node.Parent.Pos.Y); } else { pointLocMap[node.Pos.Y, node.Pos.X] = mapEnd; } //collapseBlockedPaths(node, map); } } return null; }