//populate the cached path of the given AI with the path from startPoint to endPoint private void GeneratePath(int aiAgentIndex, NodeIndex startPoint, NodeIndex endPoint, Node topLevelNode) { bool destinationWithinCurrentNode = startPoint.EqualAtDepth(endPoint, index.GetMaxDepth()); Node start = internalNodes[startPoint.GetIndexAtDepth(index.GetMaxDepth() + 1)]; Node end; if (!destinationWithinCurrentNode) { end = topLevelNode.GetNode(endPoint); } else { end = internalNodes[endPoint.GetIndexAtDepth(index.GetMaxDepth() + 1)]; } //If pathfinding in the lowest layer use the cheaper pathfinding method, else use A* if (startPoint.GetMaxDepth() == index.GetMaxDepth() + 1) { lastPaths[aiAgentIndex] = Pathfinder.GetNextDestNode(start, end, internalNodes, topLevelNode); } else { lastPaths[aiAgentIndex] = Pathfinder.AstarPathfind(start, end, internalNodes); } }
//recursively add up the positions of all nodes in the specified index to get the position in world space //this way, if a parent node is moved then all of it's children will move with it automatically public Physics.Vector2D GetNodePosition(NodeIndex nodeIndex) { //if this node is the node specified return it's current position if (nodeIndex == index) { return(position); } //if not then return the position of the child node specified in nodeIndex, plus this nodes position else { return(internalNodes[nodeIndex.GetIndexAtDepth(index.GetMaxDepth() + 1)].GetNodePosition(nodeIndex) + position); } }
//return the node described by the node index public Node GetNode(NodeIndex nodeToFind) { //if the requested node is the current node then return the current node if (index == nodeToFind) { return(this); } //if the node isn't local then there's nothing to return if (!index.EqualAtDepth(nodeToFind, index.GetMaxDepth())) { return(null); } //delegate the request to the child node specified in the nodeToFind index int nextNodeDown = nodeToFind.GetIndexAtDepth(index.GetMaxDepth() + 1); if (nextNodeDown >= internalNodes.Count || nextNodeDown < 0) { return(null); } return(internalNodes[nextNodeDown].GetNode(nodeToFind)); }
//return the path from the start point to the destination point public List <NodeIndex> GetPath(int aiAgentIndex, NodeIndex startPoint, NodeIndex endPoint, Node topLevelNode) { if (lastPaths == null || lastPaths.Count <= aiAgentIndex) { return(null); } if (startPoint == endPoint) { return(null); } //if the start and end point are both in the same child node, delegate to that child int nextDepth = index.GetMaxDepth() + 1; if (startPoint.EqualAtDepth(endPoint, nextDepth)) { if (startPoint.GetIndexAtDepth(nextDepth) >= internalNodes.Count) { return(null); } if (startPoint.GetIndexAtDepth(nextDepth) < 0) { return(null); } return(internalNodes[startPoint.GetIndexAtDepth(nextDepth)].GetPath(aiAgentIndex, startPoint, endPoint, topLevelNode)); } //if there is no cached path for the specified AI if (lastPaths[aiAgentIndex] == null || lastPaths[aiAgentIndex].Count < 1 || lastDestinations[aiAgentIndex] != endPoint || lastOrigins[aiAgentIndex] != startPoint) { bool present = false; //check the cached paths of the other AI's to see if any of them would be suitable for (int i = 0; i < lastOrigins.Count; ++i) { if (i != aiAgentIndex && (lastOrigins[i] == startPoint) && (lastDestinations[i] == endPoint)) { lastPaths[aiAgentIndex] = new List <NodeIndex>(lastPaths[i]); lastOrigins[aiAgentIndex] = startPoint; lastDestinations[aiAgentIndex] = endPoint; i = lastOrigins.Count; present = true; } } //if not then generate the path if (!present) { GeneratePath(aiAgentIndex, startPoint, endPoint, topLevelNode); if (lastPaths[aiAgentIndex] == null || lastPaths[aiAgentIndex].Count < 1) { return(null); } lastDestinations[aiAgentIndex] = endPoint; lastOrigins[aiAgentIndex] = startPoint; } } //if the next level is the deepest level then return this level's path if (startPoint.GetMaxDepth() == nextDepth) { return(lastPaths[aiAgentIndex]); } //If there is only one node in the path then something is wrong, because by this point the start and endpoint should be in different nodes if (lastPaths[aiAgentIndex].Count < 2) { return(null); } int localStart = lastPaths[aiAgentIndex][0].GetIndexAtDepth(nextDepth); NodeIndex localDest = lastPaths[aiAgentIndex][1]; //find the path within the first node of the current level path and return that //Once the path has been found, pathfind within it's first node to determine how to get to the second node of the path return(internalNodes[localStart].GetPath(aiAgentIndex, startPoint, localDest, topLevelNode)); }