示例#1
0
        private static void identifySuccessors(JumpPointParam iParam, Node iNode)
        {
            HeuristicDelegate   tHeuristic = iParam.HeuristicFunc;
            IntervalHeap <Node> tOpenList  = iParam.openList;
            int     tEndX = iParam.EndNode.x;
            int     tEndY = iParam.EndNode.y;
            GridPos tNeighbor;
            GridPos tJumpPoint;
            Node    tJumpNode;

            List <GridPos> tNeighbors = findNeighbors(iParam, iNode);

            for (int i = 0; i < tNeighbors.Count; i++)
            {
                tNeighbor = tNeighbors[i];
                if (iParam.CurIterationType == IterationType.RECURSIVE)
                {
                    tJumpPoint = jump(iParam, tNeighbor.x, tNeighbor.y, iNode.x, iNode.y);
                }
                else
                {
                    tJumpPoint = jumpLoop(iParam, tNeighbor.x, tNeighbor.y, iNode.x, iNode.y);
                }
                if (tJumpPoint != null)
                {
                    tJumpNode = iParam.SearchGrid.GetNodeAt(tJumpPoint.x, tJumpPoint.y);
                    if (tJumpNode == null)
                    {
                        if (iParam.EndNode.x == tJumpPoint.x && iParam.EndNode.y == tJumpPoint.y)
                        {
                            tJumpNode = iParam.SearchGrid.GetNodeAt(tJumpPoint);
                        }
                    }
                    if (tJumpNode.isClosed)
                    {
                        continue;
                    }
                    // include distance, as parent may not be immediately adjacent:
                    float tCurNodeToJumpNodeLen = tHeuristic(Math.Abs(tJumpPoint.x - iNode.x), Math.Abs(tJumpPoint.y - iNode.y));
                    float tStartToJumpNodeLen   = iNode.startToCurNodeLen + tCurNodeToJumpNodeLen; // next `startToCurNodeLen` value

                    if (!tJumpNode.isOpened || tStartToJumpNodeLen < tJumpNode.startToCurNodeLen)
                    {
                        tJumpNode.startToCurNodeLen        = tStartToJumpNodeLen;
                        tJumpNode.heuristicCurNodeToEndLen = (tJumpNode.heuristicCurNodeToEndLen == null ? tHeuristic(Math.Abs(tJumpPoint.x - tEndX), Math.Abs(tJumpPoint.y - tEndY)) : tJumpNode.heuristicCurNodeToEndLen);
                        tJumpNode.heuristicStartToEndLen   = tJumpNode.startToCurNodeLen + tJumpNode.heuristicCurNodeToEndLen.Value;
                        tJumpNode.parent = iNode;

                        if (!tJumpNode.isOpened)
                        {
                            tOpenList.Add(tJumpNode);
                            tJumpNode.isOpened = true;
                        }
                    }
                }
            }
        }
示例#2
0
        public JumpPointParam(JumpPointParam b) : base(b)
        {
            m_heuristic = b.m_heuristic;
            CurEndNodeUnWalkableTreatment = b.CurEndNodeUnWalkableTreatment;

            openList = new IntervalHeap <Node>();
            openList.AddAll(b.openList);

            CurIterationType = b.CurIterationType;
        }
示例#3
0
        public static List <GridPos> FindPath(JumpPointParam iParam)
        {
            IntervalHeap <Node> tOpenList = iParam.openList;
            Node tStartNode = iParam.StartNode;
            Node tEndNode   = iParam.EndNode;
            Node tNode;
            bool revertEndNodeWalkable = false;

            // set the `g` and `f` value of the start node to be 0
            tStartNode.startToCurNodeLen      = 0;
            tStartNode.heuristicStartToEndLen = 0;

            // push the start node into the open list
            tOpenList.Add(tStartNode);
            tStartNode.isOpened = true;

            if (iParam.CurEndNodeUnWalkableTreatment == EndNodeUnWalkableTreatment.ALLOW && !iParam.SearchGrid.IsWalkableAt(tEndNode.x, tEndNode.y))
            {
                iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, true);
                revertEndNodeWalkable = true;
            }

            // while the open list is not empty
            while (tOpenList.Count > 0)
            {
                // pop the position of node which has the minimum `f` value.
                tNode          = tOpenList.DeleteMin();
                tNode.isClosed = true;

                if (tNode.Equals(tEndNode))
                {
                    if (revertEndNodeWalkable)
                    {
                        iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, false);
                    }
                    return(Node.Backtrace(tNode)); // rebuilding path
                }

                identifySuccessors(iParam, tNode);
            }

            if (revertEndNodeWalkable)
            {
                iParam.SearchGrid.SetWalkableAt(tEndNode.x, tEndNode.y, false);
            }

            // fail to find the path
            return(new List <GridPos>());
        }
示例#4
0
        private static List <GridPos> findNeighbors(JumpPointParam iParam, Node iNode)
        {
            Node tParent = (Node)iNode.parent;
            //var diagonalMovement = Util.GetDiagonalMovement(iParam.CrossCorner, iParam.CrossAdjacentPoint);
            int            tX = iNode.x;
            int            tY = iNode.y;
            int            tPx, tPy, tDx, tDy;
            List <GridPos> tNeighbors = new List <GridPos>();
            List <Node>    tNeighborNodes;
            Node           tNeighborNode;

            // directed pruning: can ignore most neighbors, unless forced.
            if (tParent != null)
            {
                tPx = tParent.x;
                tPy = tParent.y;
                // get the normalized direction of travel
                tDx = (tX - tPx) / Math.Max(Math.Abs(tX - tPx), 1);
                tDy = (tY - tPy) / Math.Max(Math.Abs(tY - tPy), 1);


                // search diagonally
                if (tDx != 0 && tDy != 0)
                {
                    if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                    {
                        tNeighbors.Add(new GridPos(tX, tY + tDy));
                    }
                    if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                    {
                        tNeighbors.Add(new GridPos(tX + tDx, tY));
                    }

                    if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + tDy))
                    {
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + tDx, tY + tDy));
                        }
                    }

                    if (iParam.SearchGrid.IsWalkableAt(tX - tDx, tY + tDy))
                    {
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX - tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX - tDx, tY + tDy));
                        }
                    }

                    if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - tDy))
                    {
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY - tDy) && iParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + tDx, tY - tDy));
                        }
                    }
                }
                // search horizontally/vertically
                else
                {
                    if (tDx != 0)
                    {
                        if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + tDx, tY));

                            if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && iParam.SearchGrid.IsWalkableAt(tX, tY + 1))
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY + 1));
                            }
                            if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && iParam.SearchGrid.IsWalkableAt(tX, tY - 1))
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY - 1));
                            }
                        }
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY + 1))
                        {
                            tNeighbors.Add(new GridPos(tX, tY + 1));
                        }
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY - 1))
                        {
                            tNeighbors.Add(new GridPos(tX, tY - 1));
                        }
                    }
                    else
                    {
                        if (iParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                        {
                            tNeighbors.Add(new GridPos(tX, tY + tDy));

                            if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX + 1, tY))
                            {
                                tNeighbors.Add(new GridPos(tX + 1, tY + tDy));
                            }
                            if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && iParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                            {
                                tNeighbors.Add(new GridPos(tX - 1, tY + tDy));
                            }
                        }
                        if (iParam.SearchGrid.IsWalkableAt(tX + 1, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + 1, tY));
                        }
                        if (iParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                        {
                            tNeighbors.Add(new GridPos(tX - 1, tY));
                        }
                    }
                }
            }
            // return all neighbors
            else
            {
                tNeighborNodes = iParam.SearchGrid.GetNeighbors(iNode);
                for (int i = 0; i < tNeighborNodes.Count; i++)
                {
                    tNeighborNode = tNeighborNodes[i];
                    tNeighbors.Add(new GridPos(tNeighborNode.x, tNeighborNode.y));
                }
            }

            return(tNeighbors);
        }
示例#5
0
        private static GridPos jump(JumpPointParam iParam, int iX, int iY, int iPx, int iPy)
        {
            if (!iParam.SearchGrid.IsWalkableAt(iX, iY))
            {
                return(null);
            }
            else if (iParam.SearchGrid.GetNodeAt(iX, iY).Equals(iParam.EndNode))
            {
                return(new GridPos(iX, iY));
            }

            int tDx = iX - iPx;
            int tDy = iY - iPy;

            // check for forced neighbors
            // along the diagonal
            if (tDx != 0 && tDy != 0)
            {
                if (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + tDy) && (!iParam.SearchGrid.IsWalkableAt(iX, iY + tDy) || !iParam.SearchGrid.IsWalkableAt(iX + tDx, iY)))
                {
                    return(new GridPos(iX, iY));
                }
            }
            // horizontally/vertically
            else
            {
                if (tDx != 0)
                {
                    // moving along x
                    if ((iParam.SearchGrid.IsWalkableAt(iX, iY + 1) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY + 1)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX, iY - 1) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY - 1)))
                    {
                        return(new GridPos(iX, iY));
                    }
                }
                else
                {
                    if ((iParam.SearchGrid.IsWalkableAt(iX + 1, iY) && !iParam.SearchGrid.IsWalkableAt(iX + 1, iY - tDy)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX - 1, iY) && !iParam.SearchGrid.IsWalkableAt(iX - 1, iY - tDy)))
                    {
                        return(new GridPos(iX, iY));
                    }
                }
            }


            // when moving diagonally, must check for vertical/horizontal jump points
            if (tDx != 0 && tDy != 0)
            {
                if (jump(iParam, iX + tDx, iY, iX, iY) != null)
                {
                    return(new GridPos(iX, iY));
                }
                if (jump(iParam, iX, iY + tDy, iX, iY) != null)
                {
                    return(new GridPos(iX, iY));
                }
            }

            // moving diagonally, must make sure both of the vertical/horizontal
            // neighbors is open to allow the path
            if (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) && iParam.SearchGrid.IsWalkableAt(iX, iY + tDy))
            {
                return(jump(iParam, iX + tDx, iY + tDy, iX, iY));
            }
            else
            {
                return(null);
            }
        }
示例#6
0
        private static GridPos jumpLoop(JumpPointParam iParam, int iX, int iY, int iPx, int iPy)
        {
            GridPos retVal             = null;
            Stack <JumpSnapshot> stack = new Stack <JumpSnapshot>();

            JumpSnapshot currentSnapshot = new JumpSnapshot();
            JumpSnapshot newSnapshot     = null;

            currentSnapshot.iX    = iX;
            currentSnapshot.iY    = iY;
            currentSnapshot.iPx   = iPx;
            currentSnapshot.iPy   = iPy;
            currentSnapshot.stage = 0;

            stack.Push(currentSnapshot);
            while (stack.Count != 0)
            {
                currentSnapshot = stack.Pop();
                switch (currentSnapshot.stage)
                {
                case 0:
                    if (!iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY))
                    {
                        retVal = null;
                        continue;
                    }
                    else if (iParam.SearchGrid.GetNodeAt(currentSnapshot.iX, currentSnapshot.iY).Equals(iParam.EndNode))
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    currentSnapshot.tDx = currentSnapshot.iX - currentSnapshot.iPx;
                    currentSnapshot.tDy = currentSnapshot.iY - currentSnapshot.iPy;

                    // check for forced neighbors
                    // along the diagonal
                    if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                    {
                        if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY)) ||
                            (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)))
                        {
                            retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                            continue;
                        }
                    }
                    // horizontally/vertically
                    else
                    {
                        if (currentSnapshot.tDx != 0)
                        {
                            // moving along x
                            if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY + 1)) ||
                                (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY - 1)))
                            {
                                retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                continue;
                            }
                        }
                        else
                        {
                            if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY - currentSnapshot.tDy)) ||
                                (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY - currentSnapshot.tDy)))
                            {
                                retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                continue;
                            }
                        }
                    }


                    // when moving diagonally, must check for vertical/horizontal jump points
                    if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                    {
                        currentSnapshot.stage = 3;
                        stack.Push(currentSnapshot);

                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }

                    // moving diagonally, must make sure both of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }

                    retVal = null;
                    break;

                case 1:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    currentSnapshot.stage = 2;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX;
                    newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 2:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    // moving diagonally, must make sure one of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) || iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }

                    retVal = null;
                    break;

                case 3:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    currentSnapshot.stage = 4;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX;
                    newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 4:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    // moving diagonally, must make sure both of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

                case 5:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }
                    currentSnapshot.stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX;
                    newSnapshot.iY    = currentSnapshot.iY - 1;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 6:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }
                    currentSnapshot.stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX - 1;
                    newSnapshot.iY    = currentSnapshot.iY;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 7:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }
                    // keep going
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;
                }
            }

            return(retVal);
        }