cocos2dx A*算法

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

使用cocos2dx 3.2 原理都一样

淡蓝色的点是地图

深蓝色的点是障碍物

绿色的点是路径

暗绿色的点是搜寻过的点

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

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

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

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

[cpp] view plaincopy

  1. #ifndef __HELLOWORLD_SCENE_H__
  2. #define __HELLOWORLD_SCENE_H__
  3. #include "cocos2d.h"
  4. #include "vector"
  5. using namespace std;
  6. USING_NS_CC;
  7. class PathSprite : public cocos2d::Sprite//继承Sprite类, 因为要在里面加些其他变量
  8. {
  9. PathSprite():Sprite()
  10. {
  11. m_parent = NULL;
  12. m_child = NULL;
  13. m_costToSource = 0;
  14. m_FValue = 0;
  15. };
  16. public:
  17. static PathSprite* create(const char* ch)
  18. {
  19. PathSprite *pRet = new PathSprite();
  20. if (pRet )
  21. {
  22. pRet->initWithFile(ch);
  23. pRet->autorelease();
  24. return pRet;
  25. }
  26. else
  27. {
  28. delete pRet;
  29. pRet = NULL;
  30. return NULL;
  31. }
  32. }
  33. PathSprite* m_parent;//父节点
  34. PathSprite* m_child;//子节点
  35. float m_costToSource;//到起始点的距离
  36. int m_x;//地图坐标
  37. int m_y;
  38. float m_FValue;
  39. };
  40. class PathSearchInfo//寻路类(主要负责寻路的参数和逻辑)
  41. {
  42. public:
  43. static int m_startX;//开始点
  44. static int m_startY;
  45. static int m_endX;//结束点
  46. static int m_endY;
  47. static vector<PathSprite*> m_openList;//开放列表(里面存放相邻节点)
  48. static vector<PathSprite*> m_inspectList;//检测列表(里面存放除了障碍物的节点)
  49. static vector<PathSprite*> m_pathList;//路径列表
  50. static void  barrierTest( vector<PathSprite*> &pathList,int x, int y)//模拟障碍物
  51. {
  52. PathSprite* _z = getObjByPointOfMapCoord(pathList, x, y);
  53. if (_z)
  54. {
  55. _z->setColor(ccColor3B::MAGENTA);
  56. removeObjFromList(pathList, _z);
  57. }
  58. }
  59. static float calculateTwoObjDistance(PathSprite* obj1, PathSprite* obj2)//计算两个物体间的距离
  60. {
  61. //        float _offsetX = obj1->m_x - obj2->m_x;
  62. //        float _offsetY = obj1->m_y - obj2->m_y;
  63. //        return sqrt( _offsetX * _offsetX + _offsetY * _offsetY);
  64. float _x = abs(obj2->m_x - obj1->m_x);
  65. float _y = abs(obj2->m_y - obj1->m_y);
  66. return _x + _y;
  67. }
  68. static void inspectTheAdjacentNodes(PathSprite* node, PathSprite* adjacent, PathSprite* endNode)//把相邻的节点放入开放节点中
  69. {
  70. if (adjacent)
  71. {
  72. float _x = abs(endNode->m_x - adjacent->m_x);
  73. float _y = abs(endNode->m_y - adjacent->m_y);
  74. float F , G, H1, H2, H3;
  75. adjacent->m_costToSource = node->m_costToSource + calculateTwoObjDistance(node, adjacent);//获得累计的路程
  76. G = adjacent->m_costToSource;
  77. //三种算法, 感觉H2不错
  78. H1 = _x + _y;
  79. H2 = hypot(_x, _y);
  80. H3 = max(_x, _y);
  81. #if 1 //A*算法 = Dijkstra算法 + 最佳优先搜索
  82. F = G + H2;
  83. #endif
  84. #if 0//Dijkstra算法
  85. F = G;
  86. #endif
  87. #if 0//最佳优先搜索
  88. F = H2;
  89. #endif
  90. adjacent->m_FValue = F;
  91. adjacent->m_parent = node;//设置父节点
  92. adjacent->setColor(Color3B::ORANGE);//搜寻过的节点设为橘色
  93. node->m_child = adjacent;//设置子节点
  94. PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, adjacent);//把检测过的点从检测列表中删除
  95. PathSearchInfo::m_openList.push_back(adjacent);//加入开放列表
  96. }
  97. }
  98. static PathSprite* getMinPathFormOpenList()//从开放节点中获取路径最小值
  99. {
  100. if (m_openList.size()>0) {
  101. PathSprite* _sp =* m_openList.begin();
  102. for (vector<PathSprite*>::iterator iter = m_openList.begin(); iter !=  m_openList.end(); iter++)
  103. {
  104. if ((*iter)->m_FValue < _sp->m_FValue)
  105. {
  106. _sp = *iter;
  107. }
  108. }
  109. return _sp;
  110. }
  111. else
  112. {
  113. return NULL;
  114. }
  115. }
  116. static PathSprite* getObjByPointOfMapCoord( vector<PathSprite*> &spriteVector,  int x, int y)//根据点获取对象
  117. {
  118. for (int i = 0; i < spriteVector.size(); i++)
  119. {
  120. if (spriteVector[i]->m_x == x && spriteVector[i]->m_y == y)
  121. {
  122. return spriteVector[i];
  123. }
  124. }
  125. return NULL;
  126. }
  127. static bool removeObjFromList(vector<PathSprite*> &spriteVector, PathSprite* sprite)//从容器中移除对象
  128. {
  129. for (vector<PathSprite*>::iterator iter = spriteVector.begin(); iter !=  spriteVector.end(); iter++)
  130. {
  131. if (*iter == sprite)
  132. {
  133. spriteVector.erase(iter);
  134. return true;
  135. }
  136. }
  137. return false;
  138. }
  139. };
  140. class HelloWorld : public cocos2d::Layer
  141. {
  142. public:
  143. // there‘s no ‘id‘ in cpp, so we recommend returning the class instance pointer
  144. static cocos2d::Scene* createScene();
  145. // Here‘s a difference. Method ‘init‘ in cocos2d-x returns bool, instead of returning ‘id‘ in cocos2d-iphone
  146. virtual bool init();
  147. // a selector callback
  148. void menuCloseCallback(cocos2d::Ref* pSender);
  149. // implement the "static create()" method manually
  150. CREATE_FUNC(HelloWorld);
  151. bool onTouchBegan(Touch* touch, Event* event);
  152. void onTouchMoved(Touch* touch, Event* event);
  153. void onTouchEnded(Touch* touch, Event* event);
  154. void calculatePath();//计算路径
  155. void drawPath();//绘制路径
  156. vector<PathSprite*> m_mapList;//地图
  157. void clearPath();//清理路径
  158. PathSprite* m_player;//人物 用于演示行走
  159. int m_playerMoveStep;//人物当前的行程
  160. void playerMove();//人物走动
  161. };
  162. #endif // __HELLOWORLD_SCENE_H__

[cpp] view plaincopy

  1. #include "HelloWorldScene.h"
  2. vector<PathSprite*> PathSearchInfo::m_openList;
  3. vector<PathSprite*> PathSearchInfo::m_inspectList;
  4. vector<PathSprite*> PathSearchInfo::m_pathList;
  5. int PathSearchInfo::m_startX;
  6. int PathSearchInfo::m_startY;
  7. int PathSearchInfo::m_endX;
  8. int PathSearchInfo::m_endY;
  9. Scene* HelloWorld::createScene()
  10. {
  11. // ‘scene‘ is an autorelease object
  12. auto scene = Scene::create();
  13. // ‘layer‘ is an autorelease object
  14. auto layer = HelloWorld::create();
  15. // add layer as a child to scene
  16. scene->addChild(layer);
  17. // return the scene
  18. return scene;
  19. }
  20. // on "init" you need to initialize your instance
  21. bool HelloWorld::init()
  22. {
  23. //////////////////////////////
  24. // 1. super init first
  25. if ( !Layer::init() )
  26. {
  27. return false;
  28. }
  29. Size visibleSize = Director::getInstance()->getVisibleSize();
  30. Vec2 origin = Director::getInstance()->getVisibleOrigin();
  31. Size winSize = Director::getInstance()->getWinSize();
  32. /////////////////////////////
  33. // 2. add a menu item with "X" image, which is clicked to quit the program
  34. //    you may modify it.
  35. // add a "close" icon to exit the progress. it‘s an autorelease object
  36. auto listener = EventListenerTouchOneByOne::create();
  37. listener->setSwallowTouches(true);
  38. listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
  39. listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
  40. listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this);
  41. _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
  42. //模拟一张地图 左上角 为(0,0) 主要是模拟tiledmap  每块的宽度为1
  43. int _width = 25;
  44. int _heigth = 15;
  45. for (int i = 0; i < _heigth; i++)
  46. {
  47. for (int j = 0; j < _width; j++)
  48. {
  49. PathSprite* _sp = PathSprite::create("CloseNormal.png");
  50. _sp->m_x = j;
  51. _sp->m_y = i;
  52. Size _size = _sp->getContentSize();
  53. _sp->setPosition(CCPoint(j * _size.width + 100, - i * _size.height + 600));
  54. m_mapList.push_back(_sp);
  55. this->addChild(_sp);
  56. }
  57. }
  58. //设置障碍物
  59. //    for (int i = 0; i < _heigth*_width/2; i++)
  60. //    {
  61. //
  62. //        int _x = CCRANDOM_0_1()*_width;
  63. //        int _y = CCRANDOM_0_1()*_heigth;
  64. //        if (_x ==0 && _y == 0) {
  65. //            continue;
  66. //        }
  67. //        PathSearchInfo::barrierTest(m_mapList,_x,_y);
  68. //    }
  69. for (int i = 0; i < 10; i++) {
  70. PathSearchInfo::barrierTest(m_mapList,5+i,10);
  71. PathSearchInfo::barrierTest(m_mapList,15,i+1);
  72. }
  73. //PathSprite::getObjByPointOfMapCoord(m_inspectList, 2, 5)->removeFromParent();
  74. //设置起始和终点
  75. PathSearchInfo::m_startX =0;
  76. PathSearchInfo::m_startY = 0;
  77. PathSearchInfo::m_endX = 4;
  78. PathSearchInfo::m_endY = 9;
  79. m_player = PathSprite::create("CloseSelected1.png");
  80. m_player->setColor(Color3B::RED);
  81. this->addChild(m_player);
  82. m_player->m_x = PathSearchInfo::m_startX;
  83. m_player->m_y = PathSearchInfo::m_startY;
  84. m_player->setPosition(PathSearchInfo::getObjByPointOfMapCoord(m_mapList, PathSearchInfo::m_startX, PathSearchInfo::m_startY)->getPosition());
  85. return true;
  86. }
  87. void HelloWorld::calculatePath()
  88. {
  89. //得到开始点的节点
  90. PathSprite* _sp = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_startX, PathSearchInfo::m_startY);
  91. //得到开始点的节点
  92. PathSprite* _endNode = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_endX, PathSearchInfo::m_endY);
  93. //因为是开始点 把到起始点的距离设为0
  94. _sp->m_costToSource = 0;
  95. _sp->m_FValue = 0;
  96. //把已经检测过的点从检测列表中删除
  97. PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, _sp);
  98. //然后加入开放列表
  99. PathSearchInfo::m_openList.push_back(_sp);
  100. PathSprite* _node = NULL;
  101. while (true)
  102. {
  103. //得到离起始点最近的点
  104. _node = PathSearchInfo::getMinPathFormOpenList();
  105. if (!_node)
  106. {
  107. //找不到路径
  108. break;
  109. }
  110. //把计算过的点从开放列表中删除
  111. PathSearchInfo::removeObjFromList(PathSearchInfo::m_openList, _node);
  112. int _x = _node->m_x;
  113. int _y = _node->m_y;
  114. //
  115. if (_x ==PathSearchInfo::m_endX && _y == PathSearchInfo::m_endY)
  116. {
  117. break;
  118. }
  119. //检测8个方向的相邻节点是否可以放入开放列表中
  120. PathSprite* _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x + 1, _y + 1);
  121. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  122. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y);
  123. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  124. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y-1);
  125. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  126. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y -1);
  127. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  128. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y - 1);
  129. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  130. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y);
  131. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  132. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y+1);
  133. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  134. _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y+1);
  135. PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode);
  136. }
  137. while (_node)
  138. {
  139. //PathSprite* _sp = node;
  140. PathSearchInfo::m_pathList.insert(PathSearchInfo::m_pathList.begin(), _node);
  141. _node = _node->m_parent;
  142. }
  143. }
  144. void HelloWorld::drawPath(  )
  145. {
  146. for (vector<PathSprite*>::iterator iter = PathSearchInfo::m_pathList.begin(); iter !=  PathSearchInfo::m_pathList.end(); iter++)
  147. {
  148. (*iter)->setColor(ccColor3B::GREEN);
  149. }
  150. }
  151. bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
  152. {
  153. //清除之前的路径
  154. clearPath();
  155. auto nodePosition = convertToNodeSpace( touch->getLocation() );
  156. log("%f, %f", nodePosition.x, nodePosition.y);
  157. for (int i = 0; i < PathSearchInfo::m_inspectList.size(); i++)
  158. {
  159. PathSprite* _sp = PathSearchInfo::m_inspectList[i];
  160. if (_sp->getBoundingBox().containsPoint(nodePosition))
  161. {
  162. //获取触摸点, 设置为终点
  163. PathSearchInfo::m_endX = _sp->m_x;
  164. PathSearchInfo::m_endY = _sp->m_y;
  165. //计算路径
  166. calculatePath();
  167. //绘制路径
  168. drawPath(  );
  169. playerMove();
  170. }
  171. }
  172. return true;
  173. }
  174. void HelloWorld::onTouchMoved(Touch* touch, Event* event)
  175. {
  176. // If it weren‘t for the TouchDispatcher, you would need to keep a reference
  177. // to the touch from touchBegan and check that the current touch is the same
  178. // as that one.
  179. // Actually, it would be even more complicated since in the Cocos dispatcher
  180. // you get Sets instead of 1 UITouch, so you‘d need to loop through the set
  181. // in each touchXXX method.
  182. }
  183. void HelloWorld::onTouchEnded(Touch* touch, Event* event)
  184. {
  185. }
  186. void HelloWorld::menuCloseCallback(Ref* pSender)
  187. {
  188. #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  189. MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
  190. return;
  191. #endif
  192. Director::getInstance()->end();
  193. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  194. exit(0);
  195. #endif
  196. }
  197. void HelloWorld::clearPath()
  198. {
  199. for (vector<PathSprite*>::iterator iter = m_mapList.begin(); iter !=  m_mapList.end(); iter++)
  200. {
  201. (*iter)->setColor(ccColor3B::WHITE);
  202. (*iter)->m_costToSource = 0;
  203. (*iter)->m_FValue = 0;
  204. (*iter)->m_parent = NULL;
  205. (*iter)->m_child = NULL;
  206. }
  207. //把移除了障碍物的地图放入检测列表中
  208. PathSearchInfo::m_inspectList = m_mapList;
  209. PathSearchInfo::m_openList.clear();
  210. PathSearchInfo::m_pathList.clear();
  211. PathSearchInfo::m_startX = m_player->m_x;
  212. PathSearchInfo::m_startY = m_player->m_y;
  213. m_player->stopAllActions();
  214. m_playerMoveStep = 0;
  215. }
  216. void HelloWorld::playerMove()
  217. {
  218. m_playerMoveStep++;
  219. if (m_playerMoveStep >= PathSearchInfo::m_pathList.size()) {
  220. return;
  221. }
  222. m_player->m_x = PathSearchInfo::m_pathList[m_playerMoveStep]->m_x;
  223. m_player->m_y = PathSearchInfo::m_pathList[m_playerMoveStep]->m_y;
  224. m_player->runAction(Sequence::create(MoveTo::create(0.2, PathSearchInfo::m_pathList[m_playerMoveStep]->getPosition()), CallFunc::create(this, SEL_CallFunc(&HelloWorld::playerMove)) , NULL));
  225. }
时间: 2024-10-16 13:38:15

cocos2dx A*算法的相关文章

Cocos2d-x 地图行走的实现2:SPFA算法

上一节<Cocos2d-x 地图行走的实现1:图论与Dijkstra算法> http://blog.csdn.net/stevenkylelee/article/details/38408253 本节实践另一种求最短路径算法:SPFA 1.寻路算法实现上的优化 上一节我们实现的Dijkstra用了一个哈希表来保存搜索到的路径树.如果能用直接的访问的方式,就不要用哈希表,因为直接访问的方式会比哈希表更快.我们修改一下图顶点的数据结构.如下: /* 图顶点 */ class Vertex { fr

Cocos2d-x 地图行走的实现3:A*算法

上一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http://blog.csdn.net/stevenkylelee/article/details/38440663 1.修改一下Dijkstra的实现 回顾一下之前Dijkstra的实现.Dijkstra需要从一个表Q中选出一个路径代价最小的顶点.之前我们的实现是,一开始就把所有的顶点都放入这个表Q中.仔细想下就会发现,那些被初始化为路径代价最大值0x0FFFFFFF的顶点是不可能会被选中的,对于这些顶点不需要遍历.从表中取出

Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问

A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 2.首先推断该点是不是不能够穿越的点,或者是已经再close中了 3.假设2步骤为真.什么都不做,假设为假,那么我们就进行加入了 4.假设在加入的时候,发现该点在open中不存在.那么我们直接加入,并且视之为当前节点,假设该点              存在open中,那么我们比較G值,假设发现当

Cocos2d-x游戏开发_战斗算法

我的战斗算法的核心代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 private void aHitb(HeroBean a,HeroBean b){         ///*自身状态(已经移到aHitBTeam那里)         //判断A能否出招或者受到伤害什么的

Cocos2d-x教程(33)-三维物体AABB碰撞检测算法

欢迎加入Cocos2d-x 交流群:193411763 转载时请注明原文出处 :http://blog.csdn.net/u012945598/article/details/38870705 ---------------------------------------------------------------------------------------------------------------------------------------------------------

基于Cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法

基于Cocos2d-x的2D空间中的OBB(Orient Bounding Box)碰撞检测算法 尊重原创:http://cn.cocos2d-x.org/tutorial/show?id=1577

Cocos2d-x教程(35)-三维拾取Ray-AABB碰撞检测算法

欢迎加入Cocos2d-x 交流群:193411763 转载时请注明原文出处 :http://blog.csdn.net/u012945598/article/details/39927911 ---------------------------------------------------------------------------------------------------------------------------------------------------------

Cocos2d-x 2地图步行实现:SPFA算法

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee 上一节<Cocos2d-x 地图行走的实现1:图论与Dijkstra算法> http://blog.csdn.net/stevenkylelee/article/details/38408253 下一节<Cocos2d-x 地图行走的实现3:A*算法> http://blog.csdn.net/stevenkylelee/article/details/38456419

Cocos2d-x教程(34)-三维物体OBB碰撞检测算法

欢迎加入Cocos2d-x 交流群:193411763 转载时请注明原文出处 :http://blog.csdn.net/u012945598/article/details/39665911 ---------------------------------------------------------------------------------------------------------------------------------------- 在上一篇文章中讲解了AABB包围