总结、代码、效果看Cocos2d-x 3.3TileMap的A*算法实现详解
总结:
- Cocos里面的Vector比C++的vector容纳的类型少很多,因此用标准库的vector
- 地图是320*680,瓦片是32*32像素
- 首先添加点击事件,获取终点的瓦片坐标,并记录下来
- 设定起始坐标,并将起始坐标作为【当前点】
- 每次对【当前点】的四周探索,放入优先队列openList
- 将优先队列的第一个元素,即F值最小的那个点,作为新的【当前点】,并放入closeList
- 继续调用探索方法,直到终点坐标也被放入openList
代码:
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include “cocos2d.h”
#include
#include
USING_NS_CC;
//定义【当前点】类,包含权值F和坐标点
classpointValue
{
public:
pointValue(Point tem, Point dst , inttotal)
{
tempPoint = tem;
FValue = (abs((int)dst.x-(int)tem.x +(int)dst.y-(int)tem.y) + total) ;
}
//当前点坐标,和F值
Point tempPoint;
intFValue;
};
//设置优先队列比较函数,F值最小的【当前点】在优先队列的Top
structCompare
{
booloperator ()(pointValue a,pointValue b)
{
returna.FValue > b.FValue;
}
};
classHelloWorld : publiccocos2d:ayer
{
public:
staticcocos2d::Scene* createScene();
virtualboolinit();
CREATE_FUNC(HelloWorld);
voidmenuCloseCallback(cocos2d::Ref* pSender);
//二维数组,防止点重复探索,初始化为0,探索过的设为1
intarr[15][10];
//TileMap的层
TMXLayer *layer;
//待检测坐标列表,优先队列作为OpenList
std::priority_queue p_quene;
//关闭列表
std::vector closeList;
std::vector::iterator closeListStart;
//起点瓦片坐标
Point beginPoint;
//终点瓦片坐标
Point destination;
//估算一个从起始点到终点的格子数目,每移动一次,则减30
inttotal;
//将最终的路径所有点,存放在closeList中
boolaStart();
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include “HelloWorldScene.h”
USING_NS_CC;
Scene* HelloWorld::createScene()
{
auto scene = Scene::create();
auto layer = HelloWorld::create();
scene->addChild(layer);
returnscene;
}
boolHelloWorld::init()
{
if( !Layer::init() )
{
returnfalse;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
//载入TileMap地图
auto map = TMXTiledMap::create(“map.tmx”);
addChild(map);
//获取TileMap的层
layer = map->getLayer(“layer1″);
//确定起点瓦片坐标和初始化二维数组
beginPoint = Point(0,0);
arr[0][0] = 1;
//点击事件监听,记录终点瓦片坐标
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = [this](Touch *t, Event *e)
{
//设置终点瓦片坐标
intdx = (int)(t->getLocation().x)/32;
intdy = 14 – (int)(t->getLocation().y)/32;
this->destination = Point(dx,dy);
CCLOG(“%d,%d”,dx,dy);
//自己设置起点到终点的最短格子数估值,即G值
total = 1000;
//寻找最短路径,坐标存放在closeList里面
aStart();
returntrue;
};
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this);
returntrue;
}
boolHelloWorld::aStart()
{
//每调用一次aStart相当于移动一步,每移动一步total减30,作为G值
total = total – 30;
if((int)beginPoint.x == (int)destination.x && (int)beginPoint.y == (int)destination.y)
{
returntrue;
}
//探索这个点的4周(上,右,下,左),若存在,则放进优先队列openList中
//判断上方
if((int)beginPoint.x >= 0 && ((int)beginPoint.y-1) >= 0 && (int)beginPoint.x
= 0 && (int)beginPoint.y >= 0 && ((int)beginPoint.x-1) = 0 && ((int)beginPoint.y+1) >= 0 && (int)beginPoint.x = 0 && (int)beginPoint.y >= 0 && ((int)beginPoint.x+1) setPosition(Point(beginPoint.x*32+10,480-beginPoint.y*32-10));addChild(star);
//继续递归
aStart();
}
voidHelloWorld::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
效果: