Tiled瓦片地图的使用

Tiled软件使用的注意事项:
1️⃣文件的导入。图层文件的导入不能有中文名字,最好是先把需要的资源文件导入到工程的Resource文件夹中,让后到这个文件夹中导入Tiled软件,进行瓦片地图的绘制。
2️⃣文件的导出。在保存的时候就可以直接保存到工程的Resource文件夹中,随后在工程中添加,即导出成功。导出后可以查看.tmx文件,可以尝试着读懂导出的.tmx文件。
以上步骤完成后就可以在程序中使用瓦片地图了。
// 获得地图层,将其层级设为-1
TMXTiledMap * m_tiled = TMXTiledMap::create(“Tiled1.tmx");
addChild(m_tiled,-1);
//获得图层
TMXLayer * floor = tiled->getLayer("floor");
接着我们要添加英雄对象了,首先要先设置一个对象层,接着为了设置英雄的精灵图片,设置一个矩形区域(“图层”)
TMXObjectGroup * objects = m_tiled-> getObjectGroup ( "object" );
  ValueMap m_player = objects-> getObject ( “player”);
然后设置一个精灵,用这个对象的坐标来设置精灵的位置
    int x = m_player[ "x" ]. asInt ();
   
int y = m_player[ "y" ]. asInt ();
   
auto hero = Sprite :: create ( "Player.png" );
    hero->setPosition(x, y);
这时候,精灵已经可以在地图上显示出来了,值得注意的是对象曾与对象之间是Map的键值对的存储形式
这时候需要考虑通过点击来控制英雄的移动了。首先要设置触摸监听,代码略去,在重写的触摸事件中首先要知道点击点的位置是世界坐标系,相对于屏幕的左下角,需要将其转换为节点坐标系的点(相对于layer,因为在layer中的精灵坐标是相对于layer的坐标),通过点击屏幕让英雄瞬移到所点击屏幕的坐标显然是不可行的,我们点击一下让英雄移动一个瓦块的距离,通过点击的位置与英雄的位置差来判断行走的方向。
bool TiledTest::onTouchBegan(Touch *touch, Event *unused_event){
   
auto touchPos = touch->getLocation();
   
auto heroPos = hero->getPosition();
   
auto direction = touchPos - heroPos;
   
if (std::abs(direction.x)>std::abs(direction.y)) {
       
if (direction.x<0) {//left
            heroPos.
x -= m_tiled->getTileSize().width;
        }
else{//right
            heroPos.x += m_tiled->getTileSize().width;
        }// 出于方便的考虑将m_tiled设为了成员变量
    }else{
        if (directio     n.y<0) {
            heroPos.y -= m_tiled->getTileSize().height;
        }
       
else{
            heroPos.
y += m_tiled->getTileSize().height;
        }
    }
    hero->setPosition(heroPos);// 出于方便的考虑将hero设为了成员变量
    return true;
由于地图的比较大,需要设置屏幕的适配,类似于前面说到的摄像机类,即让英雄能够走完整个地图,我们写一个名字为setPlayerPosition(Vec2 pos)的函数来完成这一功能。
屏幕中心与地图位置的差值最小是屏幕大小的一半,最大是地图的大小减去屏幕大小的一半,我们选择设置一个在一个void setViewPosition(Vec2 pos)函数中实现这个功能.
void TiledTest::setLayerPosition(Vec2 pos){
   
auto winsize = Director::getInstance()->getVisibleSize();
   
int x,y;//差值(相对距离)
   
if (pos.x > winsize.width/2) {
        x = pos.
x;
    }
else{ x = winsize.width/2; }
   
if (pos.y > winsize.height/2) {
        y = pos.
y;
    }
else{ y = winsize.height/2; }
   
   
auto width = m_tiled->getTileSize().width * m_tiled->getMapSize().width-winsize.width/2;
   
auto height = m_tiled->getMapSize().height * m_tiled->getTileSize().height-winsize.height/2;
   
if (x>width) {
        x = width;
    }
   
if (y>height) {
        y = height;
    }
   
auto layerPos = Vec2(winsize.width/2, winsize.height/2)- Vec2(x, y);
    this->setPosition(layerPos);}
此时我们应该考虑限制英雄的移动了,对墙体等应设置属性让其无法通过,而对“蔬菜”应该让其吃掉。这时候需要使用Tiled软件添加一个图层,给起一个标记,添加属性与值,在程序中可以得到他,以便做碰撞检测.这个图层即为标记层,专门处理墙的问题。其中首先需要经过一个节点坐标到瓦片坐标的转换,瓦片地图以左上角为原点,每一个瓦片为单位。
Vec2 HelloWorld::getTiledPos(Vec2 pos){
   
int x = pos.x/m_tiled->getTileSize().width;
   
int y = (m_tiled->getMapSize().height*m_tiled->getTileSize().height - pos.y)/m_tiled->getTileSize().height;
    return Vec2(x, y);}
然后就需要根据属性值来得到墙,做碰撞检测.首先每一个瓦片都有一个唯一的ID值。通过获得ID来判断设置的标记wall是否为true,若不是则不是墙。
void TiledTest::setPlayerPostion(Vec2 pos){
   
auto tiledCoord = this->getTiledPos(pos);
   
auto tiledGID = meta->getTileGIDAt(tiledCoord);
   
if (tiledGID) {
       
ValueMap properties = m_tiled->getPropertiesForGID(tiledGID).asValueMap();
       
if (!properties.empty()) {
           
auto wall = properties["wall"].asString();
           
if (wall=="true") {
               
log("zhuangqiang");
               
return;
            }
        }
    }
    hero->setPosition(pos);// 若没有撞墙则正常移动
是不是该考虑给水果,蔬菜设置可以被英雄吃掉?这时候需要额外建立一个图层 并添上要被吃掉的水果并添加属性 ,因为需要吃掉水果,水果需要被移除,倘若不新建一个层,删除后会成一个黑洞或报错。
if (foodwall=="true") {// 在判断撞墙处           
food->removeTileAt(Vec2(tiledCoord.x, tiledCoord.y));}
这时候要添加敌人了void addEnemy(Vec2 pos);

你可能感兴趣的:(cocos2d-x,3.0,cocos2dx-3.10)