cocos2dx 45度Staggered格式A*寻路 曼哈顿算法(待优化)

来源:互联网 发布:mysql #什么意思 编辑:程序博客网 时间:2024/05/01 02:58

cocos2dx 45度Staggered格式A*寻路 曼哈顿算法(待优化) 


转自:http://blog.csdn.net/hpking/article/details/9775289


#ifndef __ASTARPATHFINDER_H__
#define __ASTARPATHFINDER_H__ #include "cocos2d.h" USING_NS_CC; /** * 横向移动一格的路径评分 */static const int COST_HORIZONTAL = 20; /** * 竖向移动一格的路径评分 */static const int COST_VERTICAL = 5; /** * 斜向移动一格的路径评分 */static const int COST_DIAGONAL = 12; class PathInfo; /** * A星寻路类 * @author hpking * */class AStarPathFinder{// 未探索的节点列表    cocos2d::CCArray_openSteps;// 已探索的,不需要再寻路的节点列表    cocos2d::CCArray_closedSteps; // 地图相关数据PathInfo_pathInfo; public:AStarPathFinder(PathInfoinfo);virtual ~AStarPathFinder();     /**     * public 寻路     *     * @param CCPoint startPoint tile开始坐标点     * @param CCPoint endPoint tile结束坐标点     * @return CCArray* 读取方法:CCPointFromString ( string->getCString() )     */    CCArrayfindCCPoint startTilePtCCPoint endTilePt ); private:// 最短路径步数class ShortestPathStep : public cocos2d::CCObject{public:bool initWithPositioncocos2d::CCPoint pos ){bool bRet = false; do{position = pos;gScore = 0;hScore = 0;parent = NULL;inOpen = false;inClose = false; bRet = true;}while ( 0 ); return bRet;} int fScore(){return this->getGScore() + this->getHScore();} inline bool operator==( const ShortestPathStepother ){return isEqualother );} bool isEqualconst ShortestPathStepother ){return this->getPosition().equals ( other->getPosition() );} static ShortestPathStepinstcocos2d::CCPoint pos ){AStarPathFinder::ShortestPathStepsps = new AStarPathFinder::ShortestPathStep; if ( sps && sps->initWithPosition ( pos ) ){sps->autorelease();return sps;} CC_SAFE_DELETE ( sps );return NULL;} CC_SYNTHESIZEcocos2d::CCPointpositionPosition );CC_SYNTHESIZEintgScore, GScore );CC_SYNTHESIZEinthScore, HScore );CC_SYNTHESIZEShortestPathStep*, parentParent );CC_SYNTHESIZEboolinOpen, InOpen );CC_SYNTHESIZEboolinClose, InClose ); private:cocos2d::CCStringdescription(){return CCString::createWithFormat ( "pos = [%f, %f], g=%d, h=%d, f=%d"this->getPosition().xthis->getPosition().ythis->getGScore(), this->getHScore(), this->fScore() );}}; private:    void destroyLists();     CCArraycreatePathShortestPathStepstep );//int xStart, int yStart    void findAndSortShortestPathStepstep ); void insertAndSortShortestPathStepstep );     /**     * private  判断是否超出边界或路点是否可走     *     * @param CCPoint tpt      * @return bool      */    bool isWalkableCCPoint tpt );     /**     * private  计算G值     *     * @param Node * curNode     * @param Node * node     * @return int     */    int getGValueShortestPathStepcurStepShortestPathStepstep );     /**     * private  计算H值     *     * @param Node * curNode     * @param Node * endNode     * @param Node * node     * @return int     */    int getHValueShortestPathStepcurStepShortestPathStependStepShortestPathStepstep );     cocos2d::CCArraygetAroundsNodeCCPoint tPt ); bool isInClosed(CCPoint tPt);     void setOpenSteps ( cocos2d::CCArrayvar );    void setClosedSteps ( cocos2d::CCArrayvar );    void setShortestPath ( cocos2d::CCArrayvar );}; #endif

#include "AStarPathFinder.h"#include "map/PathInfo.h" AStarPathFinder::AStarPathFinderPathInfoinfo ){    _pathInfo = info;    _openSteps = NULL;    _closedSteps = NULL;} AStarPathFinder::~AStarPathFinder(){    destroyLists();} // 获取毫秒时间long msNow(){struct cc_timeval now;CCTime::gettimeofdayCocos2d( &nowNULL );return ( now.tv_sec * 1000 + now.tv_usec / 1000 );} CCArrayAStarPathFinder::findCCPoint startTilePtCCPoint endTilePt ){    bool isFinded = false//能否找到路径,true-已找到     // 到达终点    if ( startTilePt.equals ( endTilePt ) )    {        CCLog ( "You're already there! :P" );        return NULL;    }     // 终点不可走,直接退出(可优化为最近的可走地点停止)    if ( !isWalkableendTilePt ) )    {        CCLog ( "blocked! :P" );        return NULL;    }     // 设置打开和封闭步数    setOpenSteps ( CCArray::create() );    setClosedSteps ( CCArray::create() );     //CCLog ( "From:(%f, %f) To(%f, %f)", startTilePt.x, startTilePt.y, endTilePt.x, endTilePt.y );     // 结束坐标    ShortestPathStependStep = ShortestPathStep::inst ( endTilePt );     // 插入开始点    insertAndSort ( ShortestPathStep::inst ( startTilePt ) );     ShortestPathStepcurStep;    long time1 = msNow();     do    {        // 取出并删除开放列表第一个元素        curStep = ( ShortestPathStep* ) _openSteps->objectAtIndex ( 0 );        curStep->setInClosetrue );        curStep->setInOpenfalse );        _closedSteps->addObject ( curStep );        _openSteps->removeObjectAtIndex ( 0 );         // 当前节点==目标节点        if ( curStep->getPosition().equalsendTilePt ) )        {            isFinded = true//能达到终点,找到路径            break;        }         // 取相邻八个方向的节点,去除不可通过和已在关闭列表中的节点        CCArrayaroundNodes  = getAroundsNode ( curStep->getPosition() );        //CCLog("8 dirc %d",aroundNodes->count());        CCObjectobj;        CCARRAY_FOREACH ( aroundNodesobj )        {            // 计算 G, H 值            CCStringstring = ( CCString* ) obj;            ShortestPathStepnextStep = new ShortestPathStep;            nextStep->initWithPosition ( CCPointFromString ( string->getCString() ) );             int g = getGValue ( curStep , nextStep );            int h = getHValue ( curStep , endStep , nextStep );             if ( nextStep->getInOpen() ) // 如果节点已在播放列表中            {                // 如果该节点新的G值比原来的G值小,修改F,G值,设置该节点的父节点为当前节点                if ( g < nextStep->getGScore() )                {                    nextStep->setGScoreg );                    nextStep->setHScoreh );                    nextStep->setParentcurStep );                    findAndSort ( nextStep );                    nextStep->release();                }            }            else // 如果节点不在开放列表中            {                // 插入开放列表中,并按照估价值排序                nextStep->setGScoreg );                nextStep->setHScoreh );                nextStep->setParentcurStep );                 insertAndSort ( nextStep );                nextStep->release();            }             //CCLog("open num:%d",_openSteps->count());        }    }    while ( _openSteps->count() > 0 );     CCLog"a* time:%d"msNow() - time1 );     /*if( _openSteps )    CCLog( "finded:%d, openlen %d, closelen %d", isFinded ? 1 : 0, _openSteps->count(), _closedSteps->count() );*/     // 找到路径    if ( isFinded )    {        CCArraypath = createPath ( curStep );         destroyLists ();         return path;    }    else // 没有找到路径    {        destroyLists ();         return NULL;    }} void AStarPathFinder::destroyLists(){    CC_SAFE_RELEASE_NULL ( _openSteps );    CC_SAFE_RELEASE_NULL ( _closedSteps );} CCArrayAStarPathFinder::createPathShortestPathStepstep )//int xStart, int yStart{    CCArraypath = CCArray::create();     CCStringstr;     do    {        if ( step->getParent() != NULL )        {            str = CCString::createWithFormat ( "{%f, %f}"step->getPosition().xstep->getPosition().y );            path->insertObject ( str, 0 );        }         step = step->getParent();    }    while ( step != NULL );     return path;} void AStarPathFinder::findAndSortShortestPathStepstep ){    unsigned int count = _openSteps->count();     if ( count < 1 )        return;     int stepFScore = step->fScore();     for ( unsigned int i = 0; i < counti++ )    {        ShortestPathStepsps = ( ShortestPathStep* ) _openSteps->objectAtIndex ( i );         if ( stepFScore <= sps->fScore() )            _openSteps->insertObject ( stepi );         if ( step->getPosition().equalssps->getPosition() ) )            _openSteps->removeObjectAtIndexi );    }} void AStarPathFinder::insertAndSortShortestPathStepstep ){    step->setInOpentrue );     int stepFScore = step->fScore();    unsigned int count = _openSteps->count();     ifcount == 0 )        _openSteps->addObjectstep );    else    {        for ( unsigned int i = 0; i < counti++ )        {            ShortestPathStepsps = ( ShortestPathStep* ) _openSteps->objectAtIndex ( i );             if ( stepFScore <= sps->fScore() )            {                _openSteps->insertObject ( stepi );                return;            }        }    }} bool AStarPathFinder::isWalkableCCPoint tPt ){    // 1. 是否是有效的地图上点(数组边界检查)    if ( tPt.x < _pathInfo->startPt.x || tPt.x >= _pathInfo->iCol )        return false;     if ( tPt.y < _pathInfo->startPt.y || tPt.y >= _pathInfo->iRow )        return false;     // 2. 是否是walkable    return _pathInfo->isWalkabletPt );}  /** * private  计算G值 * * @param ShortestPathStep * curStep * @param ShortestPathStep * step * @return int */int AStarPathFinder::getGValueShortestPathStepcurStepShortestPathStepstep ){    int g  = 0;     if ( curStep->getPosition().y == step->getPosition().y ) // 横向  左右    {        g = curStep->getGScore() + COST_HORIZONTAL;    }    else if ( curStep->getPosition().y + 2 == step->getPosition().y || curStep->getPosition().y - 2 == step->getPosition().y ) // 竖向  上下    {        g = curStep->getGScore() + COST_VERTICAL * 2;    }    else // 斜向  左上 左下 右上 右下    {        g = curStep->getGScore() + COST_DIAGONAL;    }     return g;} /** * private  计算H值 * * @param ShortestPathStep * curStep * @param ShortestPathStep * endStep * @param ShortestPathStep * step * @return int */int AStarPathFinder::getHValueShortestPathStepcurStepShortestPathStependStepShortestPathStepstep ){    if ( curStep == NULL || endStep == NULL || step == NULL )        return 0;     // 节点到0,0点的x轴距离    int to0  = step->getPosition().x * COST_HORIZONTAL + ( ( int )step->getPosition().y & 1 ) * COST_HORIZONTAL / 2;     // 终止节点到0,0点的x轴距离    int endTo0  = endStep->getPosition().x * COST_HORIZONTAL + ( ( int )endStep->getPosition().y & 1 ) * COST_HORIZONTAL / 2;     return abs ( ( float )endTo0 - ( float )to0 ) + abs ( ( float )endStep->getPosition().y - ( float )step->getPosition().y ) * COST_VERTICAL;} cocos2d::CCArrayAStarPathFinder::getAroundsNodeCCPoint tPt ){    CCArrayaroundNodes = CCArray::create();     /// 菱形组合的地图八方向与正常不同     // 左    CCPoint p = CCPointMake ( tPt.x - 1, tPt.y );    CCStringstr;     if ( isWalkable ( p ) && !isInClosedp ) ) // 可走并且不在关闭列表    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "left=%s", str->getCString() );        aroundNodes->addObject ( str );    }     // 右    p = CCPointMake ( tPt.x + 1, tPt.y );     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        // CCLOG( "right=%s", str->getCString() );        aroundNodes->addObject ( str );    }     // 上    p = CCPointMake ( tPt.xtPt.y - 2 );  // -2     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "up=%s", str->getCString() );        aroundNodes->addObject ( str );    }     // 下    p = CCPointMake ( tPt.xtPt.y + 2 );// + 2     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "down=%s", str->getCString() );        aroundNodes->addObject ( str );    }     // 左上    p = CCPointMake ( tPt.x - 1 + ( ( int )tPt.y & 1 ), tPt.y - 1 );     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "leftUp=%s", str->getCString() );        aroundNodes->addObject ( str );    }     // 左下    p = CCPointMake ( tPt.x - 1 + ( ( int )tPt.y & 1 ), tPt.y + 1 );     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "leftDown=%s", str->getCString() );        aroundNodes->addObject ( str );    }     //右上    p = CCPointMake ( tPt.x + ( ( int )tPt.y & 1 ), tPt.y - 1 );     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "rightUp=%s", str->getCString() );        aroundNodes->addObject ( str );    }     //右下    p = CCPointMake ( tPt.x + ( ( int )tPt.y & 1 ), tPt.y + 1 );     if ( isWalkable ( p ) && !isInClosedp ) )    {        str = CCString::createWithFormat ( "{%f, %f}"p.xp.y );        //CCLOG( "rightDown=%s", str->getCString() );        aroundNodes->addObject ( str );    }     return aroundNodes;} bool AStarPathFinder::isInClosedCCPoint pt ){    CCObjecttemp;    CCARRAY_FOREACH ( _closedStepstemp )    {        ShortestPathStepsps = ( ShortestPathStep* ) temp;         ifsps->getPosition().equalspt ) )        {            return true;        }    }     return false;} void AStarPathFinder::setOpenSteps ( cocos2d::CCArrayvar ){    if ( _openSteps != var )    {        CC_SAFE_RELEASE_NULL ( _openSteps );        CC_SAFE_RETAIN ( var );        _openSteps = var;    }} void AStarPathFinder::setClosedSteps ( cocos2d::CCArrayvar ){    if ( _closedSteps != var )    {        CC_SAFE_RELEASE_NULL ( _closedSteps );        CC_SAFE_RETAIN ( var );        _closedSteps = var;    }} void AStarPathFinder::setShortestPath ( cocos2d::CCArrayvar ){    /*if ( shortestPath != var )    {    CC_SAFE_RELEASE_NULL ( shortestPath );    CC_SAFE_RETAIN ( var );    shortestPath = var;    }*/}
0 0
原创粉丝点击