您的位置:首页 > 其它

Tiled瓦片地图的使用

2016-10-22 15:05 239 查看
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
[b]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[/b]
            heroPos.[b]x
+=
m_tiled->getTileSize().width;[/b]
        }// 出于方便的考虑将m_tiled设为了成员变量

[b]    }else{[/b]
       
[b]if
(directio     n.y<0)
{[/b]
[b]            heroPos.y
-=
m_tiled->getTileSize().height;

        }

       
else{

            heroPos.
y
+=
m_tiled->getTileSize().height;

        }
[/b]

    }
   
[b]hero
->setPosition(heroPos);// 出于方便的考虑将hero设为了成员变量[/b]
[b]   
return
true;[/b]

由于地图的比较大,需要设置屏幕的适配,类似于前面说到的摄像机类,即让英雄能够走完整个地图,我们写一个名字为setPlayerPosition(Vec2 pos)的函数来完成这一功能。
屏幕中心与地图位置的差值最小是屏幕大小的一半,最大是地图的大小减去屏幕大小的一半,我们选择设置一个在一个void setViewPosition(Vec2 pos)函数中实现这个功能.
void
[b]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);[/b]

    [b]this[b]->setPosition[/b](layerPos);}[/b]
此时我们应该考虑限制英雄的移动了,对墙体等应设置属性让其无法通过,而对“蔬菜”应该让其吃掉。这时候需要使用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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐