The TMX (Tile Map XML) map format used by Tiled is a flexible way to describe a tile based map. It can describe maps with any tile size, any amount of layers, any number of tile sets and it allows custom properties to be set on most elements. Beside tile layers, it can also contain groups of objects that can be placed freely.
In this document we'll go through each element found in this map format. The elements are mentioned in the headers and the list of attributes of the elements are listed right below, followed by a short explanation. Attributes or elements that are deprecated or unsupported by the current version of Tiled are formatted in italics.
See the change log below when you're interested in what changed between Tiled versions.
A DTD-file is served at http://mapeditor.org/dtd/1.0/map.dtd. This file is not up-to-date but might be useful for XML-namespacing anyway.
right-down (the default), right-up, left-down and left-up. In all cases, the map is drawn row-by-row. (since 0.10, but only supported for orthogonal maps at the moment)The tilewidth and tileheight properties determine the general grid size of the map. The individual tiles may have different sizes. Larger tiles will extend at the top and right (anchored to the bottom left).
A map contains three different kinds of layers. Tile layers were once the only type, and are simply called layer, object layers have the objectgroup tag and image layers use the imagelayer tag. The order in which these layers appear is the order in which the layers are rendered by Tiled.
Can contain: properties, tileset, layer, objectgroup, imagelayer
<tileset> element described here. (There is the firstgid attribute missing and this source attribute is also not there. These two attributes are kept in the TMX map, since they are map specific.)Can contain: tileoffset (since 0.8.0), properties (since 0.8.0), image, terraintypes (since 0.9.0), tile
This element is used to specify an offset in pixels, to be applied when drawing a tile from the related tileset. When not present, no offset is applied.
data child element. Valid values are file extensions like png, gif, jpg, bmp, etc. (since 0.9.0)# but this is planned to change.As of the current version of Tiled Qt, each tileset has a single image associated with it, which is cut into smaller tiles based on the attributes defined on the tileset element. Later versions may add support for adding multiple images to a single tileset, as is possible in Tiled Java.
Can contain: data (since 0.9.0)
This element defines an array of terrain types, which can be referenced from the terrain attribute of the tile element.
Can contain: terrain
Can contain: properties
Can contain: properties, image (since 0.9.0), objectgroup (since 0.10.0)
All <tileset> tags shall occur before the first <layer> tag so that parsers may rely on having the tilesets before needing to resolve tiles.
Can contain: properties, data
When no encoding or compression is given, the tiles are stored as individual XML tile elements. Next to that, the easiest format to parse is the "csv" (comma separated values) format.
The base64-encoded and optionally compressed layer data is somewhat more complicated to parse. First you need to base64-decode it, then you may need to decompress it. Now you have an array of bytes, which should be interpreted as an array of unsigned 32-bit integers using little-endian byte ordering.
Whatever format you choose for your layer data, you will always end up with so called "global tile IDs" (gids). They are global, since they may refer to a tile from any of the tilesets used by the map. In order to find out from which tileset the tile is you need to find the tileset with the highest firstgid that is still lower or equal than the gid. The tilesets are always stored with increasing firstgids.
Can contain: tile
When you use the tile flipping feature added in Tiled Qt 0.7.0, the highest two bits of the gid store the flipped state. Bit 32 is used for storing whether the tile is horizontally flipped and bit 31 is used for the vertically flipped tiles. And since Tiled Qt 0.8.0, bit 30 means whether the tile is flipped (anti) diagonally, enabling tile rotation. These bits have to be read and cleared before you can find out which tileset a tile belongs to.
When rendering a tile, the order of operation matters. The diagonal flip (x/y axis swap) is done first, followed by the horizontal and vertical flips.
The following C++ pseudo-code should make it all clear:
// 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;
}
}
}
}
(Since the above code was put together on this wiki page and can't be directly tested, please make sure to report any errors you encounter when basing your parsing code on it, thanks.)
Not to be confused with the tile element inside a tileset, this element defines the value of a single tile on a tile layer. This is however the most inefficient way of storing the tile layer data, and should generally be avoided.
The object group is in fact a map layer, and is hence called "object layer" in Tiled Qt.
Can contain: properties, object
While tile layers are very suitable for anything repetitive aligned to the tile grid, sometimes you want to annotate your map with other information, not necessarily aligned to the grid. Hence the objects have their coordinates and size in pixels, but you can still easily align that to the grid when you want to.
You generally use objects to add custom information to your tile map, such as spawn points, warps, exits, etc.
When the object has a gid set, then it is represented by the image of the tile with that global ID. Currently that means width and height are ignored for such objects. The image alignment currently depends on the map orientation. In orthogonal orientation it's aligned to the bottom-left while in isometric it's aligned to the bottom-center.
Can contain: properties, ellipse (since 0.9.0), polygon, polyline, image
Used to mark an object as an ellipse. The regular x, y, width, height attributes are used to determine the size of the ellipse.
Each polygon object is made up of a space-delimited list of x,y coordinates. The origin for these coordinates is the location of the parent object. By default, the first point is created as 0,0 denoting that the point will originate exactly where the object is placed.
A polyline follows the same placement definition as a polygon object.
A layer consisting of a single image.
Can contain: properties, image
Can contain: property
Wraps any number of custom properties. Can be used as a child of the map, tile (when part of a tileset), layer, objectgroup and object elements.
When the property spans contains newlines, the current versions of Tiled Java and Tiled Qt will write out the value as characters contained inside the property element rather than as the value attribute. However, it is at the moment not really possible to edit properties consisting of multiple lines with Tiled.
It is possible that a future version of the TMX format will switch to always saving property values inside the element rather than as an attribute.
Below are described the changes/additions that were made to the TMX format for recent versions of Tiled.
hexagonal to the supported values for the orientation attribute on the map element. This also adds staggerindex (even or odd) and staggerdirection (rows or columns) and hexsidelength (integer value) attributes to the map element, in order to support the many variations of staggered hexagonal. The staggerindex attribute is now also supported when using the staggered map orientation.Tile objects can now be horizontally or vertically flipped. This is stored in the gid attribute using the same mechanism as for regular tiles. The image is expected to be flipped without affecting its position, same way as flipped tiles.
Objects can be rotated freely. The rotation is stored in degrees as a rotation attribute, with positive rotation going clockwise.
The render order of the tiles on tile layers can be configured in a number of ways through a new renderorder property on the map element. Valid values are right-down (the default), right-up, left-down and left-up. In all cases, the map is drawn row-by-row. This is only supported for orthogonal maps at the moment.
<object visible="0|1"><tileset>
...
<terraintypes>
<terrain name="Name" tile="local_id"/>
</terraintypes>
<tile id="local_id" terrain="[n],[n],[n],[n]" probability="percentage"/>
...
</tileset>There is preliminary support for a "staggered" (isometric) projection (new value for the orientation attribute of the map element).
A basic image layer type was added:
<imagelayer ...>
<image source="..."/>
</imagelayer><object ...>
<ellipse/>
</object><map ... backgroundcolor="#XXXXXX"><tileset ...>
<tile id="[n]">
<!-- an embedded image -->
<image format="png">
<data encoding="base64">
...
</data>
</image>
</tile>
<tile id="[n]">
<!-- an individually referenced image for a single tile -->
<image source="file.png"/>
</tile>
...
</tileset>Tilesets can now have custom properties (using the properties child element, just like everything else).
Tilesets now support defining a drawing offset in pixels, which is to be used when drawing any tiles from that tileset. Example:
<tileset name="perspective_walls" tilewidth="64" tileheight="64">
<tileoffset x="-32" y="0"/>
...
</tileset>
TMX Map Format by http://mapeditor.org/ is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.