# cocos2dx3.2 A*寻路算法
来源:互联网 发布:淘宝商品批量上传 编辑:程序博客网 时间:2024/06/14 06:04
cocos2dx3.2 A*寻路算法
在此项工程中画出搜索路径,即将搜寻到的节点全部表示出来,暂时还没有列出最优路径,只是对A*算法的一个理解。
先看helloworld.h文件
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"USING_NS_CC;/* A*简单寻路,先定义一下节点类,属性有节点的坐标、G值,F值*/class NodePoint {public: Vec2 curPosition; // 当前的坐标 int GValue; int FValue;public: NodePoint(Vec2 i_curPosition, Vec2 des_position, int i_Gvalue) { curPosition = i_curPosition; //函数F = G + H; H用曼哈顿算法(算出从该点到目标节点横纵的节点和) int H = abs(des_position.x - i_curPosition.x) + abs(des_position.y - i_curPosition.y); FValue = i_Gvalue + H; }};/* 设置优先队列比较函数 最小的pop出来*/struct Cmp { bool operator ()(NodePoint p1, NodePoint p2) { return p1.FValue > p2.FValue; };};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);public: int GValue = 0; Vec2 startPosition; // 起始的坐标 Vec2 endPosition; // 目的的坐标 Vec2 curPosition; Vec2 tile_startPosition; //,用瓦片坐标来表示 Vec2 tile_endPosition; //,用瓦片坐标来表示 int markArray[20][30]; // 用来表示是否查询过,查询过的写1,未查询过的初始化为0 Sprite* sprite; int touches = 0; cocos2d::TMXLayer* tmxlayer; cocos2d::TMXTiledMap* _tilemap; //定义openlist closelist openlist是优先级队列 std::priority_queue<NodePoint, std::vector<NodePoint>, Cmp> openList; std::vector<NodePoint> closeList; std::vector<NodePoint>::iterator closeListIter;public: //将x,y转化为tile坐标 将点坐标转化为块坐标 Vec2 tileCoordForPosition(Vec2 position); bool findPath(float dt); virtual bool onTouchBegan(Touch *touch, Event *unused_event); void checkPointAndaddOpen(Vec2 point); //判断点,加入openlist};#endif // __HELLOWORLD_SCENE_H__
再头文件中定义了节点类,优先级队列,以及helloworld类的一些函数,注释在代码中已经标出
接下来实现cpp
#include "HelloWorldScene.h"USING_NS_CC;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 instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); _tilemap = TMXTiledMap::create("TileMap.tmx"); this->addChild(_tilemap); tmxlayer = _tilemap->getLayer("Background"); tmxlayer->setAnchorPoint(Point(0.5f, 0.5f)); tmxlayer->setPosition(visibleSize.width / 2, visibleSize.height / 2); startPosition = Vec2(100,100); tile_startPosition = tileCoordForPosition(Vec2(100, 100)); markArray[(int)tile_startPosition.y][(int)tile_startPosition.x] = 1; sprite = Sprite::create("food1.png"); sprite->setPosition((int)tile_startPosition.x*32+16, (int)(20-tile_startPosition.y)*32 - 16); this->addChild(sprite); for (int i = 0; i < 20; i++) { for (int j = 0; j < 30; j++) { markArray[i][j] = 0; } } auto listener = EventListenerTouchOneByOne::create(); listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); return true;}bool HelloWorld::onTouchBegan(Touch* touch, Event* event) { if (touches == 1) {// tmxlayer->removeAllChildren(); Director::getInstance()->replaceScene(HelloWorld::createScene()); } touches = 1; // 点击确定终点 tile_endPosition = this->tileCoordForPosition(touch->getLocation()); curPosition = tile_startPosition; int gid = tmxlayer->getTileGIDAt(Vec2((int)tile_endPosition.x, (int)tile_endPosition.y)); int mapvalue; if (_tilemap->getPropertiesForGID(gid).isNull()) { mapvalue = 0; } else { mapvalue = _tilemap->getPropertiesForGID(gid).asValueMap().at("canTouch").asInt(); } if (mapvalue == 1) { MessageBox("not touch!", "error"); return true; } //每次启动一次寻找过程时设定一下GValue的值 GValue = 0; //closeList.clear(); //开始寻找最佳路径 findPath(0.2); return true;}/* 此函数为A*算法*/bool HelloWorld::findPath(float dt) { //判断结束条件 if ((int)curPosition.x == (int)tile_endPosition.x && (int)curPosition.y == (int)tile_endPosition.y) { return true; //此时找到终点 } //判断4个方向的节点是否在openlist列表中,若不在,则放入openlist; //周围4个节点的情况下,不用去考虑新的G值小于原来的G值,而去改变父节点 //log("AAAAAAAAAAAAAAAAAAAA%d,%d", curPosition.x, curPosition.y); //先判断上方 log("****************up***************"); checkPointAndaddOpen(Vec2(curPosition.x, curPosition.y - 1)); //判断左方 log("****************left***************"); checkPointAndaddOpen(Vec2(curPosition.x - 1, curPosition.y)); //判断下方 log("****************down***************"); checkPointAndaddOpen(Vec2(curPosition.x, curPosition.y + 1)); //判断右方 log("****************right***************"); checkPointAndaddOpen(Vec2(curPosition.x + 1, curPosition.y)); //重置当前的位置 if (openList.empty()) { MessageBox("not a right path!", "error"); return true; } curPosition = openList.top().curPosition; log("curPositionX=%d,curPositionY=%d", (int)curPosition.x, (int)curPosition.y); //将F最小的节点放入closelist closeList.push_back(openList.top()); //移除该节点从openlist openList.pop(); //在路径之中添加精灵 sprite = Sprite::create("food.png"); //sprite->setPosition((int)tile_startPosition.x * 32 + 16, (int)(20 - tile_startPosition.y) * 32 - 16); this->addChild(sprite); sprite->setPosition((int)curPosition.x *32 + 16, (int)(20-curPosition.y)* 32 - 16); //递归 findPath(dt);}void HelloWorld::checkPointAndaddOpen(Vec2 point) { GValue = sqrt(((int)point.x - (int)curPosition.x)*((int)point.x - (int)curPosition.x) + ((int)point.y - (int)curPosition.y)*((int)point.y - (int)curPosition.y)); if ((int)point.x >= 0 && (int)point.y >= 0 && (int)point.x <= 29 && (int)point.y <= 19) { //判断是否越界 //接下来判断上方点是否在closeList 或者为木桩等 int gid = tmxlayer->getTileGIDAt(Vec2((int)point.x, (int)point.y)); int mapvalue; if (_tilemap->getPropertiesForGID(gid).isNull()) { mapvalue = 0; } else { mapvalue = _tilemap->getPropertiesForGID(gid).asValueMap().at("canTouch").asInt(); } //log("****************mapvalue*******************%d",mapvalue); //log("%d,%d, value = %d", (int)point.y, (int)point.x, markArray[(int)point.y][(int)point.x]); if (mapvalue == 0 && markArray[(int)point.y][(int)point.x] != 1) { //将该点创建为节点,并且加入优先队列 auto tmpPoint = new NodePoint(point, tile_endPosition, GValue); openList.push(*tmpPoint); markArray[(int)point.y][(int)point.x] = 1; } }}Vec2 HelloWorld::tileCoordForPosition(Vec2 position) { int x = position.x / _tilemap->getTileSize().width; //点坐标除瓦片的宽度 int y = (_tilemap->getMapSize().height * _tilemap->getTileSize().height - position.y) / _tilemap->getTileSize().height; return Vec2(x, y);}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}
运行结果如下
源码下载链接
0 0
- # cocos2dx3.2 A*寻路算法
- 如何基于cocos2dx3.x实现A星寻路算法
- cocos2dx3.2学习之路之前言
- cocos2dx3.2学习之路之基本概念
- cocos2dx3.2学习之路之动作
- Cocos2dx3.2从零开始【二】继续Cocos2dx3.2
- A*寻路算法
- A* 寻路算法
- A* 寻路算法
- A*寻路算法
- A*寻路算法
- A*寻路算法
- A*寻路算法
- A* 寻路算法
- A*寻路算法
- A* 寻路算法
- A* 寻路算法
- A* 寻路算法
- Android帮助文档本地打开慢的解决方案
- php之session代码
- bash no such file or directory in ubuntu 1404
- python request快速上手
- 二分法从数组中查找指定元素
- # cocos2dx3.2 A*寻路算法
- C++基础知识总结与回顾--5.5共享数据的保护
- gcc linux math.h sqrt 问题
- 继承与派生:虚基类及其派生类的构造函数
- mysql 5.6存储引擎比较
- 信息增益,信息增益率,Gini
- 十六进制转十进制
- 【LeetCode】 Populating Next Right Pointers in Each Node 完全二叉树
- Search Insert Position