cocos2dx-3.10 45度地图 tiledmap+A*寻路

45度地图 寻路主要参考了某位博客文章,链接如下:

cocos2dx 45度Staggered格式A*寻路 曼哈顿算法(待优化)

另外也参考了某位作者的正方形A* 寻路,所以这套A* 算法是可以兼正方形寻路也可以45度菱形寻路的。

现贴下代码:

地图类:

#ifndef _MAP_LAYER_H_
#define _MAP_LAYER_H_
#include <cocos2d.h>
#include "Role.h"
#include "Astar.h"
#include <iostream>
#include "common/BaseInfo.h"
#include "common/Global.h"
#include "Role.h"

USING_NS_CC;

class Role;

class MapLayer : public Layer,public BaseInfo,public Global
{
public:
    MapLayer();
    ~MapLayer();
    int _screenWidth, _screenHeight;  // 屏幕宽度和高度
    virtual bool init();
    void update(float dt);
    void setViewpointCenter(Point pos);

    void initMapWithFile(const char * path);

    static cocos2d::Scene* createScene();
    CREATE_FUNC(MapLayer);

private:
    Role *CRole; //玩家角色

};

#endif
#include "MapLayer.h"

MapLayer::MapLayer()
{
}
MapLayer::~MapLayer()
{
}

Scene* MapLayer::createScene()
{
    // ‘scene‘ is an autorelease object
    auto scene = Scene::create();

    // ‘layer‘ is an autorelease object
    auto layer = MapLayer::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}
bool MapLayer::init()
{
    if (!Layer::init())
    {
        return false;
    }

    this->initMapWithFile("chi.tmx");//地图初始化

    astar.InitAstar(_grid, MapWidth, MapHeight);
    auto gameListener = EventListenerTouchOneByOne::create();
    // 响应触摸事件函数
    gameListener->onTouchBegan = [](Touch* touch, Event* event){return true; };
    gameListener->onTouchEnded = [=](Touch *touch, Event *event)
    {
        // OpenGL坐标
        Vec2 touchLocation = touch->getLocation();
        // 将触摸点坐标转换成相对的Node坐标
        Vec2 nodeLocation = this->convertToNodeSpace(touchLocation);

        // 用玩家位置作为起点,触摸点作为终点,转换为网格坐标,在地图上查找最佳到达路径
        Vec2 from = tileCoordForPosition(CRole->getPosition());
        Vec2 to = tileCoordForPosition(nodeLocation);
        // 如果终点是不可通过(即有障碍物)的位置,则直接return

        int tileGid = _collidable->getTileGIDAt(to);
        if (tileGid)
        {
            // 使用GID来查找指定tile的属性,返回一个Value
            Value properties = _tileMap->getPropertiesForGID(tileGid);
            // 返回的Value实际是一个ValueMap
            ValueMap map = properties.asValueMap();
            // 查找ValueMap,判断是否有”可碰撞的“物体,如果有,直接返回
            std::string value = map.at("collidable").asString();
            if (value.compare("true") == 0)
            {
                return;
            }
        }

        CRole->path.clear();
        int fromx = (int)from.x;
        int fromy = (int)from.y;
        int tox = (int)to.x;
        int toy = (int)to.y;
        APoint start(fromx, fromy);
        APoint end(tox, toy);
        //A*算法找寻路径
        auto t1 = ::clock();
        CRole->path = astar.GetPath(start, end, false);
        auto t2 = ::clock();
        CRole->PathCurrentStep = 1;
        CRole->PathSteps = CRole->path.size() - 1;
        CRole->bMoving = true;
        log("path size===>%d,  time=====>%d ms", CRole->path.size(),t2-t1);

        for (auto &p : CRole->path)
        {
            log("point===============>%d,%d",p->x,p->y);
        }
        if (CRole->path.size()>0)
        {
            CRole->RoleMove();
        }

    };
    // 添加场景优先事件监听器
    Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(gameListener, this);

    //设置起始和结束点
    this->scheduleUpdate();

    return true;

}
void MapLayer::initMapWithFile(const char * path)
{
    _tileMap = TMXTiledMap::create(path);
    //_tileMap = cocos2d::experimental::TMXTiledMap::create(path);
    _collidable = _tileMap->getLayer("collidable");
    _collidable->setVisible(true);
    auto bg= _tileMap->getLayer("back");
    bg->setVisible(true);
    _tileMap->setPosition(Vec2(0, 0));
    MapWidth = _tileMap->getMapSize().width;
    MapHeight = _tileMap->getMapSize().height;
    this->initGrid();
    this->addChild(_tileMap);
    CRole = Role::create();
    CRole->setPosition(positionForTileCoord(Point(8,286)));
    CRole->setSumLifeValue(200);
    CRole->setCurtLifeValue(CRole->getSumLifeValue());
    CRole->_tileMap = _tileMap;
    CRole->MapHeight = MapHeight;
    CRole->MapWidth = MapWidth;
    CRole->SetState(Role::ActionState::IDLE_STATE_UP);
    this->addChild(CRole,2);
}

void MapLayer::setViewpointCenter(Point pos)  //这个是移动地图,同时跟踪X,Y轴标准算法
{
    Size winSize = Director::getInstance()->getWinSize();
    //如果主角坐标小于屏幕的一半,则取屏幕中点坐标,否则取对象的坐标
    int x = MAX(pos.x, winSize.width / 2);
    int y = MAX(pos.y, winSize.height / 2);

    //如果X、Y的坐标大于右上角的极限值,则取极限值的坐标(极限值是指不让地图超出屏幕造成出现黑边的极限坐标 )
    x = MIN(x, (_tileMap->getMapSize().width *_tileMap->getTileSize().width) - winSize.width / 2);
    y = MIN(y, (_tileMap->getMapSize().height * _tileMap->getTileSize().height) - winSize.height / 2);

    //对象当前所在坐标
    Point actualPosition = Vec2(x, y);

    //计算屏幕中点和所要移动的目的点之间的距离
    Point centerOfView = Vec2(winSize.width / 2, winSize.height / 2);
    Point viewPoint = centerOfView - actualPosition;
    this->setPosition(viewPoint);
}

void MapLayer::update(float delta)
{
    this->setViewpointCenter(CRole->getPosition());
}

角色类,这里直接用了3d模型做主角:

#ifndef _ROLE_H_
#define _ROLE_H_
#include "cocos2d.h"
#include "Astar.h"
#include "common/BaseInfo.h"

USING_NS_CC;

//基础角色类,主角和NPC都需要继承它

class BaseInfo;

class Role :public Node,public BaseInfo
{
public:
    Role(void);
    ~Role(void);
    /* 角色状态设定,初始化角色状态等 */
    CC_SYNTHESIZE(std::string, name, name);                         //角色名称
    CC_SYNTHESIZE(float, curtLifevalue, CurtLifeValue);             //角色当前生命值
    CC_SYNTHESIZE(float, sumLifevalue, SumLifeValue);                   //角色总体生命值

public:
    enum class ActionState {
        ACTION_STATE_IDLE = 0,
        RUN_STATE_UP,
        RUN_STATE_DOWN,
        RUN_STATE_LEFT,
        RUN_STATE_RIGHT,
        RUN_STATE_LEFTUP,
        RUN_STATE_RIGHTUP,
        RUN_STATE_LEFTDOWN,
        RUN_STATE_RIGHTDOWN,
        IDLE_STATE_UP,
        IDLE_STATE_DOWN,
        IDLE_STATE_LEFT,
        IDLE_STATE_RIGHT,
        IDLE_STATE_LEFTUP,
        IDLE_STATE_RIGHTUP,
        IDLE_STATE_LEFTDOWN,
        IDLE_STATE_RIGHTDOWN,
    };

public:

    Action* m_down_idle;
    Action* m_right_idle;
    Action* m_up_idle;
    Action* m_left_idle;
    Action* m_leftdown_idle;
    Action* m_rightdown_idle;
    Action* m_leftup_idle;
    Action* m_rightup_idle;

    Action* m_down_walk;
    Action* m_right_walk;
    Action* m_up_walk;
    Action* m_left_walk;
    Action* m_leftdown_walk;
    Action* m_rightdown_walk;
    Action* m_leftup_walk;
    Action* m_rightup_walk;

    //角色初始化
    virtual bool init();
    //初始化创建角色动作
    void CreateActions();
    //角色移动
    //virtual void RoleMove();

    CREATE_FUNC(Role);

    void SetState(ActionState actionState);
    bool bMoving;
    unsigned int PathCurrentStep;
    unsigned int PathSteps;

    Vector<APoint *> path;
    ActionState currActionState;
    Sprite3D *_player;

    void RoleMove();

};
#endif
#include "Role.h"

Role::Role(void) :
m_down_idle(NULL),
m_up_idle(NULL),
m_left_idle(NULL),
m_right_idle(NULL),
m_leftdown_idle(NULL),
m_rightdown_idle(NULL),
m_leftup_idle(NULL),
m_rightup_idle(NULL),
m_down_walk(NULL),
m_up_walk(NULL),
m_left_walk(NULL),
m_right_walk(NULL),
m_leftdown_walk(NULL),
m_rightdown_walk(NULL),
m_leftup_walk(NULL),
m_rightup_walk(NULL),
currActionState(ActionState::ACTION_STATE_IDLE)
{
    //this->setRoleDirection(RolelTurnRight);//设定初始朝向
}
Role::~Role(void)
{

}

bool Role::init(){
    bool ret = false;
    do
    {
        //加载模型文件
        std::string fileName = "orc.c3b";  //"orc.c3b";
        _player = Sprite3D::create(fileName);
        _player->setScale(3.0f);
        _player->setPosition(Vec2(0, 0));
        _player->setGlobalZOrder(1);
        _player->setRotation3D(Vec3(0, 180, 0));
        addChild(_player);
        //加载武器
        auto sp = Sprite3D::create("axe.c3b");
        sp->setGlobalZOrder(1);
        //将武器放到玩家手上
        _player->getAttachNode("Bip001 R Hand")->addChild(sp);
        //获取骨骼动画信息
        auto animation = Animation3D::create(fileName);
        if (animation)
        {
            auto _idle = Animate3D::create(animation);
            _idle->retain();
            //让精灵循环播放动作
            Sequence*   pSequence = Sequence::create(_idle, NULL);
            _player->runAction(RepeatForever::create(pSequence));
        }

        this->addChild(_player);

        bMoving = false;
        CreateActions();
        PathCurrentStep = 0;
        PathSteps = 0;
        ret = true;
    } while (0);

    return ret;
}

void Role::CreateActions()
{
    //初始化用户的动作

}

void Role::SetState(ActionState actionState)
{
    this->stopAllActions();
    switch (actionState)
    {
    case ActionState::IDLE_STATE_UP:
        _player->setRotation3D(Vec3(0, 0, 0));
        break;
    case ActionState::IDLE_STATE_DOWN:
        _player->setRotation3D(Vec3(0, 180, 0));
        break;
    case ActionState::IDLE_STATE_LEFT:
        _player->setRotation3D(Vec3(0, 90, 0));
        break;
    case ActionState::IDLE_STATE_RIGHT:
        _player->setRotation3D(Vec3(0, -90, 0));
        break;
    case ActionState::IDLE_STATE_LEFTUP:
        _player->setRotation3D(Vec3(0, -135, 0));
        break;
    case ActionState::IDLE_STATE_RIGHTUP:
        _player->setRotation3D(Vec3(0, 45, 0));
        break;
    case ActionState::IDLE_STATE_LEFTDOWN:
        _player->setRotation3D(Vec3(0, -45, 0));
        break;
    case ActionState::IDLE_STATE_RIGHTDOWN:
        _player->setRotation3D(Vec3(0, 135, 0));
        break;
    case ActionState::RUN_STATE_UP:
        _player->setRotation3D(Vec3(0, 0, 0));
        break;
    case ActionState::RUN_STATE_DOWN:
        _player->setRotation3D(Vec3(0, 180, 0));
        break;
    case ActionState::RUN_STATE_LEFT:
        _player->setRotation3D(Vec3(0, 90, 0));
        break;
    case ActionState::RUN_STATE_RIGHT:
        _player->setRotation3D(Vec3(0, -90, 0));
        break;
    case ActionState::RUN_STATE_LEFTUP:
        _player->setRotation3D(Vec3(0, -135, 0));
        break;
    case ActionState::RUN_STATE_RIGHTUP:
        _player->setRotation3D(Vec3(0, -45, 0));
        break;
    case ActionState::RUN_STATE_LEFTDOWN:
        _player->setRotation3D(Vec3(0, 45, 0));
        break;
    case ActionState::RUN_STATE_RIGHTDOWN:
        _player->setRotation3D(Vec3(0, 135, 0));
        break;
    default:
        break;
    }
    currActionState = actionState;
}

void Role::RoleMove()
{
    Vector<FiniteTimeAction* > Actions;
    if (bMoving)
    {
        //角色当前所在格子坐标
        auto currpos = tileCoordForPosition(this->getPosition());
        if (currpos.x==this->path.at(PathSteps)->x && currpos.y == this->path.at(PathSteps)->y)
        {
            //已到达目的地
            this->SetState(ActionState::IDLE_STATE_UP);
        }
        else
        {
            for (int i = 0; i < PathSteps; i++)
            {
                auto netStep = Point(this->path.at(i + 1)->x, this->path.at(i + 1)->y);
                Point v = Point(this->path.at(i)->x, this->path.at(i)->y)-netStep;
                float len = v.getLength();// 计算每一段的距离
                float duration = len / 10 * 1.2; //计算每段行走的时间
                float rad = v.getAngle(Point(1, 1));
                float Degree = CC_RADIANS_TO_DEGREES(rad);
                log("the degree=========> %f",Degree);

                auto fnSetState = [](Role *pRole, ActionState state)
                {
                    pRole->SetState(state);
                };

                if (Degree >= 0 && Degree < 45)
                {
                //  Actions.pushBack(CallFunc::create(bind(fnSetState, this, ActionState::RUN_STATE_RIGHT)));
                    SetState(ActionState::RUN_STATE_LEFT);
                }
                if (Degree >= 45 && Degree < 90)
                {
                //  Actions.pushBack(CallFunc::create(bind(fnSetState, this, ActionState::RUN_STATE_RIGHTUP)));
                    SetState(ActionState::RUN_STATE_LEFTDOWN);
                }
                if (Degree >= 90 && Degree < 135)
                {
                //  Actions.pushBack(CallFunc::create(bind(fnSetState, this, ActionState::RUN_STATE_UP)));
                    SetState(ActionState::RUN_STATE_RIGHTDOWN);
                }
                if (Degree >= 135 && Degree < 180)
                {
                //  Actions.pushBack(CallFunc::create(bind(fnSetState, this, ActionState::RUN_STATE_LEFTUP)));
                    SetState(ActionState::RUN_STATE_RIGHT);
                }
                if (Degree >-135 && Degree <= -180)
                {
                //  Actions.pushBack(CallFunc::create(bind(fnSetState, this, ActionState::RUN_STATE_LEFT)));
                    SetState(ActionState::RUN_STATE_RIGHTUP);
                }

                FiniteTimeAction *pAct = MoveTo::create(duration, positionForTileCoord(netStep));
                Actions.pushBack(pAct);

            }

            auto pSeq = Sequence::create(Actions);
            pSeq->setTag(1);
            this->runAction(pSeq);

        }
        bMoving = false;
    }
    else {
        SetState(ActionState::IDLE_STATE_DOWN);
    }

}

A* 寻路类:

#pragma once
/*
//A*算法对象类
*/
#include <vector>
#include <list>
#include <unordered_map>
#include "cocos2d.h"
USING_NS_CC;
using namespace std;

//横向移动一格的路径评分
static const int COST_HORIZONTAL = 20;
//竖向移动一格的路径评分
static const int COST_VERTICAL = 5;
//斜向移动一格的路径评分
static const int COST_DIAGONAL = 12;

const int kCost1 = 10; //直移一格消耗
const int kCost2 = 14; //斜移一格消耗  

struct APoint :public Ref
{
    int x, y; //点坐标,这里为了方便按照C++的数组来计算,x代表横排,y代表竖列
    int F, G, H; //F=G+H
    APoint *parent; //parent的坐标,这里没有用指针,从而简化代码
    APoint(int _x, int _y) :x(_x), y(_y), F(0), G(0), H(0), parent(NULL)  //变量初始化
    {
    }
};

class Astar
{
public:
    void InitAstar(std::vector<bool> &_maze,int mapwidth, int mapheight);
    Vector<APoint *> GetPath(APoint &startPoint, APoint &endPoint, bool isIgnoreCorner);

private:
    APoint *findPath(APoint &startPoint, APoint &endPoint, bool isIgnoreCorner);
    Vector<APoint *> getSurroundPoints(const APoint *point, bool isIgnoreCorner) const;
    bool isCanreach(const APoint *point, const APoint *target, bool isIgnoreCorner) const; //判断某点是否可以用于下一步判断
    APoint *isInList(const Vector<APoint *> &list, const APoint *point) const; //判断开启/关闭列表中是否包含某点
    APoint *getLeastFpoint(); //从开启列表中返回F值最小的节点
    //计算FGH值
    int calcG(APoint *temp_start, APoint *point);
    int calcH(APoint *point, APoint *end);
    int calcF(APoint *point);
private:
    std::vector<bool> maze;
    Vector<APoint *> openList;  //开启列表
    Vector<APoint *> closeList; //关闭列表  

    int width;
    int height;
};
#include <math.h>
#include "Astar.h"  

void Astar::InitAstar(std::vector<bool> &_maze, int mapwidth, int mapheight)
{
    maze = _maze;
    width = mapwidth;
    height = mapheight;
}

int Astar::calcG(APoint *temp_start, APoint *point)
{
    /* 原正方形  */
    //int extraG = (abs(point->x - temp_start->x) + abs(point->y - temp_start->y)) == 1 ? kCost1 : kCost2;
    //int parentG = point->parent == NULL ? 0 : point->parent->G; //如果是初始节点,则其父节点是空
    //return parentG + extraG;

    //45度菱形

    int g = 0;
    if (temp_start->y == point->y) // 横向  左右
    {
        g = temp_start->G + COST_HORIZONTAL;
    }
    else if (temp_start->y + 2 == point->y || temp_start->y - 2 == point->y) // 竖向  上下
    {
        g = temp_start->G + COST_VERTICAL * 2;
    }
    else // 斜向  左上 左下 右上 右下
    {
        g = temp_start->G + COST_DIAGONAL;
    }
    return g;
}

int Astar::calcH(APoint *point, APoint *end)
{
    //原正方形 用简单的欧几里得距离计算H
//  return sqrt((double)(end->x - point->x)*(double)(end->x - point->x) + (double)(end->y - point->y)*(double)(end->y - point->y))*kCost1;

    //45度菱形  曼哈顿算法
    int to0 = point->x * COST_HORIZONTAL + ((int)point->y & 1) * COST_HORIZONTAL / 2;
    int endTo0 = end->x * COST_HORIZONTAL + ((int)end->y & 1) * COST_HORIZONTAL / 2;
    return abs((float)endTo0 - (float)to0) + abs((float)end->y - (float)point->y) * COST_VERTICAL;
}

int Astar::calcF(APoint *point)
{
    return point->G + point->H;
}

APoint *Astar::getLeastFpoint()
{

    if (!openList.empty())
    {
        auto resPoint = openList.front();
        for (auto point : openList)
        if (point->F<resPoint->F)
            resPoint = point;
        return resPoint;
    }
    return NULL;
}

APoint *Astar::findPath(APoint &startPoint, APoint &endPoint, bool isIgnoreCorner)
{
    openList.clear();
    closeList.clear();
    //CCLOG("%d,%d", startPoint.x,startPoint.y);
    //CCLOG("%d,%d", endPoint.x,endPoint.y);
    openList.pushBack(new APoint(startPoint.x, startPoint.y)); //置入起点,拷贝开辟一个节点,内外隔离
    while (!openList.empty())
    {
        auto curPoint = getLeastFpoint(); //找到F值最小的点
        openList.eraseObject(curPoint); //从开启列表中删除
        closeList.pushBack(curPoint); //放到关闭列表
        //1,找到当前周围八个格中可以通过的格子
        auto surroundPoints = getSurroundPoints(curPoint, isIgnoreCorner);
        for (auto &target : surroundPoints)
        {
            //2,对某一个格子,如果它不在开启列表中,加入到开启列表,设置当前格为其父节点,计算F G H
            if (!isInList(openList, target))
            {
                target->parent = curPoint;

                target->G = calcG(curPoint, target);
                target->H = calcH(target, &endPoint);
                target->F = calcF(target);

                openList.pushBack(target);
            }
            //3,对某一个格子,它在开启列表中,计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
            else
            {
                int tempG = calcG(curPoint, target);
                if (tempG<target->G)
                {
                    target->parent = curPoint;

                    target->G = tempG;
                    target->F = calcF(target);
                    //CCLOG("%d,%d", target.x, target.y);
                }
            }
            APoint *resPoint = isInList(openList, &endPoint);
            if (resPoint)
                return resPoint; //返回列表里的节点指针,不要用原来传入的endpoint指针,因为发生了深拷贝
        }
    }

    return NULL;
}

Vector<APoint *> Astar::GetPath(APoint &startPoint, APoint &endPoint, bool isIgnoreCorner)
{
    log("from point===============>%d,%d", startPoint.x, startPoint.y);
    log("to point===============>%d,%d", endPoint.x, endPoint.y);
    APoint *result = findPath(startPoint, endPoint, isIgnoreCorner);
    Vector<APoint *> path;
    //返回路径,如果没找到路径,返回空链表
    int s = 1;
    while (result->parent)
    {
     // result->y = height - result->y - 1;
        path.insert(0,result);
        result = result->parent;
        s++;
    }
    log("s===>%d",s);
    return path;
}

APoint *Astar::isInList(const Vector<APoint *> &list, const APoint *point) const
{
    //判断某个节点是否在列表中,这里不能比较指针,因为每次加入列表是新开辟的节点,只能比较坐标
    for (auto p : list)
    if (p->x == point->x&&p->y == point->y)
        return p;
    return NULL;
}

bool Astar::isCanreach(const APoint *point, const APoint *target, bool isIgnoreCorner) const
{
    if (target->x<0 || target->x>width-1
        || target->y<0 || target->y>height-1
        || maze[width*target->y + target->x] == false
        || (target->x == point->x&&target->y == point->y)
        || isInList(closeList, target)) //如果点与当前节点重合、超出地图、是障碍物、或者在关闭列表中,返回false
        return false;
    else
    {
        if (abs(point->x - target->x) + abs(point->y - target->y) == 1) //非斜角可以
            return true;
        else
        {
            //斜对角要判断是否绊住
            if (maze[width*target->y + point->x] == true && maze[width*point->y + target->x] == true)
                return true;
            else
                return isIgnoreCorner;
        }
    }
}

Vector<APoint *> Astar::getSurroundPoints(const APoint *point, bool isIgnoreCorner) const
{
    Vector<APoint *> surroundPoints;

    //原正方形
    /*for (int x = point->x - 1; x <= point->x + 1; x++)
    for (int y = point->y - 1; y <= point->y + 1; y++)
    if (isCanreach(point, new APoint(x, y), isIgnoreCorner))
        surroundPoints.pushBack(new APoint(x, y));*/

    //45度菱形  菱形组合的地图八方向与正常不同

    // 左
    auto p = new APoint(point->x - 1, point->y);
    if (isCanreach(point, p, isIgnoreCorner)) // 可走并且不在关闭列表
    {
        surroundPoints.pushBack(p);
    }

    // 右
    p = new APoint(point->x + 1, point->y);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    // 上
    p = new APoint(point->x, point->y-2);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }
    // 下
    p = new APoint(point->x , point->y+2);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    // 左上
    p = new APoint(point->x - 1+ ((int)point->y & 1), point->y-1);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    // 左下
    p = new APoint(point->x - 1 + ((int)point->y & 1), point->y + 1);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    //右上
    p = new APoint(point->x  + ((int)point->y & 1), point->y - 1);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    //右下
    p = new APoint(point->x + ((int)point->y & 1), point->y +1);
    if (isCanreach(point, p, isIgnoreCorner))
    {
        surroundPoints.pushBack(p);
    }

    return surroundPoints;
}

主要代码已经贴上了:下面是本demo图片,随便做的,看看就行

本文demo代码请到如下地址下载,图片资源来自网络,切勿商用。

下载资源

时间: 2024-10-10 16:22:53

cocos2dx-3.10 45度地图 tiledmap+A*寻路的相关文章

cocos2dx[3.4](25)——瓦片地图TiledMap

[唠叨] 还记得我们小时候玩的小霸王里面的游戏吗?大部分都是基于Tile地图的游戏,如坦克大战.冒险岛.魂斗罗.吞食天地等.而在手游中,基于瓦片地图的游戏也很常见.如:<保卫萝卜>. 瓦片地图有专门的地图编辑器:Tiled Map Editor . 先给大家看个酷炫的图吧. 此图来自:http://blog.csdn.net/aa4790139/article/details/8135831 [参考] http://cn.cocos2d-x.org/tutorial/lists?id=70 

libgdx学习记录11——平铺地图TiledMap

地图对于游戏场景十分重要,很多游戏都需要对地图进行编辑,可使用TileMap进行编辑并生成对应的tmx格式地图文件. 编辑好后,可通过TmxMapLoader来读取地图文件.可通过一个正交相机OthographicCamera和正交地图渲染器OrthogonalTiledMapRenderer来进行显示. 实例如下: 1 package com.fxb.newtest; 2 3 import com.badlogic.gdx.ApplicationAdapter; 4 import com.ba

mir9-lua——《热血沙城》45度ARPG手游-Lua移植版

mir9--<热血沙城>,是9秒论坛开源的一个使用Cocos2d-x-2.2.1引擎开发的45度ARPG手游Demo,源代码为c++.mir9-lua是mir9的Lua移植版,使用Quick-Cocos2d-x-2.2.5引擎开发.由于移植得比较匆忙,代码写得可能比较混乱,请见谅. 已知Bug: 1.Label字体在Windows上面显示模糊 2.小地图在已是最左或最下的情况下,仍可以向上或或向滑动一段距离,并且不弹回原样 3.切换地图后小地图还是打开状态,并且显示的是之前的小地图 4.人物移

HTML5 Canvas 描画旋转45度佛教万字

效果如下: 代码如下: <!DOCTYPE html> <html lang="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <head> <title>旋转45度佛教万字</title> </head> <body onload="draw

汽车倒车入库技巧图解--倒车方式一字倒车-----非字倒车---斜45度倒车

汽车倒车入库技巧图解 浙江奉化一小区车库里致夫妻双双遇难的倒车悲剧,女司机倒车撞死丈夫自己也被夹死.让人心惊,也给不少倒库不熟练的新手敲响了警钟.如果你的倒车技术不扎实,不妨学习一下这张倒车入库技巧详解图.不紧张.多练习,一次性入库,你也可以!安全驾驶,出入平安! 汽车倒车入库技巧图解 “一”字形停车位倒车技巧图解: “非”字形停车位倒车技巧图解 斜45度停车位倒车技巧图解

java将矩阵旋转45度输出

例如: A B C D E F G H I J K L M N O P Q R S T U V W X Y E D J C I O B H N T A G M S Y F L R X K Q W P V U 思路如上图: 在菱形之外的都是空格,菱形之内(可以使用函数判断)有两种点,一种是有字符,一种是空格 可以发现,有字符的位置(col-row)%2 == 0:接下来寻找45度菱形和矩形的对应关系,row'=(col-row)/2 ,col'=col-row' 完整代码如下: public cl

cocos2d-x 3.10版本 使用BabeLua调试

cocos2d-x 3.10在"simulator\win32\"有一份src和res, 为避免混乱最好在删除副本文件夹,做法参考 cocos2d-x 3.10版本 Lua 删除工作目录下的src和res文件夹 为了使用BabeLua调试, 我们需要将项目的工作目录路径传给生成的exe, 做法如下: Lua exe path : exe所在路径 Working path : Lua工程工作目录 Command line : 传给exe的命令, 这里传给exe的是当前的工作目录, 也就是

Android-百度地图的调用 (基础版本)

之前写了一篇Android-百度地图的调用(检索功能)是因为我所在公司的项目有用到东西,作了一些简单的分享. 这篇文章也是简单的介绍一下百度地图的基础地图使用 现在百度开发者平台提供的Android SDK 版本是 - Android SDK V 3.4.0. 1,什么是百度地图Android SDK ?(简单看看从官网的截图) 2.  如何获取定制的百度地图SDK. 开发者可在百度地图Android SDK的下载页面下载到最新版的地图SDK, 下载地址为:http://developer.ba

己知点坐标和半径R,求每隔45度半径与同心圆交汇的坐标

需求如下图 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>javascript己知点坐标