SRPG游戏开发(二十七)第七章 寻路与地图对象 - 五 搜索移动范围与路径(Search Move Range and Path)

该章节详细介绍了SRPG游戏中寻路与地图对象的相关工作,包括搜索移动范围与路径的实现。通过修改寻路算法,添加判断格子是否可移动的条件,以及对外部调用的函数进行相应调整。同时,创建了搜索移动范围的类,实现了选择节点、判断格子可移动性以及填充计算G的函数。在搜索路径部分,更新了结束搜索的判断、计算H值和加入开放集的条件。最后,提供了测试寻路与移动的步骤。
摘要由CSDN通过智能技术生成

返回总目录

第七章 寻路与地图对象(Pathfinding and Map Object)

这一章主要进行寻路与地图对象的部分工作。



五 搜索移动范围与路径(Search Move Range and Path)

就像我们之前说的,移动范围与攻击范围的搜索算法十分的类似,只需要修改少部分内容:

  • 计算消耗G;

  • 在判断是否能加入开放集时,需要判断格子是否有效(是否可移动);

  • 对外调用的函数,加入移动消耗。


1 修改寻路(Extend Pathfinding)

这个方法,我们在PathFinding类中添加。

  • 首先,修改对外调用函数:

            // 修改后寻找移动范围
            public bool SearchMoveRange(IHowToFind howToFind, CellData start, float movePoint, MoveConsumption consumption)
            {
          
                if (howToFind == null || start == null || movePoint < 0)
                {
          
                    return false;
                }
    
                Reset();
    
                m_HowToFind = howToFind;
                m_MoveConsumption = consumption;
    
                m_StartCell = start;
                m_StartCell.ResetAStar();
                m_Range.y = movePoint;
    
                m_Reachable.Add(m_StartCell);
    
                return SearchRangeInternal();
            }
    
            // 修改后搜寻路径
            public bool SearchPath(IHowToFind howToFind, CellData start, CellData end, MoveConsumption consumption)
            {
          
                if (howToFind == null || start == null || end == null)
                {
          
                    return false;
                }
    
                Reset();
    
                m_HowToFind = howToFind;
                m_MoveConsumption = consumption;
                m_StartCell = start;
                m_StartCell.ResetAStar();
                m_EndCell = end;
                m_EndCell.ResetAStar();
    
                m_Reachable.Add(m_StartCell);
    
                m_StartCell.h = m_HowToFind.CalcH(this, m_StartCell);
    
                return SearchRangeInternal();
            }
    
            /// 修改后寻找攻击范围
            /// 这里添加的参数 `useEndCell` ,
            /// 是在 `移动范围` 与 `攻击范围` 一起显示时,
            /// 不破坏 `起始节点`。
            public bool SearchAttackRange(IHowToFind howToFind, CellData start, int minRange, int maxRange, bool useEndCell = false)
            {
          
                if (howToFind == null || start == null || minRange < 1 || maxRange < minRange)
                {
          
                    return false;
                }
    
                Reset();
    
                m_HowToFind = howToFind;
                m_Range = new Vector2(minRange, maxRange);
    
                // 在重置时,不重置 `父亲节点` ,
                // 其一:没有用到
                // 其二:二次查找时不破坏路径,否则路径将被破坏
                if (useEndCell)
                {
          
                    m_EndCell = start;
                    m_EndCell.g = 0f;
                    m_Reachable.Add(m_EndCell);
                }
                else
                {
          
                    m_StartCell = start;
                    m_StartCell.g = 0f;
                    m_Reachable.Add(m_StartCell);
                }
    
                return SearchRangeInternal();
            }
    
    

    当然,你还要记得修改MapGraph里的对应函数。

  • 其次,修改Reset函数:

    在寻路过程中,我们会不断的重新计算A星的G和H,还有父亲节点。

    Reset时,我们不必每个都重置,只需要之前做的修改那样,将关键点重置(例如起始结束节点,而攻击范围没有用到父亲节点,所以只重置G)。

            /// <summary>
            /// 重置
            /// </summary>
            public void Reset()
            {
          
                m_Reachable.Clear();
                m_Explored.Clear();
                m_Result.Clear();
    
                m_Range = Vector2.zero;
                m_StartCell = null;
                m_EndCell = null;
                m_CurrentCell = null;
                m_Finished = false;
                m_HowToFind = null;
                m_MoveConsumption = null;
    
                m_SearchCount = 0;
            }
    
    
  • 再次,添加获取消耗方法:

            /// <summary>
            /// 获取移动消耗
            /// </summary>
            /// <param name="terrainType"></param>
            /// <returns></returns>
            public float GetMoveConsumption(TerrainType terrainType)
            {
          
                if (m_MoveConsumption == null)
                {
          
                    return 1f;
                }
                return m_MoveConsumption[terrainType];
            }
    
    
  • 最后,添加建立路径方法:

            /// <summary>
            /// 建立路径List
            /// </summary>
            /// <param name="endCell"></param>
            /// <param name="useResult"></param>
            /// <returns></returns>
            public List<CellData> BuildPath(CellData endCell, bool useResult)
            {
          
                if (endCell == null)
                {
          
                    Debug.LogError("PathFinding -> Argument named `endCell` is null.");
                    return null;
                }
    
                List<CellData> path = useResult ? m_Result : new List<CellData>();
    
                CellData current = endCell;
                path.Add(current);
                while (current.previous != null)
                {
          
                    current = current.previous;
                    path.Insert(0, current);
                }
                return path;
            }
    
            /// <summary>
            /// 建立路径Stack
            /// </summary>
            /// <param name="endCell"></param>
            /// <returns></returns>
            public Stack<CellData> BuildPath(CellData endCell)
            {
          
                if (endCell == null)
                {
          
                    Debug.LogError("PathFinding -> Argument named `endCell` is null.");
                    return null;
                }
    
                Stack<CellData> path = new Stack<CellData>();
    
                CellData current = endCell;
                path.Push(current);
                while (current.previous != null)
                {
          
                    current = current.previous;
                    path.Push(c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值