Cocos2d-x 3.3TileMap的A*算法实现详解

总结、代码、效果看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 <queue>

#include <vector>

USING_NS_CC;

//定义【当前点】类,包含权值F和坐标点

扫描二维码关注公众号,回复: 11742513 查看本文章

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<pointValue, std::vector<pointValue>,Compare> p_quene;

    //关闭列表

    std::vector<pointValue> closeList;

    std::vector<pointValue>::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 <= 9 && ((int)beginPoint.y-1) <= 14 ){

        Sprite *testUp = layer->getTileAt(Vec2((int)beginPoint.x,(int)beginPoint.y-1));

        if(testUp != NULL && (arr[(int)beginPoint.x][(int)beginPoint.y-1] != 1) )

        {

            CCLOG(“up”);

            //初始化探索的点,将它放进优先队列openList中,并设置二维数组中的值为1,防止重复探索

            auto temp = newpointValue(Point(beginPoint.x,beginPoint.y-1),destination,total);

            p_quene.push(*temp);

            arr[(int)beginPoint.x][(int)beginPoint.y-1] = 1;

        }

        }

        //判断左方

        if(((int)beginPoint.x-1) >= 0 && (int)beginPoint.y >= 0 && ((int)beginPoint.x-1) <= 9 && (int)beginPoint.y <= 14) {

        Sprite *testLeft = layer->getTileAt(Vec2((int)beginPoint.x-1,(int)beginPoint.y));

        if(testLeft != NULL && (arr[(int)beginPoint.x-1][(int)beginPoint.y] != 1) )

        {

            CCLOG(“left”);

            //初始化探索的点,将它放进优先队列openList中,并设置二维数组中的值为1,防止重复探索

            auto temp2 = newpointValue(Point(beginPoint.x-1,beginPoint.y),destination,total);

            p_quene.push(*temp2);

            arr[(int)beginPoint.x-1][(int)beginPoint.y] = 1;

        }

        }

        //判断下方

        if((int)beginPoint.x >= 0 && ((int)beginPoint.y+1) >= 0 && (int)beginPoint.x <= 9 && ((int)beginPoint.y+1) <= 14) {

        Sprite *testDown = layer->getTileAt(Vec2((int)beginPoint.x,(int)beginPoint.y+1));

        if(testDown != NULL && (arr[(int)beginPoint.x][(int)beginPoint.y+1] != 1) )

        {

            CCLOG(“down”);

            //初始化探索的点,将它放进优先队列openList中,并设置二维数组中的值为1,防止重复探索

            auto temp3 = newpointValue(Point(beginPoint.x,beginPoint.y+1),destination,total);

            p_quene.push(*temp3);

            arr[(int)beginPoint.x][(int)beginPoint.y+1] = 1;

        }

        }

        //判断右方

        if(((int)beginPoint.x+1) >= 0 && (int)beginPoint.y >= 0 && ((int)beginPoint.x+1) <= 9 && (int)beginPoint.y <= 14){

        Sprite *testRight = layer->getTileAt(Vec2((int)beginPoint.x+1,(int)beginPoint.y));

        if(testRight != NULL && (arr[(int)beginPoint.x+1][(int)beginPoint.y] != 1))

        {

            CCLOG(“right”);

            //初始化探索的点,将它放进优先队列openList中,并设置二维数组中的值为1,防止重复探索

            auto temp4 = newpointValue(Point(beginPoint.x+1,beginPoint.y),destination,total);

            p_quene.push(*temp4);

            arr[(int)beginPoint.x+1][(int)beginPoint.y] = 1;

        }

        }

        //重置当前位置

        beginPoint.x = p_quene.top().tempPoint.x;

        beginPoint.y = p_quene.top().tempPoint.y;

        CCLOG(“%d,%d”,(int)beginPoint.x,(int)beginPoint.y);

        //把F值最小的点,放进closeList中,并从优先队列中pop掉

        closeList.push_back(p_quene.top());

        p_quene.pop();

         //在路径中添加精灵

        auto star = Sprite::create(“star.png”);

        star->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

效果:

猜你喜欢

转载自blog.csdn.net/qq_21743659/article/details/108637317