예제 #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.UseRecursive)
                {
                    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)
        {
            heuristic = b.heuristic;
            CurEndNodeUnWalkableTreatment = b.CurEndNodeUnWalkableTreatment;

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

            CurIterationType = b.CurIterationType;
        }
예제 #3
0
        public JumpPointParam(JumpPointParam b) : base(b)
        {
            m_heuristic = b.m_heuristic;
            m_allowEndNodeUnWalkable = b.m_allowEndNodeUnWalkable;
            m_crossAdjacentPoint     = b.m_crossAdjacentPoint;
            m_crossCorner            = b.m_crossCorner;

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

            m_useRecursive = b.m_useRecursive;
        }
예제 #4
0
        private static void IdentifySuccessors(JumpPointParam jpParam, Node node)
        {
            var     tHeuristic = jpParam.HeuristicFunc;
            var     tOpenList  = jpParam.OpenList;
            var     tEndX      = jpParam.EndNode.X;
            var     tEndY      = jpParam.EndNode.Y;
            GridPos tNeighbor;
            GridPos tJumpPoint;
            Node    tJumpNode;

            var tNeighbors = FindNeighbors(jpParam, node);

            for (var i = 0; i < tNeighbors.Count; i++)
            {
                tNeighbor  = tNeighbors[i];
                tJumpPoint = jpParam.CurIterationType == IterationType.Recursive
                                        ? Jump(jpParam, tNeighbor.X, tNeighbor.Y, node.X, node.Y)
                                        : JumpLoop(jpParam, tNeighbor.X, tNeighbor.Y, node.X, node.Y);

                if (tJumpPoint != null)
                {
                    tJumpNode = jpParam.SearchGrid.GetNodeAt(tJumpPoint.X, tJumpPoint.Y);
                    if (tJumpNode == null && jpParam.EndNode.X == tJumpPoint.X && jpParam.EndNode.Y == tJumpPoint.Y)
                    {
                        tJumpNode = jpParam.SearchGrid.GetNodeAt(tJumpPoint);
                    }

                    if (tJumpNode.IsClosed)
                    {
                        continue;
                    }

                    // include distance, as parent may not be immediately adjacent:
                    var tCurNodeToJumpNodeLen = tHeuristic(Math.Abs(tJumpPoint.X - node.X), Math.Abs(tJumpPoint.Y - node.Y));
                    var tStartToJumpNodeLen   = node.StartToCurNodeLen + tCurNodeToJumpNodeLen;                   // next `startToCurNodeLen` value

                    if (!tJumpNode.IsOpened || tStartToJumpNodeLen < tJumpNode.StartToCurNodeLen)
                    {
                        tJumpNode.StartToCurNodeLen = tStartToJumpNodeLen;
                        tJumpNode.HeuristicCurNodeToEndLen ??= tHeuristic(Math.Abs(tJumpPoint.X - tEndX), Math.Abs(tJumpPoint.Y - tEndY));
                        tJumpNode.HeuristicStartToEndLen = tJumpNode.StartToCurNodeLen + tJumpNode.HeuristicCurNodeToEndLen.Value;
                        tJumpNode.Parent = node;

                        if (!tJumpNode.IsOpened)
                        {
                            _ = tOpenList.Add(tJumpNode);
                            tJumpNode.IsOpened = true;
                        }
                    }
                }
            }
        }
예제 #5
0
        public static List <GridPos> FindPath(JumpPointParam iParam)
        {
            List <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.AllowEndNodeUnWalkable && !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.
                tOpenList.Sort();
                tNode = (Node)tOpenList[tOpenList.Count - 1];
                tOpenList.RemoveAt(tOpenList.Count - 1);
                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>());
        }
예제 #6
0
        public JumpPointParam(JumpPointParam b)
        {
            m_heuristic = b.m_heuristic;
            m_allowEndNodeUnWalkable = b.m_allowEndNodeUnWalkable;
            m_crossAdjacentPoint     = b.m_crossAdjacentPoint;
            m_crossCorner            = b.m_crossCorner;

            openList = new List <Node>(b.openList);

            m_searchGrid   = b.m_searchGrid;
            m_startNode    = b.m_startNode;
            m_endNode      = b.m_endNode;
            m_useRecursive = b.m_useRecursive;
        }
예제 #7
0
        public static List <GridPos> FindPath(JumpPointParam jpParam)
        {
            var  tOpenList  = jpParam.OpenList;
            var  tStartNode = jpParam.StartNode;
            var  tEndNode   = jpParam.EndNode;
            Node tNode;
            var  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 (jpParam.CurEndNodeUnWalkableTreatment == EndNodeUnWalkableTreatment.Allow && !jpParam.SearchGrid.IsWalkableAt(tEndNode.X, tEndNode.Y))
            {
                _ = jpParam.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)
                    {
                        _ = jpParam.SearchGrid.SetWalkableAt(tEndNode.X, tEndNode.Y, false);
                    }
                    return(Node.Backtrace(tNode));                    // rebuilding path
                }

                IdentifySuccessors(jpParam, tNode);
            }

            if (revertEndNodeWalkable)
            {
                _ = jpParam.SearchGrid.SetWalkableAt(tEndNode.X, tEndNode.Y, false);
            }

            // fail to find the path
            return(new List <GridPos>());
        }
예제 #8
0
 public List<Vector2> Ruta_a(Punt2d origen, Punt2d final)
 {
     var jpParam = new JumpPointParam(mapa_pa_sala, false, false, false, HeuristicMode.MANHATTAN);
     //jpParam.Reset(new GridPos(0,14), new GridPos(0,12));
     jpParam.Reset(new GridPos(origen.X, origen.Y), new GridPos(final.X, final.Y));
     //Debug.Log(Vector_Grid(origen).x+" "+Vector_Grid(origen).y+"origen");
     var ruta_a = JumpPointFinder.FindPath(jpParam);
     var ruta_a_tra = new List<Vector2>();
     foreach (var cosa in ruta_a)
     {
         //Debug.Log(cosa.x+" "+cosa.y);
         ruta_a_tra.Add(Grid_Vector(cosa));
     }
     //Debug.Log(ruta_a_tra.Count + " Hola");
     return ruta_a_tra;
 }  
예제 #9
0
        public SearchGridForm()
        {
            InitializeComponent();
            this.DoubleBuffered = true;

            m_resultBox      = new List <ResultBox>();
            this.Width       = (width + 1) * 20;
            this.Height      = (height + 1) * 20 + 100;
            this.MaximumSize = new Size(this.Width, this.Height);
            this.MaximizeBox = false;


            m_rectangles = new GridBox[width][];
            for (int widthTrav = 0; widthTrav < width; widthTrav++)
            {
                m_rectangles[widthTrav] = new GridBox[height];
                for (int heightTrav = 0; heightTrav < height; heightTrav++)
                {
                    if (widthTrav == (width / 3) && heightTrav == (height / 2))
                    {
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20, heightTrav * 20 + 50, BoxType.Start);
                    }
                    else if (widthTrav == 41 && heightTrav == (height / 2))
                    {
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20, heightTrav * 20 + 50, BoxType.End);
                    }
                    else
                    {
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20, heightTrav * 20 + 50, BoxType.Normal);
                    }
                }
            }

            m_resultLine = new List <GridLine>();

            searchGrid = new StaticGrid(width, height);
            // searchGrid = new DynamicGrid();
            //searchGrid = new DynamicGridWPool(SingletonHolder<NodePool>.Instance);
            jumpParam = new JumpPointParam(searchGrid, true, cbCrossCorners.Checked, cbCrossAdjacentPoint.Checked, HeuristicMode.EUCLIDEAN);//new JumpPointParam(searchGrid, startPos, endPos, cbCrossCorners.Checked, HeuristicMode.EUCLIDEANSQR);
            jumpParam.UseRecursive = cbUseRecursive.Checked;
        }
예제 #10
0
        public static List<GridPos> FindPath(JumpPointParam iParam)
        {

            List<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.AllowEndNodeUnWalkable && !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.
                tOpenList.Sort();
                tNode = (Node)tOpenList[tOpenList.Count-1];
                tOpenList.RemoveAt(tOpenList.Count - 1);
                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>();
        }
예제 #11
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;
                    currentSnapshot.jx  = null;
                    currentSnapshot.jy  = null;
                    if (iParam.CrossCorner)
                    {
                        // 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.tDx, currentSnapshot.iY)) ||
                                (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - currentSnapshot.tDy) && !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.tDx, currentSnapshot.iY + 1) && !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)))
                                {
                                    retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((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) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY)))
                                {
                                    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 = 1;
                            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 one of the vertical/horizontal
                        // neighbors is open to allow the path

                        // 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;
                        }
                        else if (iParam.CrossAdjacentPoint)
                        {
                            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;
                        }
                    }
                    else     //if (!iParam.CrossCorner)
                    {
                        // 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:
                    currentSnapshot.jx = retVal;

                    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:
                    currentSnapshot.jy = retVal;
                    if (currentSnapshot.jx != null || currentSnapshot.jy != 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;
                    }
                    else if (iParam.CrossAdjacentPoint)
                    {
                        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:
                    currentSnapshot.jx = retVal;

                    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:
                    currentSnapshot.jy = retVal;
                    if (currentSnapshot.jx != null || currentSnapshot.jy != 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;
                }
            }

            return(retVal);
        }
예제 #12
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;
            GridPos jx  = null;
            GridPos jy  = null;

            if (iParam.CrossCorner)
            {
                // check for forced neighbors
                // along the diagonal
                if (tDx != 0 && tDy != 0)
                {
                    if ((iParam.SearchGrid.IsWalkableAt(iX - tDx, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - tDy) && !iParam.SearchGrid.IsWalkableAt(iX, iY - tDy)))
                    {
                        return(new GridPos(iX, iY));
                    }
                }
                // horizontally/vertically
                else
                {
                    if (tDx != 0)
                    {
                        // moving along x
                        if ((iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY + 1)) ||
                            (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY - 1)))
                        {
                            return(new GridPos(iX, iY));
                        }
                    }
                    else
                    {
                        if ((iParam.SearchGrid.IsWalkableAt(iX + 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX + 1, iY)) ||
                            (iParam.SearchGrid.IsWalkableAt(iX - 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - 1, iY)))
                        {
                            return(new GridPos(iX, iY));
                        }
                    }
                }
                // when moving diagonally, must check for vertical/horizontal jump points
                if (tDx != 0 && tDy != 0)
                {
                    jx = jump(iParam, iX + tDx, iY, iX, iY);
                    jy = jump(iParam, iX, iY + tDy, iX, iY);
                    if (jx != null || jy != null)
                    {
                        return(new GridPos(iX, iY));
                    }
                }

                // moving diagonally, must make sure one 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 if (iParam.CrossAdjacentPoint)
                {
                    return(jump(iParam, iX + tDx, iY + tDy, iX, iY));
                }
                else
                {
                    return(null);
                }
            }
            else //if (!iParam.CrossCorner)
            {
                // 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)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + tDy) && iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) && !iParam.SearchGrid.IsWalkableAt(iX, iY + tDy)))
                    {
                        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)
                {
                    jx = jump(iParam, iX + tDx, iY, iX, iY);
                    jy = jump(iParam, iX, iY + tDy, iX, iY);
                    if (jx != null || jy != 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);
                }
            }
        }
예제 #13
0
        private static List<GridPos> findNeighbors(JumpPointParam iParam, Node iNode)
        {
            Node tParent = (Node)iNode.parent;
            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);

                if (iParam.CrossCorner)
                {
                    // 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));
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                tNeighbors.Add(new GridPos(tX - tDx, tY + tDy));
                            }
                        }

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


                    }
                    // search horizontally/vertically
                    else
                    {
                        if (tDx == 0)
                        {
                            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));
                                }
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                                }
                            }
                        }
                        else
                        {
                            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));
                                }
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                                }
                            }
                        }
                    }
                }
                else // if(!iParam.CrossCorner)
                {
                    // 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, 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));
                        }
                        else
                        {
                            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));
                        }
                    }
                }
             
            }
            // return all neighbors
            else
            {
                tNeighborNodes = iParam.SearchGrid.GetNeighbors(iNode, iParam.CrossCorner, iParam.CrossAdjacentPoint);
                for (int i = 0; i < tNeighborNodes.Count; i++)
                {
                    tNeighborNode = tNeighborNodes[i];
                    tNeighbors.Add(new GridPos(tNeighborNode.x, tNeighborNode.y));
                }
            }

            return tNeighbors;
        }
예제 #14
0
    private void CacheJumpPointParam()
    {
        if (staticlyCachedJpParam == null)
        {
            BaseGrid searchGrid = new StaticGrid(world.Width, world.Height);

            foreach (Tile roadTile in world.RoadTiles)
                searchGrid.SetWalkableAt(roadTile.x, roadTile.z, true);

            staticlyCachedJpParam = new JumpPointParam(searchGrid);
        }
    }
예제 #15
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;
                        currentSnapshot.jx = null;
                        currentSnapshot.jy = null;
                        if (iParam.CrossCorner)
                        {
                            // 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.tDx, currentSnapshot.iY)) ||
                                    (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - currentSnapshot.tDy) && !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.tDx, currentSnapshot.iY + 1) && !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)))
                                    {
                                        retVal= new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                        continue;
                                    }
                                }
                                else
                                {
                                    if ((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) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY)))
                                    {
                                        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 = 1;
                                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 one of the vertical/horizontal
                            // neighbors is open to allow the path

                            // 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;
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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;
                            }
                        }
                        else //if (!iParam.CrossCorner)
                        {
                            // 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:
                        currentSnapshot.jx = retVal;

                        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:
                        currentSnapshot.jy = retVal;
                        if (currentSnapshot.jx != null || currentSnapshot.jy != 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;
                        }
                        else if (iParam.CrossAdjacentPoint)
                        {
                            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:
                        currentSnapshot.jx = retVal;

                        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:
                        currentSnapshot.jy = retVal;
                        if (currentSnapshot.jx != null || currentSnapshot.jy != 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;
                }
            }

            return retVal;

        }
예제 #16
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;
            GridPos jx=null;
            GridPos jy=null;
            if (iParam.CrossCorner)
            {
                // check for forced neighbors
                // along the diagonal
                if (tDx != 0 && tDy != 0)
                {
                    if ((iParam.SearchGrid.IsWalkableAt(iX - tDx, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - tDx, iY)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - tDy) && !iParam.SearchGrid.IsWalkableAt(iX, iY - tDy)))
                    {
                        return new GridPos(iX, iY);
                    }
                }
                // horizontally/vertically
                else
                {
                    if (tDx != 0)
                    { 
                        // moving along x
                        if ((iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY + 1)) ||
                            (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY - 1) && !iParam.SearchGrid.IsWalkableAt(iX, iY - 1)))
                        {
                            return new GridPos(iX, iY);
                        }
                    }
                    else
                    {
                        if ((iParam.SearchGrid.IsWalkableAt(iX + 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX + 1, iY)) ||
                            (iParam.SearchGrid.IsWalkableAt(iX - 1, iY + tDy) && !iParam.SearchGrid.IsWalkableAt(iX - 1, iY)))
                        {
                            return new GridPos(iX, iY);
                        }
                    }
                }
                // when moving diagonally, must check for vertical/horizontal jump points
                if (tDx != 0 && tDy != 0)
                {
                    jx = jump(iParam, iX + tDx, iY, iX, iY);
                    jy = jump(iParam, iX, iY + tDy, iX, iY);
                    if (jx != null || jy != null)
                    {
                        return new GridPos(iX, iY);
                    }
                }

                // moving diagonally, must make sure one 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 if (iParam.CrossAdjacentPoint)
                {
                    return jump(iParam, iX + tDx, iY + tDy, iX, iY);
                }
                else
                {
                    return null;
                }
            }
            else //if (!iParam.CrossCorner)
            {
                // 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)) ||
                        (iParam.SearchGrid.IsWalkableAt(iX + tDx, iY + tDy) && iParam.SearchGrid.IsWalkableAt(iX + tDx, iY) && !iParam.SearchGrid.IsWalkableAt(iX, iY + tDy)))
                    {
                        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)
                {
                    jx = jump(iParam, iX + tDx, iY, iX, iY);
                    jy = jump(iParam, iX, iY + tDy, iX, iY);
                    if (jx != null || jy != 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;
                }
            }
           
        }
예제 #17
0
        private static void identifySuccessors(JumpPointParam iParam, Node iNode)
        {
            HeuristicDelegate tHeuristic = iParam.HeuristicFunc;
            List<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.UseRecursive)
                    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;
                        }
                    }
                }
            }
        }
예제 #18
0
        private static GridPos JumpLoop(JumpPointParam jpParam, int x, int y, int px, int py)
        {
            var stack = new Stack <JumpSnapshot>();

            var currentSnapshot = new JumpSnapshot
            {
                X     = x,
                Y     = y,
                Px    = px,
                Py    = py,
                Stage = 0
            };

            stack.Push(currentSnapshot);
            GridPos retVal = null;

            while (stack.Count != 0)
            {
                currentSnapshot = stack.Pop();
                JumpSnapshot newSnapshot;
                switch (currentSnapshot.Stage)
                {
                case 0:
                    if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y))
                    {
                        retVal = null;
                        continue;
                    }
                    else if (jpParam.SearchGrid.GetNodeAt(currentSnapshot.X, currentSnapshot.Y).Equals(jpParam.EndNode))
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    currentSnapshot.Dx = currentSnapshot.X - currentSnapshot.Px;
                    currentSnapshot.Dy = currentSnapshot.Y - currentSnapshot.Py;
                    if (jpParam.DiagonalMovement == DiagonalMovement.Always || jpParam.DiagonalMovement == DiagonalMovement.IfAtLeastOneWalkable)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y)) ||
                                (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y - currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - currentSnapshot.Dy)))
                            {
                                retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.Dx != 0)
                            {
                                // moving along x
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + 1)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y - 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                        }
                        // when moving diagonally, must check for vertical/horizontal jump points
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            currentSnapshot.Stage = 1;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) || jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                        else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    else if (jpParam.DiagonalMovement == DiagonalMovement.OnlyWhenNoObstacles)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y)) ||
                                (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy)))
                            {
                                retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.Dx != 0)
                            {
                                // moving along x
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y + 1)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y - currentSnapshot.Dy)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y - currentSnapshot.Dy)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                        }

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

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure both of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    else                             // if(jpParam.DiagonalMovement == DiagonalMovement.Never)
                    {
                        if (currentSnapshot.Dx != 0)
                        {
                            // moving along x
                            if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y))
                            {
                                retVal = new GridPos(x, y);
                                continue;
                            }
                        }
                        else
                        {
                            if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                            {
                                retVal = new GridPos(x, y);
                                continue;
                            }
                        }

                        //  must check for perpendicular jump points
                        if (currentSnapshot.Dx != 0)
                        {
                            currentSnapshot.Stage = 5;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X,
                                Y     = currentSnapshot.Y + 1,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                        else                                 // tDy != 0
                        {
                            currentSnapshot.Stage = 6;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + 1,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    retVal = null;
                    break;

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

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

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y + currentSnapshot.Dy,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

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

                    // moving diagonally, must make sure one of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) || jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

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

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

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y + currentSnapshot.Dy,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

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

                    // moving diagonally, must make sure both of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

                case 5:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    currentSnapshot.Stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y - 1,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 6:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    currentSnapshot.Stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X - 1,
                        Y     = currentSnapshot.Y,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 7:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    // keep going
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;
                }
            }

            return(retVal);
        }
예제 #19
0
        private static GridPos Jump(JumpPointParam jpParam, int x, int y, int px, int py)
        {
            if (!jpParam.SearchGrid.IsWalkableAt(x, y))
            {
                return(null);
            }
            else if (jpParam.SearchGrid.GetNodeAt(x, y).Equals(jpParam.EndNode))
            {
                return(new GridPos(x, y));
            }

            var tDx = x - px;
            var tDy = y - py;

            if (jpParam.DiagonalMovement == DiagonalMovement.Always || jpParam.DiagonalMovement == DiagonalMovement.IfAtLeastOneWalkable)
            {
                // check for forced neighbors
                // along the diagonal
                if (tDx != 0 && tDy != 0)
                {
                    if ((jpParam.SearchGrid.IsWalkableAt(x - tDx, y + tDy) && !jpParam.SearchGrid.IsWalkableAt(x - tDx, y)) ||
                        (jpParam.SearchGrid.IsWalkableAt(x + tDx, y - tDy) && !jpParam.SearchGrid.IsWalkableAt(x, y - tDy)))
                    {
                        return(new GridPos(x, y));
                    }
                }
                // horizontally/vertically
                else
                {
                    if (tDx != 0)
                    {
                        // moving along x
                        if ((jpParam.SearchGrid.IsWalkableAt(x + tDx, y + 1) && !jpParam.SearchGrid.IsWalkableAt(x, y + 1)) ||
                            (jpParam.SearchGrid.IsWalkableAt(x + tDx, y - 1) && !jpParam.SearchGrid.IsWalkableAt(x, y - 1)))
                        {
                            return(new GridPos(x, y));
                        }
                    }
                    else
                    {
                        if ((jpParam.SearchGrid.IsWalkableAt(x + 1, y + tDy) && !jpParam.SearchGrid.IsWalkableAt(x + 1, y)) ||
                            (jpParam.SearchGrid.IsWalkableAt(x - 1, y + tDy) && !jpParam.SearchGrid.IsWalkableAt(x - 1, y)))
                        {
                            return(new GridPos(x, y));
                        }
                    }
                }
                // when moving diagonally, must check for vertical/horizontal jump points
                if (tDx != 0 && tDy != 0)
                {
                    if (Jump(jpParam, x + tDx, y, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }
                    if (Jump(jpParam, x, y + tDy, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }
                }

                // moving diagonally, must make sure one of the vertical/horizontal
                // neighbors is open to allow the path
                return(jpParam.SearchGrid.IsWalkableAt(x + tDx, y) || jpParam.SearchGrid.IsWalkableAt(x, y + tDy)
                                        ? Jump(jpParam, x + tDx, y + tDy, x, y)
                                        : jpParam.DiagonalMovement == DiagonalMovement.Always ? Jump(jpParam, x + tDx, y + tDy, x, y) : null);
            }
            else if (jpParam.DiagonalMovement == DiagonalMovement.OnlyWhenNoObstacles)
            {
                // check for forced neighbors
                // along the diagonal
                if (tDx != 0 && tDy != 0)
                {
                    if (jpParam.SearchGrid.IsWalkableAt(x + tDx, y + tDy) && (!jpParam.SearchGrid.IsWalkableAt(x, y + tDy) || !jpParam.SearchGrid.IsWalkableAt(x + tDx, y)))
                    {
                        return(new GridPos(x, y));
                    }
                }
                // horizontally/vertically
                else
                {
                    if (tDx != 0)
                    {
                        // moving along x
                        if ((jpParam.SearchGrid.IsWalkableAt(x, y + 1) && !jpParam.SearchGrid.IsWalkableAt(x - tDx, y + 1)) ||
                            (jpParam.SearchGrid.IsWalkableAt(x, y - 1) && !jpParam.SearchGrid.IsWalkableAt(x - tDx, y - 1)))
                        {
                            return(new GridPos(x, y));
                        }
                    }
                    else
                    {
                        if ((jpParam.SearchGrid.IsWalkableAt(x + 1, y) && !jpParam.SearchGrid.IsWalkableAt(x + 1, y - tDy)) ||
                            (jpParam.SearchGrid.IsWalkableAt(x - 1, y) && !jpParam.SearchGrid.IsWalkableAt(x - 1, y - tDy)))
                        {
                            return(new GridPos(x, y));
                        }
                    }
                }

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

                    if (Jump(jpParam, x, y + tDy, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }
                }

                // moving diagonally, must make sure both of the vertical/horizontal
                // neighbors is open to allow the path
                return(jpParam.SearchGrid.IsWalkableAt(x + tDx, y) && jpParam.SearchGrid.IsWalkableAt(x, y + tDy)
                                        ? Jump(jpParam, x + tDx, y + tDy, x, y)
                                        : null);
            }
            else             // if(jpParam.DiagonalMovement == DiagonalMovement.Never)
            {
                if (tDx != 0)
                {
                    // moving along x
                    if (!jpParam.SearchGrid.IsWalkableAt(x + tDx, y))
                    {
                        return(new GridPos(x, y));
                    }
                }
                else
                {
                    if (!jpParam.SearchGrid.IsWalkableAt(x, y + tDy))
                    {
                        return(new GridPos(x, y));
                    }
                }

                //  must check for perpendicular jump points
                if (tDx != 0)
                {
                    if (Jump(jpParam, x, y + 1, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }

                    if (Jump(jpParam, x, y - 1, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }
                }
                else                 // tDy != 0
                {
                    if (Jump(jpParam, x + 1, y, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }

                    if (Jump(jpParam, x - 1, y, x, y) != null)
                    {
                        return(new GridPos(x, y));
                    }
                }

                // keep going
                return(jpParam.SearchGrid.IsWalkableAt(x + tDx, y) && jpParam.SearchGrid.IsWalkableAt(x, y + tDy)
                                        ? Jump(jpParam, x + tDx, y + tDy, x, y)
                                        : null);
            }
        }
예제 #20
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);

                if (iParam.CrossCorner)
                {
                    // 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));
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                tNeighbors.Add(new GridPos(tX - tDx, tY + tDy));
                            }
                        }

                        if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY - tDy))
                        {
                            if (iParam.SearchGrid.IsWalkableAt(tX + tDx, tY) && !iParam.SearchGrid.IsWalkableAt(tX, tY - tDy))
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY - tDy));
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY - tDy));
                            }
                        }
                    }
                    // search horizontally/vertically
                    else
                    {
                        if (tDx == 0)
                        {
                            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));
                                }
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                                }
                            }
                        }
                        else
                        {
                            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));
                                }
                            }
                            else if (iParam.CrossAdjacentPoint)
                            {
                                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));
                                }
                            }
                        }
                    }
                }
                else // if(!iParam.CrossCorner)
                {
                    // 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, 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));
                            }
                        }
                        else
                        {
                            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));
                            }
                        }
                    }
                }
            }
            // return all neighbors
            else
            {
                tNeighborNodes = iParam.SearchGrid.GetNeighbors(iNode, diagonalMovement);
                for (int i = 0; i < tNeighborNodes.Count; i++)
                {
                    tNeighborNode = tNeighborNodes[i];
                    tNeighbors.Add(new GridPos(tNeighborNode.x, tNeighborNode.y));
                }
            }

            return(tNeighbors);
        }
예제 #21
0
        private static List <GridPos> FindNeighbors(JumpPointParam jpParam, Node node)
        {
            var tParent = (Node)node.Parent;
            //var diagonalMovement = Util.GetDiagonalMovement(jpParam.CrossCorner, jpParam.CrossAdjacentPoint);
            var         tX = node.X;
            var         tY = node.Y;
            int         tPx, tPy, tDx, tDy;
            var         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);

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

                        if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY + tDy))
                        {
                            if (jpParam.SearchGrid.IsWalkableAt(tX, tY + tDy) || jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY + tDy));
                            }
                            else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                            {
                                tNeighbors.Add(new GridPos(tX + tDx, tY + tDy));
                            }
                        }

                        if (jpParam.SearchGrid.IsWalkableAt(tX - tDx, tY + tDy) && !jpParam.SearchGrid.IsWalkableAt(tX - tDx, tY))
                        {
                            if (jpParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                            {
                                tNeighbors.Add(new GridPos(tX - tDx, tY + tDy));
                            }
                            else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                            {
                                tNeighbors.Add(new GridPos(tX - tDx, tY + tDy));
                            }
                        }

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

                                if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && !jpParam.SearchGrid.IsWalkableAt(tX, tY + 1))
                                {
                                    tNeighbors.Add(new GridPos(tX + tDx, tY + 1));
                                }
                                if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && !jpParam.SearchGrid.IsWalkableAt(tX, tY - 1))
                                {
                                    tNeighbors.Add(new GridPos(tX + tDx, tY - 1));
                                }
                            }
                            else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                            {
                                if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY + 1) && !jpParam.SearchGrid.IsWalkableAt(tX, tY + 1))
                                {
                                    tNeighbors.Add(new GridPos(tX + tDx, tY + 1));
                                }
                                if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY - 1) && !jpParam.SearchGrid.IsWalkableAt(tX, tY - 1))
                                {
                                    tNeighbors.Add(new GridPos(tX + tDx, tY - 1));
                                }
                            }
                        }
                        else
                        {
                            if (jpParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                            {
                                tNeighbors.Add(new GridPos(tX, tY + tDy));

                                if (jpParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && !jpParam.SearchGrid.IsWalkableAt(tX + 1, tY))
                                {
                                    tNeighbors.Add(new GridPos(tX + 1, tY + tDy));
                                }
                                if (jpParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && !jpParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                                {
                                    tNeighbors.Add(new GridPos(tX - 1, tY + tDy));
                                }
                            }
                            else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                            {
                                if (jpParam.SearchGrid.IsWalkableAt(tX + 1, tY + tDy) && !jpParam.SearchGrid.IsWalkableAt(tX + 1, tY))
                                {
                                    tNeighbors.Add(new GridPos(tX + 1, tY + tDy));
                                }
                                if (jpParam.SearchGrid.IsWalkableAt(tX - 1, tY + tDy) && !jpParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                                {
                                    tNeighbors.Add(new GridPos(tX - 1, tY + tDy));
                                }
                            }
                        }
                    }
                }
                else if (jpParam.DiagonalMovement == DiagonalMovement.OnlyWhenNoObstacles)
                {
                    // search diagonally
                    if (tDx != 0 && tDy != 0)
                    {
                        if (jpParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                        {
                            tNeighbors.Add(new GridPos(tX, tY + tDy));
                        }
                        if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + tDx, tY));
                        }

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

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

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

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

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

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

                            if (jpParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                            {
                                tNeighbors.Add(new GridPos(tX - 1, tY));
                            }
                        }
                    }
                }
                else                 // if(jpParam.DiagonalMovement == DiagonalMovement.Never)
                {
                    if (tDx != 0)
                    {
                        if (jpParam.SearchGrid.IsWalkableAt(tX + tDx, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + tDx, tY));
                        }
                        if (jpParam.SearchGrid.IsWalkableAt(tX, tY + 1))
                        {
                            tNeighbors.Add(new GridPos(tX, tY + 1));
                        }
                        if (jpParam.SearchGrid.IsWalkableAt(tX, tY - 1))
                        {
                            tNeighbors.Add(new GridPos(tX, tY - 1));
                        }
                    }
                    else                     // if (tDy != 0)
                    {
                        if (jpParam.SearchGrid.IsWalkableAt(tX, tY + tDy))
                        {
                            tNeighbors.Add(new GridPos(tX, tY + tDy));
                        }
                        if (jpParam.SearchGrid.IsWalkableAt(tX + 1, tY))
                        {
                            tNeighbors.Add(new GridPos(tX + 1, tY));
                        }
                        if (jpParam.SearchGrid.IsWalkableAt(tX - 1, tY))
                        {
                            tNeighbors.Add(new GridPos(tX - 1, tY));
                        }
                    }
                }
            }
            // return all neighbors
            else
            {
                tNeighborNodes = jpParam.SearchGrid.GetNeighbors(node, jpParam.DiagonalMovement);
                for (var i = 0; i < tNeighborNodes.Count; i++)
                {
                    tNeighborNode = tNeighborNodes[i];
                    tNeighbors.Add(new GridPos(tNeighborNode.X, tNeighborNode.Y));
                }
            }

            return(tNeighbors);
        }
예제 #22
0
        public SearchGridForm()
        {



            InitializeComponent();
            this.DoubleBuffered = true;

            m_resultBox = new List<ResultBox>();
            this.Width = (width+1) * 20;
            this.Height = (height+1) * 20 +100;
            this.MaximumSize = new Size(this.Width, this.Height);
            this.MaximizeBox = false;


            m_rectangles = new GridBox[width][];
            for (int widthTrav = 0; widthTrav < width; widthTrav++)
            {
                m_rectangles[widthTrav] = new GridBox[height];
                for (int heightTrav = 0; heightTrav < height; heightTrav++)
                {
                    if(widthTrav==(width/3) && heightTrav==(height/2))
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20, heightTrav * 20 + 50, BoxType.Start);
                    else if (widthTrav == 41 && heightTrav == (height / 2))
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20 , heightTrav * 20 + 50, BoxType.End);
                    else
                        m_rectangles[widthTrav][heightTrav] = new GridBox(widthTrav * 20, heightTrav * 20 + 50, BoxType.Normal);


                }
            }

            m_resultLine = new List<GridLine>();

             searchGrid = new StaticGrid(width, height);
            // searchGrid = new DynamicGrid();
            //searchGrid = new DynamicGridWPool(SingletonHolder<NodePool>.Instance);
            jumpParam = new JumpPointParam(searchGrid, true, cbCrossCorners.Checked, cbCrossAdjacentPoint.Checked, HeuristicMode.EUCLIDEAN);//new JumpPointParam(searchGrid, startPos, endPos, cbCrossCorners.Checked, HeuristicMode.EUCLIDEANSQR);
            jumpParam.UseRecursive = cbUseRecursive.Checked;
            
        }
예제 #23
0
        public JumpPointParam(JumpPointParam b)
        {
            m_heuristic = b.m_heuristic;
            m_allowEndNodeUnWalkable = b.m_allowEndNodeUnWalkable;
            m_crossAdjacentPoint = b.m_crossAdjacentPoint;
            m_crossCorner = b.m_crossCorner;

            openList = new List<Node>(b.openList);

            m_searchGrid = b.m_searchGrid;
            m_startNode = b.m_startNode;
            m_endNode = b.m_endNode;
            m_useRecursive = b.m_useRecursive;
        }