// The "cost" to moving to neighbour/adjacent nodes. public static int DirectionalGCost(DiagonalDirectionEnum dir) { switch (dir) { case DiagonalDirectionEnum.UpLeft: return(14); case DiagonalDirectionEnum.Up: return(10); case DiagonalDirectionEnum.UpRight: return(14); case DiagonalDirectionEnum.Right: return(10); case DiagonalDirectionEnum.DownRight: return(14); case DiagonalDirectionEnum.Down: return(10); case DiagonalDirectionEnum.DownLeft: return(14); } return(10); }
bool IsDirectionDiagonal(DiagonalDirectionEnum direction) { switch (direction) { case DiagonalDirectionEnum.DownLeft: case DiagonalDirectionEnum.DownRight: case DiagonalDirectionEnum.UpLeft: case DiagonalDirectionEnum.UpRight: return(true); } return(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 } }
// Returns the coordinate offset based on a direction for a rectangular or isometric grid layout. public static void GetOffset(DiagonalDirectionEnum dir, ref int xoffset, ref int yoffset) { switch (dir) { case DiagonalDirectionEnum.UpLeft: xoffset = -1; yoffset = 1; break; case DiagonalDirectionEnum.Up: xoffset = 0; yoffset = 1; break; case DiagonalDirectionEnum.UpRight: xoffset = 1; yoffset = 1; break; case DiagonalDirectionEnum.Right: xoffset = 1; yoffset = 0; break; case DiagonalDirectionEnum.DownRight: xoffset = 1; yoffset = -1; break; case DiagonalDirectionEnum.Down: xoffset = 0; yoffset = -1; break; case DiagonalDirectionEnum.DownLeft: xoffset = -1; yoffset = -1; break; case DiagonalDirectionEnum.Left: xoffset = -1; yoffset = 0; break; } }
// 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); } }