#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*寻路算法源码可以帮助开发者理解和应用这一算法,解决游戏中的角色移动、导航系统中的路径规划等问题。C#语言的实现使其具有广泛的适用性,尤其是在游戏开发领域。通过深入学习和理解源码,我们可以掌握算法...
Erlang B星寻路算法源代码 B*寻路算法源代码, 由C++改写而来。效率是A星算法的几十倍到上百倍。做为服务端怪物寻路的最佳选择。
在游戏服务端开发中,尤其是在MMORPG(大型多人在线角色扮演游戏)如墨香这样的项目中,A*算法用于智能NPC的导航或者玩家角色的移动规划,确保角色能够快速、准确地在游戏世界中移动。A*算法通过评估节点的f(n)值...
在网络游戏的开发中,服务器端寻路算法是一个至关重要的组成部分,它确保了游戏中的角色能够智能、高效地在虚拟世界中移动。金山软件作为国内知名的软件开发商,在这方面有着丰富的经验和独到的技术。本文将深入探讨...
5. **游戏算法**:如战斗计算、寻路算法等,这些都是游戏逻辑的核心部分,通过源码可以学习到实际的实现方法。 6. **安全性**:防止作弊、保护玩家数据安全是服务端必须考虑的问题。源码中可能会涉及到加密、验证等...
1. **路径规划算法**:最常用的可能是A*(A-Star)算法,它结合了Dijkstra算法和启发式搜索,能够在复杂的游戏环境中找到最短路径。A*算法需要定义合适的代价函数(如欧几里得距离或曼哈顿距离)和启发式函数(如...
7. **AI设计**:游戏中的NPC(非玩家角色)行为可能涉及到简单的AI算法,如状态机、寻路算法(A*寻路)等,这些对于游戏世界的动态性至关重要。 8. **脚本语言与接口**:游戏可能会使用脚本语言来编写部分逻辑,...
机器坦克有巡逻范围的概念,当玩家坦克进入其巡逻范围,机器坦克才会使用A*寻路前往玩家坦克的位置 限制了子弹的飞行距离,当子弹到达飞行距离上限、击中障碍物、碰到边界时,子弹会爆炸。子弹爆炸是范围性伤害,在...
这涉及到复杂的算法设计,如路径规划(A*寻路算法)、单位碰撞检测、战斗模拟等。 6. **图形渲染**:游戏的画面展示可能借助HTML5的Canvas或者Three.js等图形库,用于在浏览器中绘制游戏场景、单位动画和特效。同时...
寻路算法,如A*算法,帮助角色找到最优路径;以及游戏状态机的设计,用于管理游戏的不同阶段(如等待、游戏进行、游戏结束等)。 资源管理也是游戏开发中的重要部分。Java可能使用了内存管理机制,如垃圾回收,来...
书中会涵盖基本的路径寻路算法如A*寻路,以及如何设计敌方坦克的决策逻辑,使其能够根据环境和玩家行为做出反应。这可能涉及到Unity的NavMesh系统和自定义行为树(Behavior Tree)。 界面系统是玩家与游戏交互的...
例如,AI可能运用搜索算法(如A*寻路算法)、行为树等;任务系统可能涉及状态机设计;战斗系统则可能涉及复杂的计算,如伤害计算、技能效果等。 资源管理也是大型游戏的重要部分,如内存管理、纹理和声音的加载与...
2. 数据结构与算法:源码中可能会使用到各种数据结构(如链表、树、图等)和算法(如寻路算法、AI决策算法)来优化游戏性能和玩家体验。 3. 网络通信:服务器与客户端之间的通信协议和数据传输,通常是通过TCP/IP...
这个系统专门用于在3D游戏或应用中实现智能实体的自动寻路功能。 描述中的信息虽简略,但我们可以推断,这个系统可能包含以下关键知识点: 1. **C#编程**:C#是一种面向对象的编程语言,广泛用于开发Windows桌面...
Recast Navigation提供了从原始几何数据构建导航网格,并进行查询和寻路的功能,适用于多种类型的游戏和服务端应用。 1. **导航网格(Navigation Mesh)**:NavMesh是游戏AI中用于路径规划的一种数据结构,它将3D...
此外,源码中可能涉及到的游戏算法,如碰撞检测、寻路算法(如A*算法)、AI行为逻辑等,都是游戏开发中的核心部分。这些算法的实现方式,展示了DELPHI在处理复杂计算任务时的能力。 对于想要深入了解游戏开发或者...
开发者可以通过研究这些源代码学习到如何在Unity中实现一个完整的导航系统,包括理解如何编写寻路算法、如何与游戏逻辑交互以及如何优化性能。 总的来说,UnityGameNav统一游戏导航系统是一个强大的工具,它简化了...
Java做手游服务端会用到... Jump Point Search跳点寻路算法A *算法的变种 A *算法 广度优先搜索 ps:先按各种算法单独实现,加深理解后,再撤换通用类和方法进行整合 实时排行榜Java实现方式 简单的暴力排行 未完待续!