Ejemplo n.º 1
0
        public List <Vector2Int> FindPath(Vector2Int start, Vector2Int end)
        {
            if (!_grid.CanMove(start) || !_grid.CanMove(end))
            {
                return(null);
            }
            _grid.Clear();
            _start = start;
            _end   = end;
            _openSet.Clear();

            // 后面大括号内为  初始化列表
            var startNode = new Jps_Node(_start)
            {
                Cost = 0, IsOpen = false, IsClose = false, IsForce = false
            };

            _openSet.Enqueue(startNode, startNode.Cost);
            // 每次取 估值函数最小的节点 检测
            while (_openSet.Count > 0)
            {
                Jps_Node cur = _openSet.Dequeue();
                cur.IsClose = true;
                if (cur.Pos == _end)
                {
                    return(Trace(cur));
                }
                IdentitySuccessors(cur);
            }

            return(null);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///  回溯路径
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        private List <Vector2Int> Trace(Jps_Node node)
        {
            var path = new List <Vector2Int>();

            path.Add(node.Pos);
            while (node.Parent != null)
            {
                node = node.Parent;
                path.Add(node.Pos);
            }
            path.Reverse();
            return(path);
        }
Ejemplo n.º 3
0
        public Jps_Grid(bool[, ] flags)
        {
            _boundMinX = 0;
            _boundMaxX = flags.GetUpperBound(0);        // 数组长度 表示边界
            _boundMinY = 0;
            _boundMaxY = flags.GetUpperBound(1);
            _gridFlags = flags;

            _grid = new Jps_Node[_boundMaxX + 1, _boundMaxY + 1];
            for (int x = _boundMinX; x <= _boundMaxX; x++)
            {
                for (int y = _boundMinY; y <= _boundMaxY; y++)
                {
                    _grid[x, y] = new Jps_Node(x, y);
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        ///  搜索 后续跳点
        /// </summary>
        /// <param name="node"></param>
        private void IdentitySuccessors(Jps_Node node)
        {
            // 剪枝 获取所有需要检测的邻居点
            var neighbours = _grid.Neighbours(node);

            foreach (var n in neighbours)
            {
                Vector2Int jumpPos = Jump(node.Pos, n.Pos - node.Pos, 1);
                if (jumpPos == NullVec)
                {
                    continue;
                }

                Jps_Node jumpNode = _grid[jumpPos.x, jumpPos.y];
                if (jumpNode.IsClose)       // 跳点已检测过, 过滤
                {
                    continue;
                }

                float moveCost = (jumpPos - node.Pos).magnitude;
                float newCost  = node.Cost + moveCost;
                if (!jumpNode.IsOpen)       // 判断加入 OpenSet中
                {
                    jumpNode.IsOpen = true;
                    jumpNode.Parent = node;
                    jumpNode.Cost   = newCost;
                    _openSet.Enqueue(jumpNode, jumpNode.Cost);
                }
                // 更新代价
                else if (newCost < jumpNode.Cost)
                {
                    jumpNode.Cost   = newCost;
                    jumpNode.Parent = node;
                    _openSet.UpdatePriority(jumpNode, newCost);
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        ///  获取 需要检测的所有邻居点
        ///     使用  轴向移动剪枝 和 对角线移动剪枝 优化查找的邻居点数量
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        internal List <Jps_Node> Neighbours(Jps_Node node)
        {
            List <Jps_Node> list = new List <Jps_Node>(8);

            if (node.Parent != null)
            {
                // 当前移动方向
                Vector2Int curDir = node.Pos - node.Parent.Pos;
                curDir.x /= curDir.x == 0 ? 1 : Mathf.Abs(curDir.x);
                curDir.y /= curDir.y == 0 ? 1 : Mathf.Abs(curDir.y);

                // 对角线移动
                //      检测  水平轴向 和 垂直轴向 及 当前对角方向 点
                if (curDir.x != 0 && curDir.y != 0)
                {
                    if (CanMove(node.Pos.x + curDir.x, node.Pos.y))
                    {
                        list.Add(this[node.Pos.x + curDir.x, node.Pos.y]);
                    }

                    if (CanMove(node.Pos.x, node.Pos.y + curDir.y))
                    {
                        list.Add(this[node.Pos.x, node.Pos.y + curDir.y]);
                    }

                    // 对角移动时 如果要确保不能经过 障碍格子顶点,  在此处添加限制
                    //  011
                    //  111
                    //  111
                    //      一般不能从[0,1] 走到 [1,0], 因为会经过障碍格子顶点
                    //if (CanMove(node.Pos.x, node.Pos.y + curDir.y) && CanMove(node.Pos.x + curDir.x, node.Pos.y) && CanMove(node.Pos.x + curDir.x, node.Pos.y + curDir.y))
                    if (CanMove(node.Pos.x + curDir.x, node.Pos.y + curDir.y))
                    {
                        list.Add(this[node.Pos.x + curDir.x, node.Pos.y + curDir.y]);
                    }
                }
                else if (curDir.x != 0)
                {
                    // 水平轴向移动  检测
                    //      1. 当前方向
                    //      2. 当前朝向左后方为障碍,左方可走,返回 左前方(普通邻居点) 和 左方点(强迫邻居点)
                    //      3. 当前朝向右后方为障碍,右方可走,返回 右前方(普通邻居点) 和 右方点(强迫邻居点)
                    if (CanMove(node.Pos.x + curDir.x, node.Pos.y))
                    {
                        list.Add(this[node.Pos.x + curDir.x, node.Pos.y]);
                    }

                    if (CanMove(node.Pos.x, node.Pos.y + 1) && !CanMove(node.Pos.x - curDir.x, node.Pos.y + 1))
                    {
                        list.Add(this[node.Pos.x, node.Pos.y + 1]);
                        this[node.Pos.x, node.Pos.y + 1].IsForce = true;        // 左方点为 强迫邻居点
                        if (CanMove(node.Pos.x + curDir.x, node.Pos.y + 1))
                        {
                            list.Add(this[node.Pos.x + curDir.x, node.Pos.y + 1]);
                        }
                    }

                    if (CanMove(node.Pos.x, node.Pos.y - 1) && !CanMove(node.Pos.x - curDir.x, node.Pos.y - 1))
                    {
                        list.Add(this[node.Pos.x, node.Pos.y - 1]);
                        this[node.Pos.x, node.Pos.y - 1].IsForce = true;        // 右方点为 强迫邻居点
                        if (CanMove(node.Pos.x + curDir.x, node.Pos.y - 1))
                        {
                            list.Add(this[node.Pos.x + curDir.x, node.Pos.y - 1]);
                        }
                    }
                }
                else
                {
                    // 垂直轴向移动
                    //      1. 当前方向
                    //      2. 当前朝向左后方为障碍,左方可走,返回 左前方(普通邻居点) 和 左方点(强迫邻居点)
                    //      3. 当前朝向右后方为障碍,右方可走,返回 右前方(普通邻居点) 和 右方点(强迫邻居点)
                    if (CanMove(node.Pos.x, node.Pos.y + curDir.y))
                    {
                        list.Add(this[node.Pos.x, node.Pos.y + curDir.y]);
                    }

                    if (CanMove(node.Pos.x - 1, node.Pos.y) && !CanMove(node.Pos.x - 1, node.Pos.y - curDir.y))
                    {
                        list.Add(this[node.Pos.x - 1, node.Pos.y]);
                        this[node.Pos.x - 1, node.Pos.y].IsForce = true;        // 左方点为 强迫邻居点
                        if (CanMove(node.Pos.x - 1, node.Pos.y + curDir.y))
                        {
                            list.Add(this[node.Pos.x - 1, node.Pos.y + curDir.y]);
                        }
                    }

                    if (CanMove(node.Pos.x + 1, node.Pos.y) && !CanMove(node.Pos.x + 1, node.Pos.y - curDir.y))
                    {
                        list.Add(this[node.Pos.x + 1, node.Pos.y]);
                        this[node.Pos.x + 1, node.Pos.y].IsForce = true;        // 右方点为 强迫邻居点
                        if (CanMove(node.Pos.x + 1, node.Pos.y + curDir.y))
                        {
                            list.Add(this[node.Pos.x + 1, node.Pos.y + curDir.y]);
                        }
                    }
                }
            }
            else
            {
                // 起点,  直接返回所有可移动点
                for (int i = 0; i < 8; i++)
                {
                    int x = node.Pos.x + _dirs[i].x;
                    int y = node.Pos.y + _dirs[i].y;
                    if (CanMove(x, y))
                    {
                        list.Add(this[x, y]);
                    }
                }
            }
            return(list);
        }