Exemple #1
0
        public bool LineTest2(CMap map, CCreature cc, int x1, int y1, int x2, int y2, ref Vector2 lastPos)
        {
            //Profiler.BeginSample("LineTest2");

            int dx = x2 - x1;
            int dy = y2 - y1;
            int ux = (dx > 0) ? 1 : -1; //x的增量方向,取或-1
            int uy = (dy > 0) ? 1 : -1; //y的增量方向,取或-1
            int x = x1, y = y1, eps;    //eps为累加误差

            //算法问题需要向增量方向在+1
            x2 += ux; y2 += uy;
            eps = 0; dx = Mathf.Abs(dx); dy = Mathf.Abs(dy);
            if (dx > dy)
            {
                for (x = x1; x != x2; x += ux)
                {
                    if (!map.CanArrive(cc, x, y))
                    {
                        //Profiler.EndSample();
                        return(false);
                    }
                    lastPos.x = x;
                    lastPos.y = y;
                    //mpaths.Add(new Vector2(x, y));
                    eps += dy;
                    if ((eps << 1) >= dx)
                    {
                        y += uy; eps -= dx;
                    }
                }
            }
            else
            {
                for (y = y1; y != y2; y += uy)
                {
                    if (!map.CanArrive(cc, x, y))
                    {
                        //Profiler.EndSample();
                        return(false);
                    }
                    lastPos.x = x;
                    lastPos.y = y;
                    eps      += dx;
                    if ((eps << 1) >= dy)
                    {
                        x += ux; eps -= dy;
                    }
                }
            }

            //Profiler.EndSample();

            return(true);
        }
Exemple #2
0
        // 开始寻路 开始点、结束点、结果路径列表、最大搜索节点数
        public bool FindPath(CMap map, CCreature cc, Vector2 startPt, Vector2 endPos, ref List <Vector2> paths, int maxRoute)
        {
            // 如果检测到是能走的直线,就取最后一个点为目的地
            // 如果检测到不是能走的直线,取靠近目标点最近的并且能走的点,作为寻路的目标点
            Vector2 vLastPos = Vector2.zero;

            if (LineTest2(map, cc, (int)startPt.x, (int)startPt.y, (int)endPos.x, (int)endPos.y, ref vLastPos))
            {
                paths.Add(vLastPos);
                return(true);
            }

            // 如果目标点不能走,取检测直线时得出的,靠近目标点最近的并且能走的点
            //if (null == map || !map.CanArriveDoubleInt(ref startPt) || !map.CanArriveDoubleInt(ref endPos))
            if (null == map || !map.CanArrive(cc, (int)endPos.x, (int)endPos.y))
            {
                m_nErrorType = ErrorCode.eErrParam;
                if (vLastPos != Vector2.zero)
                {
                    paths.Add(vLastPos);
                    //直线走到最近能走到的那个点需要缩放回去
                    //Profiler.EndSample();
                    return(true);
                }
                //Profiler.EndSample();
                return(false);
            }
            // sPaths.Clear();

            InitLists(0, 0);
            openNote((int)startPt.x, (int)startPt.y, 0, 0, 0);

            int currTry    = 0;
            int currId     = 0;
            int currNoteX  = 0;
            int currNoteY  = 0;
            int checkingId = 0;
            int cost       = 0;
            int score      = 0;

            Vector2[] aroundNodes = new Vector2[8];
            int       aroundCount = 0;

            while (m_nOpenCount > 0)
            {
                // 超时返回
                if (++currTry > maxRoute)
                {
                    m_nErrorType = ErrorCode.eErrMaxTry;

                    //Profiler.EndSample();
                    //Debug.Log("超过最大遍历次数");
                    return(false);
                }

                // 每次取出开放列表最前面的ID
                currId = m_vOpenList[0];
                //将编码为此ID的元素列入关闭列表
                closeNote(currId);
                currNoteX = m_vXList[currId];
                currNoteY = m_vYList[currId];

                //如果终点被放入关闭列表寻路结束,返回路径
                if (currNoteX == (int)endPos.x && currNoteY == (int)endPos.y)
                {
                    bool bRef = getPath(ref startPt, ref endPos, currId, paths);

                    //Profiler.EndSample();

                    return(bRef);
                }

                //获取周围节点,排除不可通过和已在关闭列表中的
                getArounds(map, cc, currNoteX, currNoteY, ref aroundNodes, ref aroundCount);
                for (int index = 0; index < aroundCount; index++)
                {
                    // 计算F和G值
                    cost = m_vMovementCostList[currId] +
                           ((aroundNodes[index].x == currNoteX || aroundNodes[index].y == currNoteY) ? (int)CostSave.CostStraight : (int)CostSave.CostDiagonal);

                    score = cost + (int)((Mathf.Abs(endPos.x - aroundNodes[index].x) + Mathf.Abs(endPos.y - aroundNodes[index].y)) * (float)CostSave.CostStraight);
                    if (isOpen(map, (int)aroundNodes[index].x, (int)aroundNodes[index].y))//如果节点已在播放列表中
                    {
                        checkingId = m_GlobleintAStar[(int)aroundNodes[index].y, (int)aroundNodes[index].x];
                        if (checkingId >= m_vMovementCostList.Count)
                        {
                            //Debug.LogWarning(string.Format("寻路出现问题场景{0}起始坐标[{1},{2}], 目标坐标[{3}, {4}]", map.GetMapID(), startPt.x, startPt.y, endPos.x, endPos.y));
                            return(false);
                        }
                        //如果新的G值比节点原来的G值小,修改F,G值,换父节点
                        if (cost < m_vMovementCostList[checkingId])
                        {
                            m_vMovementCostList[checkingId] = cost;
                            m_vPathScoreList[checkingId]    = score;
                            m_vFatherList[checkingId]       = currId;
                            aheadNote(getIndex(checkingId));
                        }
                    }
                    else//如果节点不在开放列表中
                    {
                        //将节点放入开放列表
                        openNote((int)aroundNodes[index].x, (int)aroundNodes[index].y, score, cost, currId);
                    }
                }
            }

            //如果找不到。那么走到可以走到的那个点上
            if (vLastPos.x > 0 && paths.Count == 0)
            {
                //直线走到最近能走到的那个点需要缩放回去

                //Profiler.EndSample();

                return(true);
            }

            // 开放列表已空,找不到路径
            m_nErrorType = ErrorCode.eErrCannotFind;

            //Profiler.EndSample();

            return(false);
        }
Exemple #3
0
        // 获取某节点的周围节点,排除不能通过和已在关闭列表中的
        bool getArounds(CMap map, CCreature cc, int p_x, int p_y, ref Vector2[] aroundNodes, ref int aroundCount)
        {
            //Vector2 pt = Vector2.zero;
            int  checkX      = 0;
            int  checkY      = 0;
            bool canDiagonal = false;
            bool canRight    = false;
            bool canDown     = false;
            bool canLeft     = false;
            bool canUp       = false;

            aroundCount = 0;

            // 右
            checkX   = p_x + 1;
            checkY   = p_y;
            canRight = map.CanArrive(cc, checkX, checkY);
            if (canRight && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 下
            checkX  = p_x;
            checkY  = p_y + 1;
            canDown = map.CanArrive(cc, checkX, checkY);
            if (canDown && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 左
            checkX  = p_x - 1;
            checkY  = p_y;
            canLeft = map.CanArrive(cc, checkX, checkY);
            if (canLeft && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 上
            checkX = p_x;
            checkY = p_y - 1;
            canUp  = map.CanArrive(cc, checkX, checkY);
            if (canUp && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 右下
            checkX      = p_x + 1;
            checkY      = p_y + 1;
            canDiagonal = map.CanArrive(cc, checkX, checkY);
            if (canDiagonal && canRight && canDown && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 左下
            checkX      = p_x - 1;
            checkY      = p_y + 1;
            canDiagonal = map.CanArrive(cc, checkX, checkY);
            if (canDiagonal && canLeft && canDown && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 左上
            checkX      = p_x - 1;
            checkY      = p_y - 1;
            canDiagonal = map.CanArrive(cc, checkX, checkY);
            if (canDiagonal && canLeft && canUp && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }

            // 右上
            checkX      = p_x + 1;
            checkY      = p_y - 1;
            canDiagonal = map.CanArrive(cc, checkX, checkY);
            if (canDiagonal && canRight && canUp && !isClosed(checkX, checkY))
            {
                aroundNodes[aroundCount++] = new Vector2(checkX, checkY);
            }
            return(true);
        }