近段时间主要是在研究开发工具与游戏制作的结合,大家知道工欲善其事必先利其器,一款好的方便的开发工具能够极大的提高游戏的开发效率,特别是在制作关卡这些东西的时候,这也就是为什么国外现在有这么多的开发引擎工具,特别是3d的比如unity3d,unreal,cryEngine等等都是基于这种需求而开发的。
那么我这个新系列的博客也就是教大家如何使用TileMap这款地图编辑器来提高大家在制作2d地图方面的效率。
这边我可能主要介绍的是一些高级用法,2d地图编辑器的一些基础用法如果大家还不清楚的就自己去百度一下,查查资料了。
下面进入正题,首先提供一下TileMap的下载地址
http://www.mapeditor.org/
TileMap是一款开源的地图编辑器,使用qt开发,因此可以跨平台,而且因为开源,所以大家还可以根据自己的需求进行加工和修改,这一点是很重要。
这里为刚接触游戏开发的同学插一句,为什么要开发地图编辑器呢,我们就用整张图做地图不就好了吗?
这里简单回答一下,好处有两个:www.it165.net
第一个是极大的减少用图的面积,这样就减少了在运行时系统占用的内存,具体原理问你们的boss或者度娘。
第二个好处是可以通个打散的地图方便在格子中做很多事件,方便判断,比如做地图行走障碍判断,做触发事件判断。
下载之后安装,打开编辑器如下。
点击新建地图,弹出如下方框
编辑器地图方向可以选择 “正常”或者“45度”两种,这个是很多其他编辑器没有的功能,大部分的编辑器都只支持单一方向的地图编辑,所以这也是我选择TileMap这款编辑器来开发的原因。
地图大小表示地图格子数的多少,30*30 的话就是一共900个格子
右边的块大小表示单个格子的大小,这里是64*32, 一般正方向地图块大小都是一致的,这边我们使用32*32。
按确定之后如下图
下面我们添加图片资源
点击“地图”->新图块,弹出下框
点击“浏览”按钮选择一张图片,这里我们用cocos2d-x里面自带的很有代表性的图片,路径如下
cocos2d-2.0-x-2.0.2\samples\TestCpp\Resources\TileMaps\tmw_desert_spacing.png
这里块的宽高就是32,说一下边距和间距的意思,
边距就是指两个块之间横向的间隔
间距就是指两个块之间纵向的间隔
我们看到图片上有很多黑色线,一般大家之前做的图块是不会加这些间隔线的,但是可能有特殊情况,那现在我们就遇到了,所以现在如果我们这边不加间距和边距的话,切出来的图块就会出现问题。
大家可以看见这里是我没有设置间距和边距切出来的图块,明显的偏差的像素会越来越多,
下面我们把这张图块先删除,再重新添加原图块
点击图块下方的“垃圾桶”按钮删除图块。
下面我们看看设置边距间距之后,这里我们都设置为1个像素
好了,我们看见图块的分割白线已经把图片上本身的黑色线完美覆盖,说明我们的设置是正确的,下面就可以用图块来拼接一张地图了
这一排就是工具按钮,一般做地图的时候用前3个按钮
第一个是图章,单个刷,或者一个矩形的图块刷用这个工具
第二个是填充,
第三个是橡皮擦
大家试一下就知道用法了,记住,在图块层上的时候可以用鼠标一次框选一个矩形的图块哦,然后用第一个图章刷就很方便快速了。
好了,大家都练习一下吧。
最后导出就点击 文件->另存为就行了。
这里再教大家几个小技巧:
选中图块,按键盘“X”快捷键可以实现图块原地水平翻转,“Y”是垂直翻转,
“Z”键可以循环90度翻转。非常实用。
还有一个随机模式的按钮
这个按钮的作用是当选中之后
然后在地图块上框选一大块地图,这时候在地图上绘制的时候会随机从你选中的很多图块中里面选取一个绘制在地图上效果如下
另外,所有TileMap中的指令大家可以在这里查到
https://github.com/bjorn/tiled/wiki/Keyboard-Shortcuts
现在应该知道学好英语的重要性了吧
cocos2d-x中讲解TileMap地图编辑器的高级用法(一)
上一篇教大家做好了一张地图,那么我们如何在真正的游戏中使用呢,这一篇就是主要教大家在cocos2d-x中使用
我们把上一篇做好的地图保存后,放置在游戏项目的资源目录下
那么我们包含地图的代码其实非常简单
1.
CCTMXTiledMap* map = CCTMXTiledMap::create(
"myTest.tmx"
);
2.
addChild(map);
就用这两句话就把我们的地图tmx文件加入到layer,addchild之后,这张地图就会绘制出来了
下面讲点新的东西
第一:图块设置技巧及注意事项
点击 图层 ->添加图层
层上的名字我们改成英文,大家记住做程序的时候所有东西都改成英文,不管是文件名,标签名,包括文件存放路径都不要包括中文,反正除了我们游戏里面需要的界面或者对话,或者类似必须要用中文的东西,其他都一定用英文来表示。毕竟计算机是老外发明的,我们就按人家的规则来玩吧。
修改后
这样表示层1,层2
这样加多层之后就可以做一些遮罩效果了。
现在说一下多层会遇到的一些问题
每个层都可以用很多不用的图片,但是有一个规则一定要记住
你在同一层使用的图片块大小一定要一致,比如你之前用32*32的图片块拼了一部分,那么后面你换了另一个图片的块大小也必须是32*32的,不能是其他大小,如果你用了两种大小,编辑器里面不会出问题,但是一旦你使用在cocos2d-x中
CCTMXLayer类会报以下错误 www.it165.net
CCAssert( m_uMaxGID >= m_pTileSet->m_uFirstGid &&
m_uMinGID >= m_pTileSet->m_uFirstGid, "TMX: Only 1 tilset per layer is supported");
看清楚了吗,TMX: Only 1 tilset per layer is supported
“每层只支持一种图块尺寸设置”
所以大家这个地方要注意
这里再讲下第二个地图块切块要注意的地方
如果有以前用过地图编辑器的同学肯定清楚,一般的地图编辑器设定了地图的块大小的话,那么图片的块切割大小也就必须是和地图单块的大小一致的
但是我们的TileMap这款编辑器可以分开设置
例如地图块大小设置32*32,图片块大小我可以设置成52*64,或者其他64*31
都可以,等你设置好了,在地图块填充的时候就会发现,TileMap会自动以左下角为
对齐点。比如我把一个图片切成60*64的图片效果如下
看见了吗,深色部分表示我放置的点,那么超过的部分就自动向上和向右延伸了,
所以我们会看见在cocos2d-x的TileMaps资源下面会有这样的图存在
ok,图片设置基本就讲这么多,下一篇教大家加入对象层和设置tile块的一些属性,可以在游戏中做的一些事情。
cocos2d-x中讲解TileMap地图编辑器的高级用法(二)
上一篇教大家了一些TileMap地图块设置的基本规则和注意事项
这一篇开始教大家些复杂的东西:
如何通过地图块的id做一些事件的判断。
这里先解释下图块的id是什么:
图块的id就是当你加载地图图片的时候通过设置图片切块的大小会把一张地图图片切成很多小块,这些小块会自动编成一个一维数组,从0开始,如下所示
第一步:首先解决第一个问题:如何获取图块id
因为图块首先是画在图层上的,所以我们先得找到对应的图层
1.
map = CCTMXTiledMap::create(
"maps/Test2.tmx"
);
2.
CCTMXLayer* walklay = map->layerNamed(
"layer0"
);
ok,现在walklay就是我们要判断地图id的图层了,通过layer0这个图层名字获得了。
跟编辑器里面的标签要对应上
好了现在得到层了,就得找对应id了。
第二步:
也很简单,如果我们想获取图层5行6列的地图块id是多少,www.it165.net
1.
CCPoint pp = ccp(
6
,
5
);
//这里第一个参数是列数,第二个是行数,特别注意
2.
unsigned
int
id = layer0->tileGIDAt(pp);
ok,现在id 就是我们得到的图块的索引值了。
想获得其他图层的其他格子上的图块索引值同理。
得到这个值能干什么呢??
举例:
1、做人物行走阻挡,比如我判断如果地图上所有索引为5的图块不能行走。
2、更换图块,比如我设置所有格子id为5的格子不显示。
。。。。
等等,根据不同的游戏我们可以有很多种的用途。
之前三篇地图主要讲的都是地图绘制有关的部分,这一篇就讲一讲如果添加对象层,以及如何处理对象层的信息
我们点击 图层->添加对象层
这里就会出现一个新的对象层,区别于图层,用紫色标记
同样的,我们更改下名字,变为“object0”
光加了层没用,我们还得在层上标记具体的对象
下面我们把光标点中“object0”对象层
我们可以看见工具栏有了变化
前面与图层有关的按钮变为了灰色,后面与对象层有关的按钮变亮了
点击 “插入对象”
按钮
然后我们用鼠标在地图上拖出一个框来,格子数多少可以自由决定
,不过一般我们就使用一格就好了,
按住右下角的小正方形可以拖拉改变格子的大小
下面我们给对象添加属性
右键点击对象,弹出下框
点击对象属性
这里上面第一排的名称是方便在编辑器查看用的,因此最上面的“名称”和类型处不填也可以。
下面我们加一个新的属性,命名为playerBorn吧,表示游戏人物主角的出生地
值可以指定为1,下面再定义个Hp的属性,值写个100,表示主角出生血量为100
确定保存,之后加入到我们的游戏工程目录下 www.it165.net
第二步:读取属性信息
01.
CCTMXObjectGroup* group = map->objectGroupName(
"object0"
);
//第一步,获取对象层
02.
CCArray* objects = group->getObjects();
//获取层上对象集合
03.
CCDictionary* dict = NULL;
04.
CCObject* pObj = NULL;
05.
CCARRAY_FOREACH(objects, pObj)
//遍历对象集合中的对象
06.
{
07.
dict = (CCDictionary*)pObj;
//
08.
if
(!dict)
09.
break
;
10.
const
char
* key =
"playerBorn"
;
//设定关键字,对应我们的"playerBorn"
11.
CCString *str = (CCString*)dict->objectForKey(key);
12.
if
(str)
13.
{
14.
key =
"x"
;
15.
float
x = ((CCString*)dict->objectForKey(key))->floatValue();
//获取对应对象的x坐标
16.
key =
"y"
;
17.
float
y = ((CCString*)dict->objectForKey(key))->floatValue();
//获取对应对象的y坐标
18.
player->setPosition(ccp(x,y));
//这里player是我们的主角sprite对象,设置坐标位置
19.
key =
"hp"
;
20.
int
Hp = ((CCString*)dict->objectForKey(key))->intValue();
//获得主角血量100
21.
player->setHp(Hp);
22.
break
;
//找到过后,退出循环
23.
}
24.
}
这里有个地方大家要注意,在编辑器上,我们的x,y属性中的值是格子数,
比如
这里,x是15,y是16,表示的是这个对象在地图的16行15列的格子上,
但是在cocos2d-x中用读取出来的就不是15,16了,而是自动乘过块大小后在地图上的像素值了,所以这就是为什么我设置主角setPosition的时候,直接用的转换后的,xy值,而没有再用他们去乘以tile块的宽高的原因
基本使用就是这样了,下一篇教大家如何处理斜45度角的地图。