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

使用cocos2dx 3.2 原理都一样

淡蓝色的点是地图

深蓝色的点是障碍物

绿色的点是路径

暗绿色的点是搜寻过的点

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

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

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

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

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__ #include "cocos2d.h"
#include "vector"
using namespace std;
USING_NS_CC; class PathSprite : public cocos2d::Sprite//继承Sprite类, 由于要在里面加些其它变量
{
PathSprite():Sprite()
{
m_parent = NULL;
m_child = NULL;
m_costToSource = 0;
m_FValue = 0;
};
public:
static PathSprite* create(const char* ch)
{
PathSprite *pRet = new PathSprite();
if (pRet )
{
pRet->initWithFile(ch);
pRet->autorelease();
return pRet;
}
else
{
delete pRet;
pRet = NULL;
return NULL;
}
}
PathSprite* m_parent;//父节点
PathSprite* m_child;//子节点
float m_costToSource;//到起始点的距离
int m_x;//地图坐标
int m_y;
float m_FValue;
}; class PathSearchInfo//寻路类(主要负责寻路的參数和逻辑)
{
public: static int m_startX;//開始点
static int m_startY;
static int m_endX;//结束点
static int m_endY; static vector<PathSprite*> m_openList;//开放列表(里面存放相邻节点)
static vector<PathSprite*> m_inspectList;//检測列表(里面存放除了障碍物的节点)
static vector<PathSprite*> m_pathList;//路径列表
static void barrierTest( vector<PathSprite*> &pathList,int x, int y)//模拟障碍物
{
PathSprite* _z = getObjByPointOfMapCoord(pathList, x, y);
if (_z)
{
_z->setColor(ccColor3B::MAGENTA);
removeObjFromList(pathList, _z);
}
}
static float calculateTwoObjDistance(PathSprite* obj1, PathSprite* obj2)//计算两个物体间的距离
{
// float _offsetX = obj1->m_x - obj2->m_x;
// float _offsetY = obj1->m_y - obj2->m_y;
// return sqrt( _offsetX * _offsetX + _offsetY * _offsetY); float _x = abs(obj2->m_x - obj1->m_x);
float _y = abs(obj2->m_y - obj1->m_y); return _x + _y;
}
static void inspectTheAdjacentNodes(PathSprite* node, PathSprite* adjacent, PathSprite* endNode)//把相邻的节点放入开放节点中
{
if (adjacent)
{
float _x = abs(endNode->m_x - adjacent->m_x);
float _y = abs(endNode->m_y - adjacent->m_y); float F , G, H1, H2, H3;
adjacent->m_costToSource = node->m_costToSource + calculateTwoObjDistance(node, adjacent);//获得累计的路程
G = adjacent->m_costToSource; //三种算法, 感觉H2不错
H1 = _x + _y;
H2 = hypot(_x, _y);
H3 = max(_x, _y); #if 1 //A*算法 = Dijkstra算法 + 最佳优先搜索
F = G + H2;
#endif
#if 0//Dijkstra算法
F = G;
#endif
#if 0//最佳优先搜索
F = H2;
#endif
adjacent->m_FValue = F; adjacent->m_parent = node;//设置父节点
adjacent->setColor(Color3B::ORANGE);//搜寻过的节点设为橘色
node->m_child = adjacent;//设置子节点
PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, adjacent);//把检測过的点从检測列表中删除
PathSearchInfo::m_openList.push_back(adjacent);//增加开放列表
}
}
static PathSprite* getMinPathFormOpenList()//从开放节点中获取路径最小值
{
if (m_openList.size()>0) {
PathSprite* _sp =* m_openList.begin();
for (vector<PathSprite*>::iterator iter = m_openList.begin(); iter != m_openList.end(); iter++)
{
if ((*iter)->m_FValue < _sp->m_FValue)
{
_sp = *iter;
}
}
return _sp;
}
else
{
return NULL;
} }
static PathSprite* getObjByPointOfMapCoord( vector<PathSprite*> &spriteVector, int x, int y)//依据点获取对象
{
for (int i = 0; i < spriteVector.size(); i++)
{
if (spriteVector[i]->m_x == x && spriteVector[i]->m_y == y)
{
return spriteVector[i];
}
}
return NULL;
}
static bool removeObjFromList(vector<PathSprite*> &spriteVector, PathSprite* sprite)//从容器中移除对象
{
for (vector<PathSprite*>::iterator iter = spriteVector.begin(); iter != spriteVector.end(); iter++)
{
if (*iter == sprite)
{
spriteVector.erase(iter);
return true;
}
}
return false; }
}; class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init(); // a selector callback
void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually
CREATE_FUNC(HelloWorld); bool onTouchBegan(Touch* touch, Event* event);
void onTouchMoved(Touch* touch, Event* event);
void onTouchEnded(Touch* touch, Event* event); void calculatePath();//计算路径
void drawPath();//绘制路径
vector<PathSprite*> m_mapList;//地图 void clearPath();//清理路径 PathSprite* m_player;//人物 用于演示行走
int m_playerMoveStep;//人物当前的行程
void playerMove();//人物走动
}; #endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"

vector<PathSprite*> PathSearchInfo::m_openList;

vector<PathSprite*> PathSearchInfo::m_inspectList;

vector<PathSprite*> PathSearchInfo::m_pathList;

int PathSearchInfo::m_startX;

int PathSearchInfo::m_startY;

int PathSearchInfo::m_endX;

int PathSearchInfo::m_endY;

Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create(); // 'layer' is an autorelease object
auto layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
} Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
Size winSize = Director::getInstance()->getWinSize(); /////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true); listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(HelloWorld::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(HelloWorld::onTouchEnded, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); //模拟一张地图 左上角 为(0,0) 主要是模拟tiledmap 每块的宽度为1
int _width = 25;
int _heigth = 15;
for (int i = 0; i < _heigth; i++)
{
for (int j = 0; j < _width; j++)
{
PathSprite* _sp = PathSprite::create("CloseNormal.png");
_sp->m_x = j;
_sp->m_y = i;
Size _size = _sp->getContentSize();
_sp->setPosition(CCPoint(j * _size.width + 100, - i * _size.height + 600));
m_mapList.push_back(_sp);
this->addChild(_sp);
}
} //设置障碍物
// for (int i = 0; i < _heigth*_width/2; i++)
// {
//
// int _x = CCRANDOM_0_1()*_width;
// int _y = CCRANDOM_0_1()*_heigth;
// if (_x ==0 && _y == 0) {
// continue;
// }
// PathSearchInfo::barrierTest(m_mapList,_x,_y);
// }
for (int i = 0; i < 10; i++) {
PathSearchInfo::barrierTest(m_mapList,5+i,10);
PathSearchInfo::barrierTest(m_mapList,15,i+1);
} //PathSprite::getObjByPointOfMapCoord(m_inspectList, 2, 5)->removeFromParent(); //设置起始和终点
PathSearchInfo::m_startX =0;
PathSearchInfo::m_startY = 0; PathSearchInfo::m_endX = 4;
PathSearchInfo::m_endY = 9; m_player = PathSprite::create("CloseSelected1.png");
m_player->setColor(Color3B::RED);
this->addChild(m_player); m_player->m_x = PathSearchInfo::m_startX;
m_player->m_y = PathSearchInfo::m_startY;
m_player->setPosition(PathSearchInfo::getObjByPointOfMapCoord(m_mapList, PathSearchInfo::m_startX, PathSearchInfo::m_startY)->getPosition());
return true;
} void HelloWorld::calculatePath()
{ //得到開始点的节点
PathSprite* _sp = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_startX, PathSearchInfo::m_startY);
//得到開始点的节点
PathSprite* _endNode = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, PathSearchInfo::m_endX, PathSearchInfo::m_endY);
//由于是開始点 把到起始点的距离设为0
_sp->m_costToSource = 0;
_sp->m_FValue = 0;
//把已经检測过的点从检測列表中删除
PathSearchInfo::removeObjFromList(PathSearchInfo::m_inspectList, _sp);
//然后增加开放列表
PathSearchInfo::m_openList.push_back(_sp); PathSprite* _node = NULL;
while (true)
{
//得到离起始点近期的点
_node = PathSearchInfo::getMinPathFormOpenList();
if (!_node)
{
//找不到路径
break;
}
//把计算过的点从开放列表中删除
PathSearchInfo::removeObjFromList(PathSearchInfo::m_openList, _node);
int _x = _node->m_x;
int _y = _node->m_y; //
if (_x ==PathSearchInfo::m_endX && _y == PathSearchInfo::m_endY)
{
break;
} //检測8个方向的相邻节点能否够放入开放列表中
PathSprite* _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x + 1, _y + 1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x +1, _y-1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y -1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y - 1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x -1, _y+1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = PathSearchInfo::getObjByPointOfMapCoord(PathSearchInfo::m_inspectList, _x , _y+1);
PathSearchInfo::inspectTheAdjacentNodes(_node, _adjacent, _endNode); } while (_node)
{
//PathSprite* _sp = node;
PathSearchInfo::m_pathList.insert(PathSearchInfo::m_pathList.begin(), _node);
_node = _node->m_parent;
}
} void HelloWorld::drawPath( )
{
for (vector<PathSprite*>::iterator iter = PathSearchInfo::m_pathList.begin(); iter != PathSearchInfo::m_pathList.end(); iter++)
{
(*iter)->setColor(ccColor3B::GREEN);
} } bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
//清除之前的路径
clearPath(); auto nodePosition = convertToNodeSpace( touch->getLocation() );
log("%f, %f", nodePosition.x, nodePosition.y);
for (int i = 0; i < PathSearchInfo::m_inspectList.size(); i++)
{
PathSprite* _sp = PathSearchInfo::m_inspectList[i]; if (_sp->getBoundingBox().containsPoint(nodePosition))
{
//获取触摸点, 设置为终点
PathSearchInfo::m_endX = _sp->m_x;
PathSearchInfo::m_endY = _sp->m_y;
//计算路径
calculatePath();
//绘制路径
drawPath( );
playerMove(); } }
return true;
} void HelloWorld::onTouchMoved(Touch* touch, Event* event)
{
// If it weren't for the TouchDispatcher, you would need to keep a reference
// to the touch from touchBegan and check that the current touch is the same
// as that one.
// Actually, it would be even more complicated since in the Cocos dispatcher
// you get Sets instead of 1 UITouch, so you'd need to loop through the set
// in each touchXXX method. }
void HelloWorld::onTouchEnded(Touch* touch, Event* event)
{ } void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
return;
#endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
} void HelloWorld::clearPath()
{
for (vector<PathSprite*>::iterator iter = m_mapList.begin(); iter != m_mapList.end(); iter++)
{
(*iter)->setColor(ccColor3B::WHITE);
(*iter)->m_costToSource = 0;
(*iter)->m_FValue = 0;
(*iter)->m_parent = NULL;
(*iter)->m_child = NULL;
} //把移除了障碍物的地图放入检測列表中
PathSearchInfo::m_inspectList = m_mapList;
PathSearchInfo::m_openList.clear();
PathSearchInfo::m_pathList.clear(); PathSearchInfo::m_startX = m_player->m_x;
PathSearchInfo::m_startY = m_player->m_y;
m_player->stopAllActions(); m_playerMoveStep = 0;
} void HelloWorld::playerMove()
{
m_playerMoveStep++; if (m_playerMoveStep >= PathSearchInfo::m_pathList.size()) {
return;
} m_player->m_x = PathSearchInfo::m_pathList[m_playerMoveStep]->m_x;
m_player->m_y = PathSearchInfo::m_pathList[m_playerMoveStep]->m_y; m_player->runAction(Sequence::create(MoveTo::create(0.2, PathSearchInfo::m_pathList[m_playerMoveStep]->getPosition()), CallFunc::create(this, SEL_CallFunc(&HelloWorld::playerMove)) , NULL)); }

cocos2dx A*算法的更多相关文章

  1. cocos2d-x学习日志(13) --A星寻路算法demo

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! A星算法简介: A*搜寻算法俗称A星 ...

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

    本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee 上一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http: ...

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

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

  4. Cocos2d-x 地图步行实现1:图论Dijkstra算法

    下一节<Cocos2d-x 地图行走的实现2:SPFA算法>: http://blog.csdn.net/stevenkylelee/article/details/38440663 本文 ...

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

    A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...

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

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

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

    欢迎增加Cocos2d-x 交流群:193411763 个中心点.1个旋转矩阵和3个1/2边长(注:一个旋转矩阵包括了三个旋转轴,若是二维的OBB包围盒则是一个中心点,两个旋转轴,两个1/2边长). ...

  8. cocos2dx下的A星算法

    这是我依据这篇博文http://hi.baidu.com/wsapyoemdfacmqr/item/bdfb5c0a74c904d01ef0466d.来在cocos2dx上编写.这是终于的效果图: 红 ...

  9. cocos2dx for lua A*寻路算法实现2

    关于A*算法的实现过程,简单来说就是一个计算权限的过程. 首先,创建一个地图节点类,"MapNode.lua" local MapNode = class("MapNod ...

随机推荐

  1. [转]linux 如何改变文件属性与权限

    转自:http://www.cnblogs.com/yangjinjin/p/3165076.html 我们知道档案权限对于一个系统的安全重要性,也知道档案的权限对于使用者与群组的相关性, 那如何修改 ...

  2. collect my database for test KCF tracker tools

    Path Button used to set dir where avi file saves, set path set video size and start record write to ...

  3. C# 一个简单的秒表引发的窗体卡死问题

    一个秒表程序也是我的一个心病,因为一直想写这样的一个东西,但是总往GUI那边想,所以就比较怵,可能是上学的时候学MFC搞出的后遗症吧,不过当我今天想好用Win Form(话说还是第一次写win for ...

  4. 运算符重载 C++ 编程思想

    class Integer{ int i; public: Integer(int ii) : i(ii) {} const Integer operator+(const Integer& ...

  5. Chapter14:重载运算符

    对于一个运算符函数来说,它或者是类的成员,或者至少含有一个类类型的参数. int operator+(int, int);//错误,不能为int重定义内置运算符 对于一个重载的运算符来说,其优先级和结 ...

  6. C使用FILE指针文件操作

    文件的基本概念 所谓“文件”是指一组相关数据的有序集合. 这个数据集有一个名称,叫做文件名.实际上在前面的各章中我们已经多次使用了文件,例如源程序文件.目标文件.可执行文件.库文件 (头文件)等.文件 ...

  7. with 语句

    with 语句用于设置代码在特定对象中的作用域. 它的语法: with (expression) statement例如: var sMessage = "hello"; with ...

  8. 有趣的库:pipe(类似linux | 管道)库

    pipe并不是Python内置的库,如果你安装了easy_install,直接可以安装它,否则你需要自己下载它:http://pypi.python.org/pypi/pipe 之所以要介绍这个库,是 ...

  9. Flex 对Java端返回Collection的处理方法

    将Flex与Spring集成后(BlazeDS 与Spring集成指南 ),第一个面临的问题就是:对于Java端返回的各种Java类型的对象,Flex中能否有相应的数据类型来映射. 处理,尤其是Lis ...

  10. sqlite使用小结

    官方网站 http://www.sqlite.org/index.html 图形前端 http://www.sqlabs.net/sqlitemanager.php 个人觉得firefox的sqlit ...