<?xml version="1.0" encoding="UTF-8"?> <map version="1.0" orientation="orthogonal" width="40" height="40" tilewidth="32" tileheight="32"> <tileset firstgid="1" name="Desert" tilewidth="32" tileheight="32" spacing="3" margin="2"> <image source="desert_tiled.png" width="281" height="211"/> <tile id="30"> <properties> <property name="cactus" value="true"/> </properties> </tile> </tileset> <layer name="Ground" width="40" height="40"> <data encoding="base64" compression="gzip"> H4sIAAAAAAAAA+2YaQvCMAyGo37wAk/wRJ3OY97+/19nxJVJKF3WrbHKPjzYQVcf30QXXALA0iEdpIv0cp5TQapIjbnmnHnT+K0s/ZpIC2kz19L59ZEBMmSuOWe+shohY2SS088Vup6wrXEaU2SWgTnY9YQta2STgdChX2Tw2yInZPdFP1N+ITNPCb+9h34P4kX9LvDu/6uwH+05ep2WF+3LIvx034OI5KfWaX4016LyO5Br5ZM1P9f1pZ6UY1w/LucC/OoxDUieRSZqzH2KRU6/LiTzhfqsJtrMfbr7bPzGkMwXaj4xMWTu093nsvekCUA/5/jkGQj62MxmEl63+JXz2/n5/AkLen8uHL+X0yPeK+l399CP9rVvfjb1/ZwvpPzuGfxolr7lp6u1z36S+dnMZpJ+/0LggcOvQLNy9b9RWeOSku/wBLyVlw4AGQAA </data> </layer> </map>
TMX地图格式是Tiled编辑器采用的一种灵活的基于瓦片的地图描述格式。用它来描述的地图有以下特点:任意数量的图块,任意数量的层(layer),任意数量的图块集(tile sets)还有附加于这些元素(elements)之上的用户自定义属性。除了layer以外,它也提供了可以自由放置的对象组(Objects Group)。
在这篇文档中我们将全面的了解TMX格式的所有元素。每个元素都将以标题的形式列出,然后是该元素支持的属性及该属性的一段简要说明,当前版本的Tiled 编辑器所不支持的属性将以斜体的形式出现在属性列表中。
tilewidth与tileheight两个属性决定了地图网格的大小,个别tiles允许有不同的大小,所有的Tile将靠挂在左下角,超出的部分将在顶部和右侧延伸。
可以包含下列元素:属性,图块集,层,对象组( properties, tileset, layer, objectgroup)
此图块集的第一个图块在全局图块集中的位置。
当前版本的Tiled QT版本,每个图片集与一张图像对应,按照图片集的属性将该图像切割为多个较小的图块。QT后续开发计划将在一个图片集中支持多个图像,如同JAVA版本的Tiled提供的功能。
Base64是一种通用的方法,其原理很简单,就是把三个Byte的数据用4个Byte表示。在这四个Byte中,实际用到的都只有前面6bit,这样就不存在只能传输7bit的字符的问题了。Base64的缩写一般是“B”。
CSV逗号分隔值文件(COMMA Separated value),是一种用来存储数据的纯文本文件格式。
如果数据为本进行编码转换和压缩的情况下,图块数据将被作为XML的子元素来存储,这是最容易解析的数据格式。
采用base64编码格式的数据和压缩过后的数据解析起来较为复杂。首先你必须对数据进行解码,然后你可能需要加压缩数据。你的数据存储于一个字节数组,你不得不将它排序为一个little-endian字节序的无符号整形数组。
无论采用哪种格式存储你的图层数据,你都必须以所谓的gids作为结尾。它们是全局的,自从图块集的任意图块被用于设计当前地图。为了能够找到图块所在的图块集,你需要找到小于图块gid的最大的图块集的firstgid。所有图块集的firstgids都是按顺序排列的。
C++伪代码:
// Bits on the far end of the 32-bit global tile ID are used for tile flags const unsigned FLIPPED_HORIZONTALLY_FLAG = 0x80000000; const unsigned FLIPPED_VERTICALLY_FLAG = 0x40000000; const unsigned FLIPPED_DIAGONALLY_FLAG = 0x20000000; ... // Extract the contents of the <data> element string tile_data = ... unsigned char *data = decompress(base64_decode(tile_data)); unsigned tile_index = 0; // Here you should check that the data has the right size // (map_width * map_height * 4) for (int y = 0; y < map_height; ++y) { for (int x = 0; x < map_width; ++x) { unsigned global_tile_id = data[tile_index] | data[tile_index + 1] << 8 | data[tile_index + 2] << 16 | data[tile_index + 3] << 24; tile_index += 4; // Read out the flags bool flipped_horizontally = (global_tile_id & FLIPPED_HORIZONTALLY_FLAG); bool flipped_vertically = (global_tile_id & FLIPPED_VERTICALLY_FLAG); bool flipped_diagonally = (global_tile_id & FLIPPED_DIAGONALLY_FLAG); // Clear the flags global_tile_id &= ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG); // Resolve the tile for (int i = tileset_count - 1; i >= 0; --i) { Tileset *tileset = tilesets[i]; if (tileset->first_gid() <= global_tile_id) { tiles[y][x] = tileset->tileAt(global_tile_id - tileset->first_gid()); break; } } } }
图块不一定要处于图块集中,也可以单独存在于层中,这个元素定义了可用于图层的一个基本图块。这是最没有效率的层数据存储方式,通常应该避免。
对象组事实上就是一个图层,因此在TiledQt版本中我们也称之为对象层。
虽然块状图层非常适合用来把所有的物件对齐到网格,但有时你需要在地图中添加一些不需要对齐到网格的信息。因此对象的位置、大小单位为像素,如果你想要对齐对象到网格也很容易。通常你用对象来添加一些自定义信息,例如出生点,跳转点,退出点等等。
如果某个对象的gid属性被设置,对象将用该ID对应的图块来表示,也就是说该对象的宽度和高度信息是被忽略的。图片的对齐方式取决于当前地图的朝向。在正交地图中,于左下角对齐,在等距地图中于底部中心对齐。
多边形对象由一系列空格符分隔的坐标点组成。这些坐标点的原点是父对象的位置。默认情况下,第一个点的坐标为0,0 指示对象的存放位置。
规则如同多边形。
可以包含任意数量的自定义属性。可以用来作为地图,图块,层,对象组,对象的子元素。
如果属性值中包含换行符,当前JAVA和QT版本的Tiled编辑器的处理方法是将其包含在property元素中而非value值,当前Tiled编辑器并没有真正意义上支持多行属性值。也许在将在的版本中属性值将直接存储于元素中而非作为一个attribute存储。
原文地址:https://github.com/bjorn/tiled/wiki/TMX-Map-Format
<本节完>