`
suiyuan0808
  • 浏览: 155273 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

游戏服务端中的A*寻路算法

    博客分类:
  • c++
阅读更多

#ifndef __ASTAR_SERACH_ALGO_H__
 #define __ASTAR_SERACH_ALGO_H__
 #include <Algorithm>
   
  namespace fredazsq
  {   
  namespace linghuye
  {   
    
 /**//*************************************************
 ** 寻路节点
 *************************************************/
 template<typename TNodeLocation>
 struct TAXNode
 {   
     float       G, F;
     TNodeLocation  pos;
     TAXNode*   pParentNode;
     bool       bClosed;        // 使用状态表明节点处于开放或关闭列表.
   
     bool operator<(const TAXNode& node) const
     {   
         return pos < node.pos;
     }   
 };   
  
 /**//******************************************************************************
 **  封装A*寻路算法
 *******************************************************************************
 **  作为棋盘信息提供类TField必须实现下列函数:
 **  1. bool IsFieldThrough(TNodeLocation pos) const;                                    在 pos 位置是否为空,可通行.
 **  2. float EvaluateStepCost(TNodeLocation posFrom, TNodeLocation posTo, TNodeLocation posLastStep) const;        计算pos1,pos2到单步代价.
 **  3. float EvaluateProbableCost(TNodeLocation posFrom, TNodeLocation posTo) const;    计算pos1,pos2到估算代价.
 **  4. TNodeLocation* QueryNeiborLocations(TNodeLocation pos, int& nNodeCount); const    询问pos的相邻可通节点集
 *******************************************************************************
 **  TNodeLocation,节点位置
 **  1.支持<,==,=操作符,如int.
 *******************************************************************************
 **  0. 初始化时传入棋盘信息提供类的实例引用.
 **  1. 使用主函数SearchPath进行搜索,使用QueryResultPath取得结果.
 ******************************************************************************/
 template<class TField, class TNodeLocation>
 struct CAStar2DAlgo
 {   
 public:
     typedef std::vector<TNodeLocation>    CResultPath;
     typedef TAXNode<TNodeLocation>        CAXNode;
     typedef std::set<CAXNode>            CAXNodeSet;
    
     struct CAXNodePriorityQueue            // 优先队列
     {   
         std::vector<CAXNode*> m_heap;
        
         static bool AXNodeCostSortPred(CAXNode* n1, CAXNode* n2)
         {   
             return (n1->G + n1->F) > (n2->G + n2->F);
         }
        
         void push(CAXNode* pNode)
         {
             m_heap.push_back(pNode);
            std::push_heap(m_heap.begin(), m_heap.end(), &CAXNodePriorityQueue::AXNodeCostSortPred);
         }
        
        CAXNode* pop()
        {   
             CAXNode* pNode = m_heap.front();
            std::pop_heap(m_heap.begin(), m_heap.end(), &CAXNodePriorityQueue::AXNodeCostSortPred);
             m_heap.pop_back();
             return pNode;
         }
       
        bool empty()
        {
            return m_heap.empty();
         }
        
        void resort(CAXNode* pNode)
        {   
             std::vector<CAXNode*>::iterator it = std::find(m_heap.begin(), m_heap.end(), pNode);
           std::push_heap(m_heap.begin(), it, &CAXNodePriorityQueue::AXNodeCostSortPred);
         }
        
        void clear()
       {
             m_heap.clear();
         }
     };   
      
 public:   
   const TField& m_field;
     TNodeLocation  m_posTarget;
     CAXNode* m_ptrTargetNode;                    // Result Node
       
    CAXNodeSet m_setNodes;                        // All nodes in use
    CAXNodePriorityQueue m_queOpenNodes;        // Cost sorted open list
       
public:   
    CAStar2DAlgo(const TField& field) : m_field(field), m_ptrTargetNode(NULL)
    {       
    }   
       
    ~CAStar2DAlgo()
   {   
    }   
       
    void Reset()
    {   
       m_setNodes.clear();
        m_queOpenNodes.clear();
        m_ptrTargetNode = NULL;
    }   
       
public:   
   inline CAXNode* ClaimNode(TNodeLocation pos, CAXNode* pParentNode = NULL)
    {   
        CAXNode node;
        node.pos = pos;
       node.F = node.G = 0;
        node.bClosed = false;    // Default is open
        node.pParentNode = pParentNode;
        return &(*m_setNodes.insert(node).first);
    }   
       
    bool SearchPath(TNodeLocation posStart, TNodeLocation posTarget)
    {   
       CAXNode* pCurNode;
        m_posTarget = posTarget;
       
        // Add start node into open list
        CAXNode* pStartNode = ClaimNode(posStart);
        m_queOpenNodes.push(pStartNode);
       
       while(!m_queOpenNodes.empty())
        {   
           // Pick lowest cost node
           pCurNode = m_queOpenNodes.pop();
           
            // Check search target
            if(pCurNode->pos == m_posTarget)
            {
                m_ptrTargetNode = pCurNode;
                return true;
            }
           
            // Switch node from OpenList to CloseList
           pCurNode->bClosed = true;
           ProcessNeighborNodes(pCurNode);
        }
      
        return false;
    }
       
   void ProcessNeighborNodes(CAXNode* pCurNode)
    {   
        CAXNode tempNode;
        int nNodeCount = 0;
       TNodeLocation* pLocs = m_field.QueryNeiborLocations(pCurNode->pos, nNodeCount);
       TNodeLocation posLastStep = pCurNode->pParentNode? pCurNode->pParentNode->pos : pCurNode->pos;
      
        // For each neibors
        for(int i = 0; i < nNodeCount; ++i)
        {   
            tempNode.pos = pLocs[i];
            if(m_field.IsFieldThrough(tempNode.pos))
            {   
                CAXNodeSet::iterator it = m_setNodes.find(tempNode);
               if(it == m_setNodes.end())
                {   
                    CAXNode* pNewNode = ClaimNode(tempNode.pos, pCurNode);
                   pNewNode->G = pCurNode->G + m_field.EvaluateStepCost(pCurNode->pos, pNewNode->pos, posLastStep);
                    pNewNode->F = m_field.EvaluateProbableCost(pNewNode->pos, m_posTarget);
                   m_queOpenNodes.push(pNewNode);
               }   
                else if(!it->bClosed)
                {   
                    CAXNode& node = *it;
                    float G = pCurNode->G + m_field.EvaluateStepCost(pCurNode->pos, node.pos, posLastStep);
                    if(G < node.G)
                    {   
                       node.G = G;
                        node.pParentNode = pCurNode;
                        m_queOpenNodes.resort(&node);
                    }
                }
            }
        }
    }
   
   /**//******************************************************************
    **  取回最终结果
    ******************************************************************/
    bool QueryResultPath(CResultPath& path)
    {   
       if(!m_ptrTargetNode) return false;
       
        CAXNode* pNode = m_ptrTargetNode;
        while(pNode)
        {   
            path.push_back(pNode->pos);
            pNode = pNode->pParentNode;
       }
        return true;
   }
};

/**//*******************************************************************************
**  TNodeLocation,节点位置
**  1.支持<,== 操作符号.
********************************************************************************/
template<typename TNodeLocation>
struct CShisenFieldImpl
{   
    TNodeLocation* QueryNeiborLocations(TNodeLocation pos, int& nRetCount) const
   {   
      static const int dy[4] = { 1, 0, 0, -1 };
        static TNodeLocation posNeibors[4];    // Single thread
               
        nRetCount = 4;
       for(int i = 0; i < 4; i++)
       {
            posNeibors[i].x = pos.x + dx[i];
            posNeibors[i].y = pos.y + dy[i];
        }
       return posNeibors;
    }
   
    float EvaluateStepCost(TNodeLocation posFrom, TNodeLocation posTo, TNodeLocation posLast) const
   {   
        if(((posFrom.x-posTo.x)  &&  (posLast.y-posFrom.y))  || 
           ((posFrom.y-posTo.y)  &&  (posLast.x-posFrom.x)))
        {   
            return 100;
        }
        else return 1;
    }
   
    float EvaluateProbableCost(TNodeLocation pos1, TNodeLocation pos2) const
    {
        return 0;
    }
   
/**//*    平滑优化
    float EvaluateStepCost(MY_POSITION posFrom, MY_POSITION posTo, MY_POSITION posLast) const
    {   
        int cx1 = posTo.x - posFrom.x;
        int cy1 = posTo.y - posFrom.y;
        int cx2 = posFrom.x - posLast.x;
        int cy2 = posFrom.y - posLast.y;
        return ((cx1 == cx2  &&  cy1 == cy2)? 0 : 10) + ((cx1  &&  cy1)? 14 : 10);
    }
*/   
};   
   
/**//*******************************************************************************
**  最小路径
*******************************************************************************/
template<typename TNodeLocation>
struct CShortestPathFieldImpl
{   
    TNodeLocation* QueryNeiborLocations(TNodeLocation pos, int& nRetCount) const
    {   
        static const int dx[4] = { 0, -1, 1,  0 };
        static const int dy[4] = { 1,  0, 0, -1 };
        static TNodeLocation posNeibors[4];    // Single thread
               
        nRetCount = 4;
        for(int i = 0; i < 4; i++)
        {
            posNeibors[i].x = pos.x + dx[i];
            posNeibors[i].y = pos.y + dy[i];
        }
        return posNeibors;
    }
   
    float EvaluateStepCost(TNodeLocation posFrom, TNodeLocation posTo, TNodeLocation posLast) const
    {   
        return 1;
    }
   
    float EvaluateProbableCost(TNodeLocation pos1, TNodeLocation pos2) const
    {
        return 0;
    }
};

/**//*******************************************************************************
**  最小路径
*******************************************************************************/
template<typename TNodeLocation>
struct CGamePathFieldImpl
{   
    TNodeLocation* QueryNeiborLocations(TNodeLocation pos, int& nRetCount) const
    {   
        static const int dx[8] = { -1, 0, 1, -1, 1, -1,  0,  1 };
        static const int dy[8] = {  1, 1, 1,  0, 0, -1, -1, -1 };
        static MY_POSITION posNeibors[8];
       
        nRetCount = 8;
        for(int i = 0; i < 8; i++)
        {
            posNeibors[i].x = pos.x + dx[i];
            posNeibors[i].y = pos.y + dy[i];
        }
        return posNeibors;
    }
   
    float EvaluateStepCost(TNodeLocation posFrom, TNodeLocation posTo, TNodeLocation posLast) const
    {   
        if(posFrom.x-posTo.x  &&  posFrom.y-posTo.y)
        {
            return 14;
        }
        else return 10;
    }
   
    float EvaluateProbableCost(TNodeLocation posFrom, TNodeLocation posTo) const
    {
        return (abs(posFrom.x-posTo.x) + abs(posFrom.y-posTo.y)) * 10;
    }
};

}// namespace linghuye
}// namespace fredazsq

#endif//__FIELD_SERACH_ALGO_H__

分享到:
评论

相关推荐

    A*寻路算法 源码

    总之,A*寻路算法源码可以帮助开发者理解和应用这一算法,解决游戏中的角色移动、导航系统中的路径规划等问题。C#语言的实现使其具有广泛的适用性,尤其是在游戏开发领域。通过深入学习和理解源码,我们可以掌握算法...

    Erlang B星寻路算法源代码 B*寻路算法源代码

    Erlang B星寻路算法源代码 B*寻路算法源代码, 由C++改写而来。效率是A星算法的几十倍到上百倍。做为服务端怪物寻路的最佳选择。

    DarkStory_Svr.rar_A*算法_Server_墨香源_数据库 备份_服务端

    在游戏服务端开发中,尤其是在MMORPG(大型多人在线角色扮演游戏)如墨香这样的项目中,A*算法用于智能NPC的导航或者玩家角色的移动规划,确保角色能够快速、准确地在游戏世界中移动。A*算法通过评估节点的f(n)值...

    金山软件:网游服务器端寻路算法

    在网络游戏的开发中,服务器端寻路算法是一个至关重要的组成部分,它确保了游戏中的角色能够智能、高效地在虚拟世界中移动。金山软件作为国内知名的软件开发商,在这方面有着丰富的经验和独到的技术。本文将深入探讨...

    droiyan源码-决战服务端源码

    5. **游戏算法**:如战斗计算、寻路算法等,这些都是游戏逻辑的核心部分,通过源码可以学习到实际的实现方法。 6. **安全性**:防止作弊、保护玩家数据安全是服务端必须考虑的问题。源码中可能会涉及到加密、验证等...

    网页游戏部分实现

    1. **路径规划算法**:最常用的可能是A*(A-Star)算法,它结合了Dijkstra算法和启发式搜索,能够在复杂的游戏环境中找到最短路径。A*算法需要定义合适的代价函数(如欧几里得距离或曼哈顿距离)和启发式函数(如...

    海之乐章源代码

    7. **AI设计**:游戏中的NPC(非玩家角色)行为可能涉及到简单的AI算法,如状态机、寻路算法(A*寻路)等,这些对于游戏世界的动态性至关重要。 8. **脚本语言与接口**:游戏可能会使用脚本语言来编写部分逻辑,...

    基于Java+Netty+MySQL实现联机版坦克大战【100011266】

    机器坦克有巡逻范围的概念,当玩家坦克进入其巡逻范围,机器坦克才会使用A*寻路前往玩家坦克的位置 限制了子弹的飞行距离,当子弹到达飞行距离上限、击中障碍物、碰到边界时,子弹会爆炸。子弹爆炸是范围性伤害,在...

    Javascript星际争霸

    这涉及到复杂的算法设计,如路径规划(A*寻路算法)、单位碰撞检测、战斗模拟等。 6. **图形渲染**:游戏的画面展示可能借助HTML5的Canvas或者Three.js等图形库,用于在浏览器中绘制游戏场景、单位动画和特效。同时...

    这个是QQ堂游戏,java版。.zip

    寻路算法,如A*算法,帮助角色找到最优路径;以及游戏状态机的设计,用于管理游戏的不同阶段(如等待、游戏进行、游戏结束等)。 资源管理也是游戏开发中的重要部分。Java可能使用了内存管理机制,如垃圾回收,来...

    《Unity3D网络游戏实战》资源说明1

    书中会涵盖基本的路径寻路算法如A*寻路,以及如何设计敌方坦克的决策逻辑,使其能够根据环境和玩家行为做出反应。这可能涉及到Unity的NavMesh系统和自定义行为树(Behavior Tree)。 界面系统是玩家与游戏交互的...

    天龙八部源码 完整版 c++

    例如,AI可能运用搜索算法(如A*寻路算法)、行为树等;任务系统可能涉及状态机设计;战斗系统则可能涉及复杂的计算,如伤害计算、技能效果等。 资源管理也是大型游戏的重要部分,如内存管理、纹理和声音的加载与...

    【大秦online端游】大秦全套游戏源码--战争策略角色扮演游戏

    2. 数据结构与算法:源码中可能会使用到各种数据结构(如链表、树、图等)和算法(如寻路算法、AI决策算法)来优化游戏性能和玩家体验。 3. 网络通信:服务器与客户端之间的通信协议和数据传输,通常是通过TCP/IP...

    c# GridPathFindSystem mogre/Axiom

    这个系统专门用于在3D游戏或应用中实现智能实体的自动寻路功能。 描述中的信息虽简略,但我们可以推断,这个系统可能包含以下关键知识点: 1. **C#编程**:C#是一种面向对象的编程语言,广泛用于开发Windows桌面...

    recastnavigation.zip

    Recast Navigation提供了从原始几何数据构建导航网格,并进行查询和寻路的功能,适用于多种类型的游戏和服务端应用。 1. **导航网格(Navigation Mesh)**:NavMesh是游戏AI中用于路径规划的一种数据结构,它将3D...

    小火炬源码

    此外,源码中可能涉及到的游戏算法,如碰撞检测、寻路算法(如A*算法)、AI行为逻辑等,都是游戏开发中的核心部分。这些算法的实现方式,展示了DELPHI在处理复杂计算任务时的能力。 对于想要深入了解游戏开发或者...

    UnityGameNav统一游戏导航 v1.0

    开发者可以通过研究这些源代码学习到如何在Unity中实现一个完整的导航系统,包括理解如何编写寻路算法、如何与游戏逻辑交互以及如何优化性能。 总的来说,UnityGameNav统一游戏导航系统是一个强大的工具,它简化了...

    gamer:Java做手游服务端的一些实用的源码框架

    Java做手游服务端会用到... Jump Point Search跳点寻路算法A *算法的变种 A *算法 广度优先搜索 ps:先按各种算法单独实现,加深理解后,再撤换通用类和方法进行整合 实时排行榜Java实现方式 简单的暴力排行 未完待续!

Global site tag (gtag.js) - Google Analytics