Beispiel #1
0
        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);
        }
Beispiel #2
0
        /// <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);
        }
Beispiel #3
0
        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);
        }