cocos2dx游戏中A*寻路算法的实现

来源:互联网 发布:nginx查看端口是否 编辑:程序博客网 时间:2024/05/01 23:47

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里。然后按照倒序取出就是要走的路径。

最后别忘了释放内存。

看懂原理后,各位都有自己的实现方式。我这就算是抛砖引玉而已。

谢谢。

0 0
原创粉丝点击