public void Init() { f = 0; g = 0; h = 0; parent = null; node = null; openList = null; isClosedFlag = false; isOpenFlag = false; isBlockedFlag = false; isFreeFlag = false; }
// Takes a look at an adjacent node based on a set direction. Checks if this is open to update it's F value. // If not, creates a new navwrapper associated with this adjacent node and adds it to the open bins. (after calculating its f value). private void CheckAdjacent(NavWrapper currentNavWrapper, DiagonalDirectionEnum dir) { int offsetx = 0, offsety = 0; if (layout == GridLayout.CellLayout.Hexagon) { Direction.GetOffset(dir, ref offsetx, ref offsety, (currentNavWrapper.node.GetIndex().y % 2) == 0); } else { Direction.GetOffset(dir, ref offsetx, ref offsety); } Vector3Int adjIndex = new Vector3Int(currentNavWrapper.node.GetIndex().x + offsetx, currentNavWrapper.node.GetIndex().y + offsety, Controls.GetTileZpf()); NavNode adjNode; adjNode = pf.GetNode(adjIndex); if (adjNode == null || adjNode.IsBlocked()) { return; } if (IsDirectionDiagonal(dir) && AreAdjacentTilesBlocked(currentNavWrapper.node, offsetx, offsety)) { return; } NavWrapper adjNavWrapper = CreateNavWrapper(adjNode);// IsInOpenList(adjNode); // Check if its in the open list. if (adjNavWrapper.isOpenFlag) { // Recalculate the F cost. if (currentNavWrapper.f + NavNode.DirectionalGCost(dir) < adjNavWrapper.g) { adjNavWrapper.g = currentNavWrapper.g + NavNode.DirectionalGCost(dir) + adjNavWrapper.node.GetMovementPenalty(); adjNavWrapper.f = adjNavWrapper.h + adjNavWrapper.g; } } else { adjNavWrapper.parent = currentNavWrapper; adjNavWrapper.g = currentNavWrapper.g + NavNode.DirectionalGCost(dir) + adjNavWrapper.node.GetMovementPenalty(); adjNavWrapper.h = CalculateHScore(currentNavWrapper.node); adjNavWrapper.f = adjNavWrapper.h + adjNavWrapper.g; AddToOpenList(adjNavWrapper); //TODO only add to open list if its f value is less than the f value it was closed with. //Otherwise could end up recalculating a node that has already been evaluated, but froma worse starting point } }
bool AreAdjacentTilesBlocked(NavNode node, int offsetX, int offsetY) { Vector3Int adjIndex = new Vector3Int(node.GetIndex().x + offsetX, currentNavWrapper.node.GetIndex().y, Controls.GetTileZpf()); NavNode adjNode = pf.GetNode(adjIndex); if (adjNode == null || adjNode.IsBlocked()) { return(true); } adjIndex.x -= offsetX; adjIndex.y += offsetY; adjNode = pf.GetNode(adjIndex); if (adjNode == null || adjNode.IsBlocked()) { return(true); } return(false); }
private bool CreatePath(NavNode startNode, NavNode endNode) { if (startNode == null || endNode == null || startNode.IsIgnorable() || endNode.IsIgnorable()) { // The start and/or end tile are invalid. return(false); } endWrapper = CreateNavWrapper(endNode); currentNavWrapper = CreateNavWrapper(startNode); AddToOpenList(currentNavWrapper); isProcessingFlag = true; hasFailedFlag = false; pf.GetPathQueries().AddLast(this); return(true); }
// Takes a look at an adjacent node based on a set direction. Checks if this is open to update it's F value. // If not, creates a new navwrapper associated with this adjacent node and adds it to the open bins. (after calculating its f value). private void CheckAdjacent(NavWrapper currentNavWrapper, DiagonalDirectionEnum dir) { int offsetx = 0, offsety = 0; if (layout == GridLayout.CellLayout.Hexagon) { Direction.GetOffset(dir, ref offsetx, ref offsety, (currentNavWrapper.node.GetIndex().y % 2) == 0); } else { Direction.GetOffset(dir, ref offsetx, ref offsety); } Vector3Int adjIndex = new Vector3Int(currentNavWrapper.node.GetIndex().x + offsetx, currentNavWrapper.node.GetIndex().y + offsety, 0); NavNode adjNode; adjNode = pf.GetNode(adjIndex); if (adjNode == null || adjNode.IsIgnorable()) { return; } NavWrapper adjNavWrapper = CreateNavWrapper(adjNode);// IsInOpenList(adjNode); // Check if its in the open list. if (adjNavWrapper.isOpenFlag) { // Recalculate the F cost. if (currentNavWrapper.f + NavNode.DirectionalGCost(dir) < adjNavWrapper.g) { adjNavWrapper.g = currentNavWrapper.g + NavNode.DirectionalGCost(dir) + adjNavWrapper.node.GetMovementPenalty(); adjNavWrapper.f = adjNavWrapper.h + adjNavWrapper.g; } } else { adjNavWrapper.parent = currentNavWrapper; adjNavWrapper.g = currentNavWrapper.g + NavNode.DirectionalGCost(dir) + adjNavWrapper.node.GetMovementPenalty(); adjNavWrapper.h = CalculateHScore(currentNavWrapper.node); adjNavWrapper.f = adjNavWrapper.h + adjNavWrapper.g; AddToOpenList(adjNavWrapper); } }
// Takes the inputted coordinates and finds the nodes associated with them. Then begins to create a path. public bool StartPath(Vector3Int startPos, Vector3Int endPos, List <Vector3Int> refPath, bool searchUsesDiagonals, int amortizeoverride = 0) { // If this Path is currently processing another path then reset it. if (isProcessingFlag) { Reset(); } useDiagonals = searchUsesDiagonals; NavNode startNode = pf.GetNode(startPos); NavNode endNode = pf.GetNode(endPos); refList = refPath; if (amortizeoverride > 0) { overridedMaxAmortizevalue = amortizeoverride; } return(CreatePath(startNode, endNode)); }
// Gets the next point in the path point list based on the passed in index. // This point is returned by reference as a world position (nextPoint). Returns true if there is a valid next point. // If it reaches the end or the path has failed it returns false. // If the next point in the point list is blocked a new path is generated. public bool GetNextPointIndex(ref Vector3 nextPoint, ref int index) { //TODO make it so we can check multiple points ahead to regenerate a path if //there is a blockage coming sooner than the very next node // We couldn't generate a path OR we are still waiting for the path to be generated. if (!IsGenerated()) { return(false); } index++; if (index < pathpoints.Count) { // Check to see if this node is blocked at this point. Vector3 worldpos = GetPathPointWorld(index); NavNode node = pf.GetNode(worldpos); if (node.IsBlocked()) { // Create a new path if the previous path is no longe usuable. if (isdynamicflag) { CreatePath(GetPathPointWorld(index - 1), endpos, searchWithDiagonals, true); } else { CreatePath(startpos, endpos, searchWithDiagonals, false); } return(false); } else { // We successfully found the next point. nextPoint = worldpos; return(true); } } // We reached the end of our path. return(false); }
// Gets the previous point in the path point list based on the passed in index. // This point is returned by reference as a world position (previousPoint). Returns true if there is a valid next point. // If it reaches the end or the path has failed it returns false. // If the next point in the point list is blocked a new path is generated. public bool GetPreviousPointIndex(ref Vector3 previousPoint, ref int index) { // We couldn't generate a path OR we are still waiting for a path. if (!IsGenerated()) { return(false); } index--; if (index >= 0) { // Check to see if this node is blocked at this point. Vector3 worldpos = GetPathPointWorld(index); NavNode node = pf.GetNode(worldpos); if (node.IsBlocked()) // Create a new path if the previous path is no longer usuable. { if (isdynamicflag) { CreatePath(GetPathPointWorld(index + 1), startpos, searchWithDiagonals, true); } else { CreatePath(endpos, startpos, searchWithDiagonals, false); } return(false); } else { previousPoint = worldpos; return(true); } } return(false); }
// Calculates the manhatten distance from the current node to the end node. private int CalculateHScore(NavNode currentNode) { return(Mathf.Abs(currentNode.GetIndex().x - endWrapper.node.GetIndex().x) + Mathf.Abs(currentNode.GetIndex().y - endWrapper.node.GetIndex().y)); }