cocos2dx的大量使用,证明其确实是一款有力的游戏开发工具。但是一个游戏光有引擎也不能完成一切游戏元素。很多事情我们也要自己做。比如A*寻路算法。
其原理不难。各位可参考:
http://blog.csdn.net/taobao755624068/article/details/8275333
http://cn.cocos2d-x.org/tutorial/show?id=1532
具体地图可分地图,大地图甚至超大,各类优化算法也有相应实现。这里仅给出简单原理实现。进一步的优化各位可各展所能。
都可以实现自己的寻路。我这里贴出自己的实现方式。不足之处希望指出。大家一起进步。先上抓图:
游戏采用map地图。二维数据实现地图数据。因此,墙=0, 可走的路=1,
定义open和close表
AStarResult* openList;
AStarResult* closeList;
相关函数:AStarResult* AStarFinder(int * mapdata, DetectPoint start, DetectPoint end);
// A* helper funcs
bool pointEqual2point(DetectPoint p1, DetectPoint p2);
void addSiblings2List(AStarResult* node, AStarResult* endNode);
void removeFromOpenList(AStarResult* node);
AStarResult* getTopNodes(); // return a node list, which includes most smallest F
AStarResult* createSibNode(DetectPoint curPos, int g, AStarResult* endNode);
AStarResult* loop(AStarResult* node, AStarResult* endNode);
bool isInCloseList(DetectPoint pos);
中间某些是辅助函数,比如清空列表,便于重新搜索。判断是否已经在close表中。
如果到达目的地:
bool AnimalSprite::pointEqual2point(DetectPoint p1, DetectPoint p2) {
if (p1.dpx == p2.dpx) {
if (p1.dpy == p2.dpy) {
return true;
}
}
return false;
}
循环判断,递归方式。
AStarResult* AnimalSprite::loop(AStarResult* node, AStarResult* endNode) {
addSiblings2List(node, endNode);
// remove node (visited ) from openList
removeFromOpenList(node);
AStarResult* topNode = getTopNodes();
if (topNode != NULL) {
// 找到终点
if (pointEqual2point(topNode->point, endNode->point)) {
// 加入终点到close list
removeFromOpenList(topNode);
return topNode;
}
return loop(topNode, endNode);
}
return NULL;
}
/**
* 说白了。A*算法就是从open表里,把节点中 G + H 最小的node,保存在 close 表里。就完了。最后根据parent回朔回去就是路径
*
*/
AStarResult* AnimalSprite::AStarFinder(int * mapdata, DetectPoint start, DetectPoint end) {
//CCLOG("Cat(%d) finding (%d, %d) ==> (%d, %d)..", this->a_id, start.dpx, start.dpy, end.dpx, end.dpy);
clearCloseList();
if (detectBlock(end.dpx, end.dpy, GOING_NONE) != 1){
return NULL;
}
if (pointEqual2point(start, end)){
return NULL;
}
AStarResult* curNode = new AStarResult;
curNode->point = start;
AStarResult* endNode = new AStarResult;
endNode->point = end;
if (pointEqual2point(curNode->point, endNode->point) == false) {
openList = NULL;
closeList = NULL;
AStarResult* lastNode = loop(curNode, endNode);
if (lastNode != NULL){
//CCLOG("found path");
// add the endNode into closeList
AStarResult* p = lastNode;
AStarResult* pParent;
while (p != NULL) {
//p->sp = Sprite::create("黄.jpg");
//p->sp->setScale(pointScale);
//game_scene->test_drawBlockAtPos(p->point, p->sp);
pParent = p->parent;
if (pParent != NULL) {
pParent->path_child = p;
}
p = pParent;
}
clearOpenList();
}else{
CCLOG("no path to target!!");
return NULL;
}
}
return closeList;// closeList never be null cause it=endNode, but no path, so return path_child
}
如注释所说,就是把G+H最小的Node保存在list里。然后按照倒序取出就是要走的路径。
最后别忘了释放内存。
看懂原理后,各位都有自己的实现方式。我这就算是抛砖引玉而已。
谢谢。