Tiled 使用总结
2016-07-28 11:58
162 查看
<1>知识点:地图的创建。
第一步:新建--》新文件 (就可以打开一个地图了)。
第二步:地图--》新图块 (这样就可以利用这些图块资源当做砖块来填充图层了)。
第三步:就可以添加:图层、对象层、图像图层了。
第四步:利用图块填充好对应的图层。
第五步:添加对象层。添加过对象层后可用插入矩形等来插入对象,还可以为对象名;切记一个对象层可以容纳很多个对象,可以通过对象层的名字返回对象的信息。
第六步:文件--》另存为(命名一下之后就得到地图了)。
总结:可知,最后 图层和对象层和必不可少的资源图片组成了最后的地图。
当然了,地图的大小什么的就是设计好后依然可以调整,不然就太不灵活了。
<2>知识点:地图长度问题。
Tiled制作的砖块地图过长的时候下面是可以拖动滚动条滚动的,因此完全可以通过滚动看到整个地图的全貌。因此尽管你的超级玛丽地图很长,但是不用担心,你是可以通过滚动看到地图全貌的设计的。
<3>知识点:地图中的图块编号与坐标。
A,图块编号是左上角是(0,0)。而且对象编号是从0开始索引的。
B,坐标依然是从左下角开始的。因此对象的位置是(它距左下角的X位置 * 每个格子X像素, 它距左下角的Y位置 * 每个格子Y像素)
<4>知识点:地图的加载代码实现。
方法1:直接加载地图,并且设置地图层的抗锯齿属性。
_tilemp=CCTMXTiledMap::create("pd_tilemap.tmx");
CCObject* obj=NULL;
CCARRAY_FOREACH(_tilemp->getChildren(),obj)
{
CCTMXLayer* _child=(CCTMXLayer*)obj;
_child->getTexture()->setAliasTexParameters(); //关闭抗锯齿
}
this->addChild(_tilemp);
方法2:通过路径加载(注意一下CCFileUtils的使用)。
string resources = "TileMaps";
string file = resources + "/orthogonal-test1.tmx";
CCString* str = CCString::createWithContentsOfFile(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(file.c_str()));
//create参数说明:资源文件全路径,资源路径目录
CCTMXTiledMap *map = CCTMXTiledMap::create(str->getCString() ,resources.c_str());
<5>知识点:地图的滚动。
void HelloWorld::mapScroll(CCPoint touchPoint)
{
CCSize winSize=CCDirector::sharedDirector()->getWinSize();
int x=MAX(touchPoint.x, winSize.width/2);
int y=MAX(touchPoint.y, winSize.height/2);
x=MIN(x,(this->m_tiledMap->getMapSize().width*this->m_tiledMap->getTileSize().width)-winSize.width/2);
y=MIN(y,(this->m_tiledMap->getMapSize().height*this->m_tiledMap->getTileSize().height)-winSize.height/2);
CCPoint actualPosition=ccp(x,y);
CCPoint centerOfView=ccp(winSize.width/2,winSize.height/2);
CCPoint viewPoint=ccpSub(centerOfView,actualPosition); //v1 - v2 也就是第一个减去第二个
this->setPosition(viewPoint);
}
<6>知识点:让机器人朝靠近英雄的地方走。
void GameLayer::updateRobots(float dt)
{
int alive=0; //当前活着的机器人的数量
int distanceSQ;
int randomChoice=0;
CCObject* pObject=NULL;
CCARRAY_FOREACH(this->_robots,pObject){
Robot* robot=(Robot*)pObject;
if(robot->_actionState != kActionDead){
alive++;
if(::GetCurTime()>robot->_nextDecisionTime){
distanceSQ=ccpDistanceSQ(robot->getPosition(),this->_hero->getPosition());
if(distanceSQ<=50*50){
robot->_nextDecisionTime=::GetCurTime()+frandom_range(0.1,0.5)*1000;
randomChoice=random_range(0,1);
if(randomChoice==0){ //机器人执行攻击动作
if(this->_hero->getPositionX()>robot->getPositionX()){
robot->setScaleX(1.0f);
}else{
robot->setScaleX(-1.0f);
}
robot->_nextDecisionTime=robot->_nextDecisionTime+frandom_range(0.1,0.5)*2000;
robot->attack();
//检测机器人是否攻击到英雄
if(fabsf(this->_hero->getPositionY()-robot->getPositionY())<10){
if(_hero->_hitBox.actual.intersectsRect(robot->_attackBox.actual)){
_hero->hurtWithDamage(robot->_damage);
if(_hero->_actionState==kActionDead && (((GameScene*)(this->getParent()))->_hudLayer->getActionByTag(537)==NULL)){
this->endGame();
}
}
}
}else{ //执行空闲动作
robot->idle();
}
}else if(distanceSQ <= CCDirector::sharedDirector()->getWinSize().width*CCDirector::sharedDirector()->getWinSize().width){
robot->_nextDecisionTime=::GetCurTime()+frandom_range(0.5,1.0)*1000;
randomChoice=random_range(0,2);
if(randomChoice==0){ //机器人执行行走动作
CCPoint moveDirection=ccpNormalize(ccpSub(_hero->getPosition(),robot->getPosition())); //求标准化向量
robot->walkWithDirection(moveDirection);
robot->updateDesiredPosition(dt*20);
//robot->setPosition(robot->_desiredPosition);
}else{ //执行空闲动作
robot->idle();
}
}
}
}
}
if(alive==0 && ((GameScene*)(this->getParent()))->_hudLayer->getChildByTag(537)==NULL){
this->endGame();
}
}
<7>限制敌人只能在地图内走动。
CCObject* pObject=NULL;
CCARRAY_FOREACH(this->_robots,pObject){
Robot* robot=(Robot*)pObject;
posx=MIN(this->_tilemp->getMapSize().width*this->_tilemp->getTileSize().width-robot->_centerToSides,MAX(robot->_centerToSides,robot->_desiredPosition.x));
posY=MIN(3*this->_tilemp->getTileSize().height+robot->_centerToBottom,MAX(robot->_centerToBottom,robot->_desiredPosition.y));
robot->setPosition(ccp(posx,posY));
}
<8>Tiled中的碰撞检测。
名词:meta 图元 tile 砖块
变量:
CCTMXTiledMap* m_tiledMap; //地图
CCSprite* wangYijIe; //英雄王义杰
CCTMXLayer* m_meta; //障碍物层(英雄不可穿越)
A,第一步:将该碰撞层设置为不可见(虽然不可见,但是还是可以获取其砖块)
m_meta = m_tiledMap->layerNamed("Meta");
m_meta->setVisible(false);
B,以人物不能穿越障碍物为例,人物行走代码如下。
//返回游戏中某点对应的地图中砖块的坐标。
CCPoint HelloWorld::tileCoordForPosition(CCPoint position)
{
int x = position.x / m_tiledMap->getTileSize().width;
int y = (m_tiledMap->getContentSize().height - position.y) / m_tiledMap->getTileSize().height;
return CCPointMake(x, y);
}
//
void HelloWorld::setPlayerPosition(CCPoint position)
{
//当没有障碍物时,英雄行走
CCPoint heroPoint = wangYijIe->getPosition(); //
int x, y;
if(position.x > heroPoint.x)
x = heroPoint.x + 5;
else
x = heroPoint.x - 5;
if (position.y > heroPoint.y)
y = heroPoint.y + 5;
else
y = heroPoint.y - 5;
CCPoint tileCoord = this->tileCoordForPosition(ccp(x, y));
int tileGid = m_meta->tileGIDAt(tileCoord);
if(tileGid) //不为0说明那边有不可穿越的砖块,因此直接返回
(如果这里有砖块,那么就是碰撞了)
return;
wangYijIe->setPosition(ccp(x, y));
}
<9>知识点:熟练对Tiled地图的一些操作。
A,根据名字获得层对象
CCTMXLayer* layer = map->layerNamed("trees");
B,根据精灵在层中的位置可以获得对应的精灵。
m_tamara = layer->tileAt(ccp(0,11));
C,移除(x, y)位置的精灵。
方法1:
CCSprite* sprite = layer->tileAt( ccp(x,y) );
layer->removeChild(sprite, true);
方法2:
layer->removeTileAt( ccp(x,y) );
D,根据群组名获得对象群组,并且遍历群组的元素输出其坐标。
CCTMXObjectGroup* group = m_tiledMap->objectGroupNamed("Hero");
CCArray* heroArrayDic = group->getObjects();
CCObject* dicObj;
CCARRAY_FOREACH(heroArrayDic, dicObj)
{
CCDictionary* dic = (CCDictionary*)dicObj;
float x = dic->valueForKey("x")->floatValue();
float y = dic->valueForKey("y")->floatValue();
CCLog("%f, %f", x, y); //显而易见,可以通过该x,y坐标来初始化比如金币等精灵。
}
特例:当对象层只有一个英雄对象时,可以获取到这个英雄。
CCTMXObjectGroup* group = m_tiledMap->objectGroupNamed("Hero");
CCDictionary* dic = (CCDictionary*)group->getObjects()->objectAtIndex(0);
float x = dic->valueForKey("x")->floatValue();
float y = dic->valueForKey("y")->floatValue();
wangYijIe = CCSprite::create("WangYiJie.jpg"); //显而易见,可以通过该x,y坐标来初 始化比如金币等精灵
wangYijIe->setPosition(ccp(x, y));
addChild(wangYijIe);
<10>知识点:熟悉几个函数。
A,getMapSize
CCLog("%f, %f", m_tiledMap->getMapSize().width, m_tiledMap->getMapSize().height);
//30 12 (也就是横向和竖向的砖块个数)
B, getTileSize
CCLog("%f, %f", m_tiledMap->getTileSize().width, m_tiledMap->getTileSize().height);
//40 40 (也就是每个砖块的像素 横和竖都是40个像素)
C,getContentSize
CCLog("%f, %f", m_tiledMap->getContentSize().width, m_tiledMap->getContentSize().height);
//1200 480 (地图的大小 也就是宽和高)
总结:
这个我举得例子虽然有点特殊(地图大小恰好和屏幕一般大),但是我们已经可以得出下面的结论:
地图的宽度为:m_tiledMap->getMapSize().width * m_tiledMap->getTileSize().width
地图的高度为:m_tiledMap->getMapSize().height * m_tiledMap->getTileSize().height
或者这样写:
地图的宽度为:m_tiledMap->getContentSize().width()
地图的高度为:m_tiledMap->getContentSize().height()
<11>知识点:熟悉对象的一些属性。
将.tmx文件的地图用notepad++打开,发现其实所谓的.tmx Tiled文件本质是一个XML文件。
对于对象层中的对象,那么它就自己本身含有坐标x,y,width,height等属性。我们可以轻松
通过这些属性来获取对象的位置和宽高等信息。
第一步:新建--》新文件 (就可以打开一个地图了)。
第二步:地图--》新图块 (这样就可以利用这些图块资源当做砖块来填充图层了)。
第三步:就可以添加:图层、对象层、图像图层了。
第四步:利用图块填充好对应的图层。
第五步:添加对象层。添加过对象层后可用插入矩形等来插入对象,还可以为对象名;切记一个对象层可以容纳很多个对象,可以通过对象层的名字返回对象的信息。
第六步:文件--》另存为(命名一下之后就得到地图了)。
总结:可知,最后 图层和对象层和必不可少的资源图片组成了最后的地图。
当然了,地图的大小什么的就是设计好后依然可以调整,不然就太不灵活了。
<2>知识点:地图长度问题。
Tiled制作的砖块地图过长的时候下面是可以拖动滚动条滚动的,因此完全可以通过滚动看到整个地图的全貌。因此尽管你的超级玛丽地图很长,但是不用担心,你是可以通过滚动看到地图全貌的设计的。
<3>知识点:地图中的图块编号与坐标。
A,图块编号是左上角是(0,0)。而且对象编号是从0开始索引的。
B,坐标依然是从左下角开始的。因此对象的位置是(它距左下角的X位置 * 每个格子X像素, 它距左下角的Y位置 * 每个格子Y像素)
<4>知识点:地图的加载代码实现。
方法1:直接加载地图,并且设置地图层的抗锯齿属性。
_tilemp=CCTMXTiledMap::create("pd_tilemap.tmx");
CCObject* obj=NULL;
CCARRAY_FOREACH(_tilemp->getChildren(),obj)
{
CCTMXLayer* _child=(CCTMXLayer*)obj;
_child->getTexture()->setAliasTexParameters(); //关闭抗锯齿
}
this->addChild(_tilemp);
方法2:通过路径加载(注意一下CCFileUtils的使用)。
string resources = "TileMaps";
string file = resources + "/orthogonal-test1.tmx";
CCString* str = CCString::createWithContentsOfFile(CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(file.c_str()));
//create参数说明:资源文件全路径,资源路径目录
CCTMXTiledMap *map = CCTMXTiledMap::create(str->getCString() ,resources.c_str());
<5>知识点:地图的滚动。
void HelloWorld::mapScroll(CCPoint touchPoint)
{
CCSize winSize=CCDirector::sharedDirector()->getWinSize();
int x=MAX(touchPoint.x, winSize.width/2);
int y=MAX(touchPoint.y, winSize.height/2);
x=MIN(x,(this->m_tiledMap->getMapSize().width*this->m_tiledMap->getTileSize().width)-winSize.width/2);
y=MIN(y,(this->m_tiledMap->getMapSize().height*this->m_tiledMap->getTileSize().height)-winSize.height/2);
CCPoint actualPosition=ccp(x,y);
CCPoint centerOfView=ccp(winSize.width/2,winSize.height/2);
CCPoint viewPoint=ccpSub(centerOfView,actualPosition); //v1 - v2 也就是第一个减去第二个
this->setPosition(viewPoint);
}
<6>知识点:让机器人朝靠近英雄的地方走。
void GameLayer::updateRobots(float dt)
{
int alive=0; //当前活着的机器人的数量
int distanceSQ;
int randomChoice=0;
CCObject* pObject=NULL;
CCARRAY_FOREACH(this->_robots,pObject){
Robot* robot=(Robot*)pObject;
if(robot->_actionState != kActionDead){
alive++;
if(::GetCurTime()>robot->_nextDecisionTime){
distanceSQ=ccpDistanceSQ(robot->getPosition(),this->_hero->getPosition());
if(distanceSQ<=50*50){
robot->_nextDecisionTime=::GetCurTime()+frandom_range(0.1,0.5)*1000;
randomChoice=random_range(0,1);
if(randomChoice==0){ //机器人执行攻击动作
if(this->_hero->getPositionX()>robot->getPositionX()){
robot->setScaleX(1.0f);
}else{
robot->setScaleX(-1.0f);
}
robot->_nextDecisionTime=robot->_nextDecisionTime+frandom_range(0.1,0.5)*2000;
robot->attack();
//检测机器人是否攻击到英雄
if(fabsf(this->_hero->getPositionY()-robot->getPositionY())<10){
if(_hero->_hitBox.actual.intersectsRect(robot->_attackBox.actual)){
_hero->hurtWithDamage(robot->_damage);
if(_hero->_actionState==kActionDead && (((GameScene*)(this->getParent()))->_hudLayer->getActionByTag(537)==NULL)){
this->endGame();
}
}
}
}else{ //执行空闲动作
robot->idle();
}
}else if(distanceSQ <= CCDirector::sharedDirector()->getWinSize().width*CCDirector::sharedDirector()->getWinSize().width){
robot->_nextDecisionTime=::GetCurTime()+frandom_range(0.5,1.0)*1000;
randomChoice=random_range(0,2);
if(randomChoice==0){ //机器人执行行走动作
CCPoint moveDirection=ccpNormalize(ccpSub(_hero->getPosition(),robot->getPosition())); //求标准化向量
robot->walkWithDirection(moveDirection);
robot->updateDesiredPosition(dt*20);
//robot->setPosition(robot->_desiredPosition);
}else{ //执行空闲动作
robot->idle();
}
}
}
}
}
if(alive==0 && ((GameScene*)(this->getParent()))->_hudLayer->getChildByTag(537)==NULL){
this->endGame();
}
}
<7>限制敌人只能在地图内走动。
CCObject* pObject=NULL;
CCARRAY_FOREACH(this->_robots,pObject){
Robot* robot=(Robot*)pObject;
posx=MIN(this->_tilemp->getMapSize().width*this->_tilemp->getTileSize().width-robot->_centerToSides,MAX(robot->_centerToSides,robot->_desiredPosition.x));
posY=MIN(3*this->_tilemp->getTileSize().height+robot->_centerToBottom,MAX(robot->_centerToBottom,robot->_desiredPosition.y));
robot->setPosition(ccp(posx,posY));
}
<8>Tiled中的碰撞检测。
名词:meta 图元 tile 砖块
变量:
CCTMXTiledMap* m_tiledMap; //地图
CCSprite* wangYijIe; //英雄王义杰
CCTMXLayer* m_meta; //障碍物层(英雄不可穿越)
A,第一步:将该碰撞层设置为不可见(虽然不可见,但是还是可以获取其砖块)
m_meta = m_tiledMap->layerNamed("Meta");
m_meta->setVisible(false);
B,以人物不能穿越障碍物为例,人物行走代码如下。
//返回游戏中某点对应的地图中砖块的坐标。
CCPoint HelloWorld::tileCoordForPosition(CCPoint position)
{
int x = position.x / m_tiledMap->getTileSize().width;
int y = (m_tiledMap->getContentSize().height - position.y) / m_tiledMap->getTileSize().height;
return CCPointMake(x, y);
}
//
void HelloWorld::setPlayerPosition(CCPoint position)
{
//当没有障碍物时,英雄行走
CCPoint heroPoint = wangYijIe->getPosition(); //
int x, y;
if(position.x > heroPoint.x)
x = heroPoint.x + 5;
else
x = heroPoint.x - 5;
if (position.y > heroPoint.y)
y = heroPoint.y + 5;
else
y = heroPoint.y - 5;
CCPoint tileCoord = this->tileCoordForPosition(ccp(x, y));
int tileGid = m_meta->tileGIDAt(tileCoord);
if(tileGid) //不为0说明那边有不可穿越的砖块,因此直接返回
(如果这里有砖块,那么就是碰撞了)
return;
wangYijIe->setPosition(ccp(x, y));
}
<9>知识点:熟练对Tiled地图的一些操作。
A,根据名字获得层对象
CCTMXLayer* layer = map->layerNamed("trees");
B,根据精灵在层中的位置可以获得对应的精灵。
m_tamara = layer->tileAt(ccp(0,11));
C,移除(x, y)位置的精灵。
方法1:
CCSprite* sprite = layer->tileAt( ccp(x,y) );
layer->removeChild(sprite, true);
方法2:
layer->removeTileAt( ccp(x,y) );
D,根据群组名获得对象群组,并且遍历群组的元素输出其坐标。
CCTMXObjectGroup* group = m_tiledMap->objectGroupNamed("Hero");
CCArray* heroArrayDic = group->getObjects();
CCObject* dicObj;
CCARRAY_FOREACH(heroArrayDic, dicObj)
{
CCDictionary* dic = (CCDictionary*)dicObj;
float x = dic->valueForKey("x")->floatValue();
float y = dic->valueForKey("y")->floatValue();
CCLog("%f, %f", x, y); //显而易见,可以通过该x,y坐标来初始化比如金币等精灵。
}
特例:当对象层只有一个英雄对象时,可以获取到这个英雄。
CCTMXObjectGroup* group = m_tiledMap->objectGroupNamed("Hero");
CCDictionary* dic = (CCDictionary*)group->getObjects()->objectAtIndex(0);
float x = dic->valueForKey("x")->floatValue();
float y = dic->valueForKey("y")->floatValue();
wangYijIe = CCSprite::create("WangYiJie.jpg"); //显而易见,可以通过该x,y坐标来初 始化比如金币等精灵
wangYijIe->setPosition(ccp(x, y));
addChild(wangYijIe);
<10>知识点:熟悉几个函数。
A,getMapSize
CCLog("%f, %f", m_tiledMap->getMapSize().width, m_tiledMap->getMapSize().height);
//30 12 (也就是横向和竖向的砖块个数)
B, getTileSize
CCLog("%f, %f", m_tiledMap->getTileSize().width, m_tiledMap->getTileSize().height);
//40 40 (也就是每个砖块的像素 横和竖都是40个像素)
C,getContentSize
CCLog("%f, %f", m_tiledMap->getContentSize().width, m_tiledMap->getContentSize().height);
//1200 480 (地图的大小 也就是宽和高)
总结:
这个我举得例子虽然有点特殊(地图大小恰好和屏幕一般大),但是我们已经可以得出下面的结论:
地图的宽度为:m_tiledMap->getMapSize().width * m_tiledMap->getTileSize().width
地图的高度为:m_tiledMap->getMapSize().height * m_tiledMap->getTileSize().height
或者这样写:
地图的宽度为:m_tiledMap->getContentSize().width()
地图的高度为:m_tiledMap->getContentSize().height()
<11>知识点:熟悉对象的一些属性。
将.tmx文件的地图用notepad++打开,发现其实所谓的.tmx Tiled文件本质是一个XML文件。
对于对象层中的对象,那么它就自己本身含有坐标x,y,width,height等属性。我们可以轻松
通过这些属性来获取对象的位置和宽高等信息。
相关文章推荐
- IOS 动态库问答
- 【杭电】[1181]变形课
- centos 文件扩展swap
- 【Git/Github学习笔记】Git课程简介
- muduo : Thread-safe Singleton
- 绝世唐门漫画的王秋儿
- git 使用(不断更新)
- HA 集群软件 keepalived 详解
- 月薪过万的Xcode插件
- Docker学习笔记 — 配置国内免费registry mirror
- cocostudio常识
- java读取classpath下的properties文件
- (12)SSH整合中的web.xml文件
- java系统高并发解决方案(转载)
- Partition does not end on cylinder boundary
- Android Calendar Provider基础
- php学习2----分页原理
- Android提醒微技巧你真的了解Dialog、Toast和Snackbar吗
- mysql日志
- STL 之set不允许元素重复,且从小到大排列