public List<CCPoint> FindPath (CCPoint start, CCPoint end) { startTile = mapLayer.ClosestTileCoordAtNodePosition(start); endTile = mapLayer.ClosestTileCoordAtNodePosition(end); InitializeMap(); startNode = nodes[startTile.Column, startTile.Row]; startNode.State = Node.NodeState.open; endNode = nodes[endTile.Column, endTile.Row]; List<CCPoint> path = new List<CCPoint>(); bool success = Search(startNode); if(success) { // If a path was found, follow the parents from the end node to build a list of locations Node node = this.endNode; while (node.ParentNode != null) { var centeredPoint = mapLayer.TilePosition(node.Location); centeredPoint = new CCPoint(centeredPoint.X + map.TileTexelSize.Width / 2, centeredPoint.Y + map.TileTexelSize.Width / 2); path.Add(centeredPoint); node = node.ParentNode; } // Reverse the list so it's in the correct order when returned path.Reverse(); } return path; }
List<Node> AdjacentValidNodes(Node fromNode) { List<Node> adjacentNodes = new List<Node>(); IEnumerable<CCTileMapCoordinates> nextLocations = GetAdjacentLocations(fromNode.Location); foreach (var location in nextLocations) { int column = location.Column; int row = location.Row; // Stay within the grid's boundaries //CHECK if (column < 0 || column >= map.MapDimensions.Size.Width || row < 0 || row >= map.MapDimensions.Size.Height) continue; Node node = this.nodes[column, row]; // Ignore non-walkable nodes if (!node.IsWalkable) continue; // Ignore already-closed nodes if (node.State == Node.NodeState.closed) continue; // Already-open nodes are only added to the list if their G-value is lower going via this route. if (node.State == Node.NodeState.open) { float traversalCost = Node.GetTraversalCost(node.Location, node.ParentNode.Location); float gTemp = fromNode.G + traversalCost; if (gTemp < node.G) { node.ParentNode = fromNode; adjacentNodes.Add(node); } } else { // If it's untested, set the parent and flag it as 'Open' for consideration node.ParentNode = fromNode; node.State = Node.NodeState.open; adjacentNodes.Add(node); } } return adjacentNodes; }
Boolean Search(Node currentNode) { currentNode.State = Node.NodeState.closed; var adjacentNodes = AdjacentValidNodes(currentNode); // Sort by F-value so that the shortest possible routes are considered first adjacentNodes.Sort((node1, node2) => node1.F.CompareTo(node2.F)); foreach(var nextNode in adjacentNodes) { if (nextNode.Location.Row == endTile.Row && nextNode.Location.Column == endTile.Column) return true; else { if (Search(nextNode)) return true; } } return false; }