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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值