private bool IsDiagonalJumpPoint(Direction direction, PathfindingNode currentNode) { // If we're going diagonally need to check all cardinals. // I just just using casts int casts and offset to make it smaller but brain no workyand it wasn't working. // From NorthEast we check (Closed / Open) S - SE, W - NW PathfindingNode openNeighborOne; PathfindingNode closedNeighborOne; PathfindingNode openNeighborTwo; PathfindingNode closedNeighborTwo; switch (direction) { case Direction.NorthEast: openNeighborOne = currentNode.GetNeighbor(Direction.SouthEast); closedNeighborOne = currentNode.GetNeighbor(Direction.South); openNeighborTwo = currentNode.GetNeighbor(Direction.NorthWest); closedNeighborTwo = currentNode.GetNeighbor(Direction.West); break; case Direction.SouthEast: openNeighborOne = currentNode.GetNeighbor(Direction.NorthEast); closedNeighborOne = currentNode.GetNeighbor(Direction.North); openNeighborTwo = currentNode.GetNeighbor(Direction.SouthWest); closedNeighborTwo = currentNode.GetNeighbor(Direction.West); break; case Direction.SouthWest: openNeighborOne = currentNode.GetNeighbor(Direction.NorthWest); closedNeighborOne = currentNode.GetNeighbor(Direction.North); openNeighborTwo = currentNode.GetNeighbor(Direction.SouthEast); closedNeighborTwo = currentNode.GetNeighbor(Direction.East); break; case Direction.NorthWest: openNeighborOne = currentNode.GetNeighbor(Direction.SouthWest); closedNeighborOne = currentNode.GetNeighbor(Direction.South); openNeighborTwo = currentNode.GetNeighbor(Direction.NorthEast); closedNeighborTwo = currentNode.GetNeighbor(Direction.East); break; default: throw new ArgumentOutOfRangeException(); } if ((closedNeighborOne == null || Utils.GetTileCost(_pathfindingArgs, currentNode, closedNeighborOne) == null) && openNeighborOne != null && Utils.GetTileCost(_pathfindingArgs, currentNode, openNeighborOne) != null) { return(true); } if ((closedNeighborTwo == null || Utils.GetTileCost(_pathfindingArgs, currentNode, closedNeighborTwo) == null) && openNeighborTwo != null && Utils.GetTileCost(_pathfindingArgs, currentNode, openNeighborTwo) != null) { return(true); } return(false); }
/// <summary> /// Check to see if the node is a jump point (only works for cardinal directions) /// </summary> private bool IsCardinalJumpPoint(Direction direction, PathfindingNode currentNode) { PathfindingNode openNeighborOne; PathfindingNode closedNeighborOne; PathfindingNode openNeighborTwo; PathfindingNode closedNeighborTwo; switch (direction) { case Direction.North: openNeighborOne = currentNode.GetNeighbor(Direction.NorthEast); closedNeighborOne = currentNode.GetNeighbor(Direction.East); openNeighborTwo = currentNode.GetNeighbor(Direction.NorthWest); closedNeighborTwo = currentNode.GetNeighbor(Direction.West); break; case Direction.East: openNeighborOne = currentNode.GetNeighbor(Direction.NorthEast); closedNeighborOne = currentNode.GetNeighbor(Direction.North); openNeighborTwo = currentNode.GetNeighbor(Direction.SouthEast); closedNeighborTwo = currentNode.GetNeighbor(Direction.South); break; case Direction.South: openNeighborOne = currentNode.GetNeighbor(Direction.SouthEast); closedNeighborOne = currentNode.GetNeighbor(Direction.East); openNeighborTwo = currentNode.GetNeighbor(Direction.SouthWest); closedNeighborTwo = currentNode.GetNeighbor(Direction.West); break; case Direction.West: openNeighborOne = currentNode.GetNeighbor(Direction.NorthWest); closedNeighborOne = currentNode.GetNeighbor(Direction.North); openNeighborTwo = currentNode.GetNeighbor(Direction.SouthWest); closedNeighborTwo = currentNode.GetNeighbor(Direction.South); break; default: throw new ArgumentOutOfRangeException(); } if ((closedNeighborOne == null || !Utils.Traversable(_pathfindingArgs.CollisionMask, closedNeighborOne.CollisionMask)) && (openNeighborOne != null && Utils.Traversable(_pathfindingArgs.CollisionMask, openNeighborOne.CollisionMask))) { return(true); } if ((closedNeighborTwo == null || !Utils.Traversable(_pathfindingArgs.CollisionMask, closedNeighborTwo.CollisionMask)) && (openNeighborTwo != null && Utils.Traversable(_pathfindingArgs.CollisionMask, openNeighborTwo.CollisionMask))) { return(true); } return(false); }
private PathfindingNode GetJumpPoint(PathfindingNode currentNode, Direction direction, PathfindingNode endNode) { var count = 0; while (count < 1000) { count++; var nextNode = currentNode.GetNeighbor(direction); // We'll do opposite DirectionTraversable just because of how the method's setup // Nodes should be 2-way anyway. if (nextNode == null || Utils.GetTileCost(_pathfindingArgs, currentNode, nextNode) == null) { return(null); } if (nextNode == endNode) { return(endNode); } // Horizontal and vertical are treated the same i.e. // They only check in their specific direction // (So Going North means you check NorthWest and NorthEast to see if we're a jump point) // Diagonals also check the cardinal directions at the same time at the same time // See https://harablog.wordpress.com/2011/09/07/jump-point-search/ for original description switch (direction) { case Direction.East: if (IsCardinalJumpPoint(direction, nextNode)) { return(nextNode); } break; case Direction.NorthEast: if (IsDiagonalJumpPoint(direction, nextNode)) { return(nextNode); } if (GetJumpPoint(nextNode, Direction.North, endNode) != null || GetJumpPoint(nextNode, Direction.East, endNode) != null) { return(nextNode); } break; case Direction.North: if (IsCardinalJumpPoint(direction, nextNode)) { return(nextNode); } break; case Direction.NorthWest: if (IsDiagonalJumpPoint(direction, nextNode)) { return(nextNode); } if (GetJumpPoint(nextNode, Direction.North, endNode) != null || GetJumpPoint(nextNode, Direction.West, endNode) != null) { return(nextNode); } break; case Direction.West: if (IsCardinalJumpPoint(direction, nextNode)) { return(nextNode); } break; case Direction.SouthWest: if (IsDiagonalJumpPoint(direction, nextNode)) { return(nextNode); } if (GetJumpPoint(nextNode, Direction.South, endNode) != null || GetJumpPoint(nextNode, Direction.West, endNode) != null) { return(nextNode); } break; case Direction.South: if (IsCardinalJumpPoint(direction, nextNode)) { return(nextNode); } break; case Direction.SouthEast: if (IsDiagonalJumpPoint(direction, nextNode)) { return(nextNode); } if (GetJumpPoint(nextNode, Direction.South, endNode) != null || GetJumpPoint(nextNode, Direction.East, endNode) != null) { return(nextNode); } break; default: throw new ArgumentOutOfRangeException(nameof(direction), direction, null); } currentNode = nextNode; } Logger.WarningS("pathfinding", "Recursion found in JPS pathfinder"); return(null); }