首页 > 代码库 > cocos2dx A*算法

cocos2dx A*算法

头文件和源文件复制到项目中就能用了! have fun

使用cocos2dx 3.2 原理都一样

淡蓝色的点是地图

深蓝色的点是障碍物

绿色的点是路径

暗绿色的点是搜寻过的点

红色的点是按路径行走的点

 

 

dijkstra算法 会发现路径最短,但寻找过的路径比较多(计算速度慢)

 

最佳优先搜索算法会发现寻找过的路径少了(计算速度提高了),但走了许多弯路

 

A星算法 结合了上面2种算法 即寻找到了最短路径, 搜寻过的路径也比较少

 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #ifndef __HELLOWORLD_SCENE_H__  
  2. #define __HELLOWORLD_SCENE_H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include "vector"  
  6. using namespace std;  
  7. USING_NS_CC;  
  8.   
  9.   
  10. class PathSprite : public cocos2d::Sprite//继承Sprite类, 因为要在里面加些其他变量  
  11. {  
  12.     PathSprite():Sprite()  
  13.     {  
  14.         m_parent = NULL;  
  15.         m_child = NULL;  
  16.         m_costToSource = 0;  
  17.         m_FValue = 0;  
  18.     };  
  19. public:  
  20.     static PathSprite* create(const char* ch)  
  21.     {  
  22.         PathSprite *pRet = new PathSprite();  
  23.         if (pRet )  
  24.         {  
  25.             pRet->initWithFile(ch);  
  26.             pRet->autorelease();  
  27.             return pRet;  
  28.         }  
  29.         else  
  30.         {  
  31.             delete pRet;  
  32.             pRet = NULL;  
  33.             return NULL;  
  34.         }  
  35.     }  
  36.     PathSprite* m_parent;//父节点  
  37.     PathSprite* m_child;//子节点  
  38.     float m_costToSource;//到起始点的距离  
  39.     int m_x;//地图坐标  
  40.     int m_y;  
  41.     float m_FValue;  
  42. };  
  43.   
  44. class PathSearchInfo//寻路类(主要负责寻路的参数和逻辑)  
  45. {  
  46. public:  
  47.       
  48.     static int m_startX;//开始点  
  49.     static int m_startY;  
  50.     static int m_endX;//结束点  
  51.     static int m_endY;  
  52.       
  53.     static vector<PathSprite*> m_openList;//开放列表(里面存放相邻节点)  
  54.     static vector<PathSprite*> m_inspectList;//检测列表(里面存放除了障碍物的节点)  
  55.     static vector<PathSprite*> m_pathList;//路径列表  
  56.     static void  barrierTest( vector<PathSprite*> &pathList,int x, int y)//模拟障碍物  
  57.     {  
  58.         PathSprite* _z = getObjByPointOfMapCoord(pathList, x, y);  
  59.         if (_z)  
  60.         {  
  61.             _z->setColor(ccColor3B::MAGENTA);  
  62.             removeObjFromList(pathList, _z);  
  63.         }  
  64.     }  
  65.     static float calculateTwoObjDistance(PathSprite* obj1, PathSprite* obj2)//计算两个物体间的距离  
  66.     {  
  67. //        float _offsetX = obj1->m_x - obj2->m_x;  
  68. //        float _offsetY = obj1->m_y - obj2->m_y;  
  69. //        return sqrt( _offsetX * _offsetX + _offsetY * _offsetY);  
  70.           
  71.         float _x = abs(obj2->m_x - obj1->m_x);  
  72.         float _y = abs(obj2->m_y - obj1->m_y);  
  73.           
  74.         return _x + _y;  
  75.     }  
  76.     static void inspectTheAdjacentNodes(PathSprite* node, PathSprite* adjacent, PathSprite* endNode)//把相邻的节点放入开放节点中  
  77.     {  
  78.         if (adjacent)  
  79.         {  
  80.             float _x = abs(endNode->m_x - adjacent->m_x);  
  81.             float _y = abs(endNode->m_y - adjacent->m_y);  
  82.               
  83.             float F , G, H1, H2, H3;  
  84.             adjacent->m_costToSource = node->m_costToSource + calculateTwoObjDistance(node, adjacent);//获得累计的路程  
  85.             G = adjacent->m_costToSource;  
  86.               
  87.             //三种算法, 感觉H2不错  
  88.             H1 = _x + _y;  
  89.             H2 = hypot(_x, _y);  
  90.             H3 = max(_x, _y);  
  91.   
  92. #if 1 //A*算法 = Dijkstra算法 + 最佳优先搜索  
  93.             F = G + H2;  
  94. #endif  
  95. #if 0//Dijkstra算法  
  96.             F = G;  
  97. #endif  
  98. #if 0//最佳优先搜索  
  99.             F = H2;  
  100. #endif  
  101.             adjacent->m_FValue = F;  
  102.               
  103.             adjacent->m_parent = node;//设置父节点  
  104.             adjacent->setColor(Color3B::ORANGE);//搜寻过的节点设为橘色  
  105.             node->m_child = adjacent;//设置子节点  
  106.             PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, adjacent);//把检测过的点从检测列表中删除  
  107.             PathSearchInfo::m_openList.push_back(adjacent);//加入开放列表  
  108.         }  
  109.     }  
  110.     static PathSprite* getMinPathFormOpenList()//从开放节点中获取路径最小值  
  111.     {  
  112.         if (m_openList.size()>0) {  
  113.             PathSprite* _sp =* m_openList.begin();  
  114.             for (vector<PathSprite*>::iterator iter = m_openList.begin(); iter !=  m_openList.end(); iter++)  
  115.             {  
  116.                 if ((*iter)->m_FValue < _sp->m_FValue)  
  117.                 {  
  118.                     _sp = *iter;  
  119.                 }  
  120.             }  
  121.             return _sp;  
  122.         }  
  123.         else  
  124.         {  
  125.             return NULL;  
  126.         }  
  127.           
  128.     }  
  129.     static PathSprite* getObjByPointOfMapCoord( vector<PathSprite*> &spriteVector,  int x, int y)//根据点获取对象  
  130.     {  
  131.         for (int i = 0; i < spriteVector.size(); i++)  
  132.         {  
  133.             if (spriteVector[i]->m_x == x && spriteVector[i]->m_y == y)  
  134.             {  
  135.                 return spriteVector[i];  
  136.             }  
  137.         }  
  138.         return NULL;  
  139.     }  
  140.     static bool removeObjFromList(vector<PathSprite*> &spriteVector, PathSprite* sprite)//从容器中移除对象  
  141.     {  
  142.         for (vector<PathSprite*>::iterator iter = spriteVector.begin(); iter !=  spriteVector.end(); iter++)  
  143.         {  
  144.             if (*iter == sprite)  
  145.             {  
  146.                 spriteVector.erase(iter);  
  147.                 return true;  
  148.             }  
  149.         }  
  150.         return false;  
  151.           
  152.     }  
  153. };  
  154.   
  155. class HelloWorld : public cocos2d::Layer  
  156. {  
  157. public:  
  158.     // there‘s no ‘id‘ in cpp, so we recommend returning the class instance pointer  
  159.     static cocos2d::Scene* createScene();  
  160.       
  161.     // Here‘s a difference. Method ‘init‘ in cocos2d-x returns bool, instead of returning ‘id‘ in cocos2d-iphone  
  162.     virtual bool init();    
  163.       
  164.     // a selector callback  
  165.     void menuCloseCallback(cocos2d::Ref* pSender);  
  166.       
  167.     // implement the "static create()" method manually  
  168.     CREATE_FUNC(HelloWorld);  
  169.       
  170.     bool onTouchBegan(Touch* touch, Event* event);  
  171.     void onTouchMoved(Touch* touch, Event* event);  
  172.     void onTouchEnded(Touch* touch, Event* event);  
  173.       
  174.     void calculatePath();//计算路径  
  175.     void drawPath();//绘制路径  
  176.     vector<PathSprite*> m_mapList;//地图  
  177.       
  178.     void clearPath();//清理路径  
  179.       
  180.     PathSprite* m_player;//人物 用于演示行走  
  181.     int m_playerMoveStep;//人物当前的行程  
  182.     void playerMove();//人物走动  
  183. };  
  184.   
  185. #endif // __HELLOWORLD_SCENE_H__  
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. #include "HelloWorldScene.h"  
  2.   
  3. vector<PathSprite*> PathSearchInfo::m_openList;  
  4.   
  5. vector<PathSprite*> PathSearchInfo::m_inspectList;  
  6.   
  7. vector<PathSprite*> PathSearchInfo::m_pathList;  
  8.   
  9. int PathSearchInfo::m_startX;  
  10.   
  11. int PathSearchInfo::m_startY;  
  12.   
  13. int PathSearchInfo::m_endX;  
  14.   
  15. int PathSearchInfo::m_endY;  
  16.   
  17. Scene* HelloWorld::createScene()  
  18. {  
  19.     // ‘scene‘ is an autorelease object  
  20.     auto scene = Scene::create();  
  21.       
  22.     // ‘layer‘ is an autorelease object  
  23.     auto layer = HelloWorld::create();  
  24.       
  25.     // add layer as a child to scene  
  26.     scene->addChild(layer);  
  27.       
  28.     // return the scene  
  29.     return scene;  
  30. }  
  31.   
  32. // on "init" you need to initialize your instance  
  33. bool HelloWorld::init()  
  34. {  
  35.     //////////////////////////////  
  36.     // 1. super init first  
  37.     if ( !Layer::init() )  
  38.     {  
  39.         return false;  
  40.     }  
  41.       
  42.     Size visibleSize = Director::getInstance()->getVisibleSize();  
  43.     Vec2 origin = Director::getInstance()->getVisibleOrigin();  
  44.     Size winSize = Director::getInstance()->getWinSize();  
  45.       
  46.     /////////////////////////////  
  47.     // 2. add a menu item with "X" image, which is clicked to quit the program  
  48.     //    you may modify it.  
  49.       
  50.     // add a "close" icon to exit the progress. it‘s an autorelease object  
  51.       
  52.     auto listener = EventListenerTouchOneByOne::create();  
  53.     listener->setSwallowTouches(true);  
  54.       
  55.     listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);  
  56.     listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);  
  57.     listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);  
  58.       
  59.     _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);  
  60.       
  61.       
  62.       
  63.     //模拟一张地图 左上角 为(0,0) 主要是模拟tiledmap  每块的宽度为1  
  64.     int _width = 25;  
  65.     int _heigth = 15;  
  66.     for (int i = 0; i < _heigth; i++)  
  67.     {  
  68.         for (int j = 0; j < _width; j++)  
  69.         {  
  70.             PathSprite* _sp = PathSprite::create("CloseNormal.png");  
  71.             _sp->m_x = j;  
  72.             _sp->m_y = i;  
  73.             Size _size = _sp->getContentSize();  
  74.             _sp->setPosition(CCPoint(j * _size.width + 100, - i * _size.height + 600));  
  75.             m_mapList.push_back(_sp);  
  76.             this->addChild(_sp);  
  77.         }  
  78.     }  
  79.       
  80.     //设置障碍物  
  81. //    for (int i = 0; i < _heigth*_width/2; i++)  
  82. //    {  
  83. //          
  84. //        int _x = CCRANDOM_0_1()*_width;  
  85. //        int _y = CCRANDOM_0_1()*_heigth;  
  86. //        if (_x ==0 && _y == 0) {  
  87. //            continue;  
  88. //        }  
  89. //        PathSearchInfo::barrierTest(m_mapList,_x,_y);  
  90. //    }  
  91.     for (int i = 0; i < 10; i++) {  
  92.         PathSearchInfo::barrierTest(m_mapList,5+i,10);  
  93.         PathSearchInfo::barrierTest(m_mapList,15,i+1);  
  94.     }  
  95.       
  96.         //PathSprite::getObjByPointOfMapCoord(m_inspectList, 2, 5)->removeFromParent();  
  97.       
  98.     //设置起始和终点  
  99.     PathSearchInfo::m_startX =0;  
  100.     PathSearchInfo::m_startY = 0;  
  101.       
  102.     PathSearchInfo::m_endX = 4;  
  103.     PathSearchInfo::m_endY = 9;  
  104.       
  105.     m_player = PathSprite::create("CloseSelected1.png");  
  106.     m_player->setColor(Color3B::RED);  
  107.     this->addChild(m_player);  
  108.       
  109.     m_player->m_x = PathSearchInfo::m_startX;  
  110.     m_player->m_y = PathSearchInfo::m_startY;  
  111.     m_player->setPosition(PathSearchInfo::getObjByPointOfMapCoord(m_mapList, PathSearchInfo::m_startX, PathSearchInfo::m_startY)->getPosition());  
  112.     return true;  
  113. }  
  114.   
  115. void HelloWorld::calculatePath()  
  116. {  
  117.       
  118.     //得到开始点的节点  
  119.     PathSprite* _sp = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_startX, PathSearchInfo::m_startY);  
  120.     //得到开始点的节点  
  121.     PathSprite* _endNode = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_endX, PathSearchInfo::m_endY);  
  122.     //因为是开始点 把到起始点的距离设为0  
  123.     _sp->m_costToSource = 0;  
  124.     _sp->m_FValue = 0;  
  125.     //把已经检测过的点从检测列表中删除  
  126.     PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, _sp);  
  127.     //然后加入开放列表  
  128.     PathSearchInfo::m_openList.push_back(_sp);  
  129.       
  130.     PathSprite* _node = NULL;  
  131.     while (true)  
  132.     {  
  133.         //得到离起始点最近的点  
  134.         _node = PathSearchInfo::getMinPathFormOpenList();  
  135.         if (!_node)  
  136.         {  
  137.             //找不到路径  
  138.             break;  
  139.         }  
  140.         //把计算过的点从开放列表中删除  
  141.         PathSearchInfo::removeObjFromList(PathSearchInfo::m_openList, _node);  
  142.         int _x = _node->m_x;  
  143.         int _y = _node->m_y;  
  144.           
  145.         //  
  146.         if (_x ==PathSearchInfo::m_endX && _y == PathSearchInfo::m_endY)  
  147.         {  
  148.             break;  
  149.         }  
  150.           
  151.         //检测8个方向的相邻节点是否可以放入开放列表中  
  152.         PathSprite* _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x + 1, _y + 1);  
  153.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  154.           
  155.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y);  
  156.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  157.           
  158.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y-1);  
  159.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  160.           
  161.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y -1);  
  162.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  163.           
  164.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y - 1);  
  165.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  166.           
  167.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y);  
  168.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  169.           
  170.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y+1);  
  171.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  172.           
  173.         _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y+1);  
  174.         PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);  
  175.           
  176.     }  
  177.       
  178.     while (_node)  
  179.     {  
  180.         //PathSprite* _sp = node;  
  181.         PathSearchInfo::m_pathList.insert(PathSearchInfo::m_pathList.begin(), _node);  
  182.         _node = _node->m_parent;  
  183.     }  
  184. }  
  185.   
  186.   
  187. void HelloWorld::drawPath(  )  
  188. {  
  189.     for (vector<PathSprite*>::iterator iter = PathSearchInfo::m_pathList.begin(); iter !=  PathSearchInfo::m_pathList.end(); iter++)  
  190.     {  
  191.         (*iter)->setColor(ccColor3B::GREEN);  
  192.     }  
  193.       
  194. }  
  195.   
  196.   
  197. bool HelloWorld::onTouchBegan(Touch* touch, Event* event)  
  198. {  
  199.     //清除之前的路径  
  200.     clearPath();  
  201.       
  202.     auto nodePosition = convertToNodeSpace( touch->getLocation() );  
  203.     log("%f, %f", nodePosition.x, nodePosition.y);  
  204.     for (int i = 0; i < PathSearchInfo::m_inspectList.size(); i++)  
  205.     {  
  206.         PathSprite* _sp = PathSearchInfo::m_inspectList[i];  
  207.           
  208.         if (_sp->getBoundingBox().containsPoint(nodePosition))  
  209.         {  
  210.             //获取触摸点, 设置为终点  
  211.             PathSearchInfo::m_endX = _sp->m_x;  
  212.             PathSearchInfo::m_endY = _sp->m_y;  
  213.             //计算路径  
  214.             calculatePath();  
  215.             //绘制路径  
  216.             drawPath(  );  
  217.             playerMove();  
  218.               
  219.         }  
  220.           
  221.     }  
  222.     return true;  
  223. }  
  224.   
  225. void HelloWorld::onTouchMoved(Touch* touch, Event* event)  
  226. {  
  227.     // If it weren‘t for the TouchDispatcher, you would need to keep a reference  
  228.     // to the touch from touchBegan and check that the current touch is the same  
  229.     // as that one.  
  230.     // Actually, it would be even more complicated since in the Cocos dispatcher  
  231.     // you get Sets instead of 1 UITouch, so you‘d need to loop through the set  
  232.     // in each touchXXX method.  
  233.       
  234. }  
  235. void HelloWorld::onTouchEnded(Touch* touch, Event* event)  
  236. {  
  237.       
  238. }   
  239.   
  240.   
  241. void HelloWorld::menuCloseCallback(Ref* pSender)  
  242. {  
  243. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)  
  244.     MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");  
  245.     return;  
  246. #endif  
  247.       
  248.     Director::getInstance()->end();  
  249.       
  250. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)  
  251.     exit(0);  
  252. #endif  
  253. }  
  254.   
  255. void HelloWorld::clearPath()  
  256. {  
  257.     for (vector<PathSprite*>::iterator iter = m_mapList.begin(); iter !=  m_mapList.end(); iter++)  
  258.     {  
  259.         (*iter)->setColor(ccColor3B::WHITE);  
  260.         (*iter)->m_costToSource = 0;  
  261.         (*iter)->m_FValue = 0;  
  262.         (*iter)->m_parent = NULL;  
  263.         (*iter)->m_child = NULL;  
  264.     }  
  265.       
  266.     //把移除了障碍物的地图放入检测列表中  
  267.     PathSearchInfo::m_inspectList = m_mapList;  
  268.     PathSearchInfo::m_openList.clear();  
  269.     PathSearchInfo::m_pathList.clear();  
  270.   
  271.     PathSearchInfo::m_startX = m_player->m_x;  
  272.     PathSearchInfo::m_startY = m_player->m_y;  
  273.     m_player->stopAllActions();  
  274.   
  275.     m_playerMoveStep = 0;  
  276. }  
  277.   
  278. void HelloWorld::playerMove()  
  279. {  
  280.     m_playerMoveStep++;  
  281.       
  282.     if (m_playerMoveStep >= PathSearchInfo::m_pathList.size()) {  
  283.         return;  
  284.     }  
  285.       
  286.     m_player->m_x = PathSearchInfo::m_pathList[m_playerMoveStep]->m_x;  
  287.     m_player->m_y = PathSearchInfo::m_pathList[m_playerMoveStep]->m_y;  
  288.       
  289.     m_player->runAction(Sequence::create(MoveTo::create(0.2, PathSearchInfo::m_pathList[m_playerMoveStep]->getPosition()), CallFunc::create(this, SEL_CallFunc(&HelloWorld::playerMove)) , NULL));  
  290.       
  291. }  



cocos2dx A*算法