T2D MIT supporting TMX maps
by William Hilke · 02/28/2013 (3:23 pm) · 5 comments
I've been working on integrating TMX tile maps into T2D MIT for a while now. You can follow my TMX thread in the forums if you want to see more details:
www.garagegames.com/community/forums/viewthread/133244
I have both iso and orthogonal based tile maps working, supporting multiple tile layers and object layers. Of course, that is just not enough for any real tile map usage.
You need custom tile data, collision bodies, etc. before you can really start to use any tile map. To support that extra data, I have introduced a TmxMapAsset type that
binds your map file with your extra scene data to automate everything. I've also introduced a new SceneObject for rendering TMX maps, which consume TmxMapAsset.
Here is a simple workflow that takes a simple map into T2D MIT, and allows it to be used within your scene.
For this walk through I'm actually going to use a map designed for a side scrolling beat um up setup. I thought this would be more fun than a standard map, and it shows that
tile maps can be used for a lot more than what you think.
First, we load up our basic map into Tiled (www.mapeditor.org):

This is a 100x11 tile map, with two layers. Th size of each tile is 32x32, and that is the same size as the tileset tiles. This gives us our basic
level layout for our beat um up scroller. Of course a real map would be a lot larger then just 100 tiles across (or you'd use a larger tileset).
The next step is to now add in a collision layer. This layer is designed to not render, but allow us to set anchor points for scene objects that we will define later.

You can see that I've added a new layer, and on that layer I've added a few tiles across the bottom of the map, the sides, and the bottom of the wall. This is going to be
used to setup box2d collision bodies to make sure you can only navigate on the floor. You'll also notice that the tiles for this layer came from a "Collision" tileset.
I use this so that I can visually separate the different anchor tiles on the map. These do not render, so it doesn't matter what you use.
Our next step is to now define an anchor tag for each of these different collision types in the tileset. A tag is used by the asset to bind a set of SceneObjects to any tile
location that uses a tile with a tag (will be shown down below). You do this by adding a custom property to a tile in the tileset with a name of "Tag", and a value that you will use later in your asset file.

We can now save our map to a tmx file, and move on to defining the TmxMapAsset file. In the following asset file we are mapping in the tmx file, and then we define the layers of the map.
For each layer we map it to the Tmx layer name, and then we can define some custom properties. You can specify the layer number that layer should use in the scene (for sorted rendering, etc), as well as if the
layer should render at all. For our "Collisions" layer we are turning rendering off since it's just used as a data layer. You can also turn object use off for a layer, which is useful if you bound tags to real tiles
on a collision layer, but you don't want your rendering layers to pull in those tags. After that, the tile tags are setup based on the tag names we defined in the TMX file.
Here we are using 3 different tags, and each tag is creating one SceneObject with a polygon collision shape. You can specify as many SceneObjects as you want, or any derived SceneObject that can be deserialized via TAML.
The scene layer, position, and size will be override and set to match the tile that it's linked against in the grid. All other properties are allowed. It's important to remember that a collision body can be larger then the
object size, and because of this you can design your maps to use as few sceneobject/collision bodies as needed. Even in this test map, we can cull out several collision tiles and just expand the collision body.
The only step left now is to load this up in T2D MIT
Easy right? Under the hood that will generate a CompositeSprite for each map layer, put them on the correct scene layers, and will spawn all the SceneObjects linked by tags in the correct locations as well. The entire map is anchored to the TmxMapSprite, so you can position it anywhere in the scene.
Here's a quick video of this map rendering in the sandbox. I even added an animated sprite in the level and threw it against a collision to get it bouncing around.
I have a work in progress branch at my GitHub repo: github.com/whilke/Torque2D/tree/feature/tmx_maps
www.garagegames.com/community/forums/viewthread/133244
I have both iso and orthogonal based tile maps working, supporting multiple tile layers and object layers. Of course, that is just not enough for any real tile map usage.
You need custom tile data, collision bodies, etc. before you can really start to use any tile map. To support that extra data, I have introduced a TmxMapAsset type that
binds your map file with your extra scene data to automate everything. I've also introduced a new SceneObject for rendering TMX maps, which consume TmxMapAsset.
Here is a simple workflow that takes a simple map into T2D MIT, and allows it to be used within your scene.
For this walk through I'm actually going to use a map designed for a side scrolling beat um up setup. I thought this would be more fun than a standard map, and it shows that
tile maps can be used for a lot more than what you think.
First, we load up our basic map into Tiled (www.mapeditor.org):

This is a 100x11 tile map, with two layers. Th size of each tile is 32x32, and that is the same size as the tileset tiles. This gives us our basic
level layout for our beat um up scroller. Of course a real map would be a lot larger then just 100 tiles across (or you'd use a larger tileset).
The next step is to now add in a collision layer. This layer is designed to not render, but allow us to set anchor points for scene objects that we will define later.

You can see that I've added a new layer, and on that layer I've added a few tiles across the bottom of the map, the sides, and the bottom of the wall. This is going to be
used to setup box2d collision bodies to make sure you can only navigate on the floor. You'll also notice that the tiles for this layer came from a "Collision" tileset.
I use this so that I can visually separate the different anchor tiles on the map. These do not render, so it doesn't matter what you use.
Our next step is to now define an anchor tag for each of these different collision types in the tileset. A tag is used by the asset to bind a set of SceneObjects to any tile
location that uses a tile with a tag (will be shown down below). You do this by adding a custom property to a tile in the tileset with a name of "Tag", and a value that you will use later in your asset file.

We can now save our map to a tmx file, and move on to defining the TmxMapAsset file. In the following asset file we are mapping in the tmx file, and then we define the layers of the map.
For each layer we map it to the Tmx layer name, and then we can define some custom properties. You can specify the layer number that layer should use in the scene (for sorted rendering, etc), as well as if the
layer should render at all. For our "Collisions" layer we are turning rendering off since it's just used as a data layer. You can also turn object use off for a layer, which is useful if you bound tags to real tiles
on a collision layer, but you don't want your rendering layers to pull in those tags. After that, the tile tags are setup based on the tag names we defined in the TMX file.
Here we are using 3 different tags, and each tag is creating one SceneObject with a polygon collision shape. You can specify as many SceneObjects as you want, or any derived SceneObject that can be deserialized via TAML.
The scene layer, position, and size will be override and set to match the tile that it's linked against in the grid. All other properties are allowed. It's important to remember that a collision body can be larger then the
object size, and because of this you can design your maps to use as few sceneobject/collision bodies as needed. Even in this test map, we can cull out several collision tiles and just expand the collision body.
<TmxMapAsset
AssetName="testmap"
MapFile="pd_tilemap.tmx">
<TmxMapAsset.Layers>
<Layer Name="Wall" Layer="14" Render="true" useObjects="true" ></Layer>
<Layer Name="Floor" Layer="15" Render="true" useObjects="true" ></Layer>
<Layer Name="Collisions" Layer="13" Render="false" useObjects="true"></Layer>
</TmxMapAsset.Layers>
<TmxMapAsset.Tiles>
<Tile Tag="3x3Collision" >
<SceneObject TamlId="1" BodyType="Static">
<SceneObject.CollisionShapes>
<Polygon>
<Point>-3.5 -0.5</Point>
<Point>3.5 -0.5</Point>
<Point>-3.5 0.5</Point>
<Point>3.5 0.5</Point>
</Polygon>
</SceneObject.CollisionShapes>
</SceneObject>
</Tile>
<Tile Tag="1x1Collision" >
<SceneObject TamlId="1" BodyType="Static">
<SceneObject.CollisionShapes>
<Polygon>
<Point>-1.5 -0.5</Point>
<Point>1.5 -0.5</Point>
<Point>-1.5 0.5</Point>
<Point>1.5 0.5</Point>
</Polygon>
</SceneObject.CollisionShapes>
</SceneObject>
</Tile>
<Tile Tag="1x1VertCollision" >
<SceneObject TamlId="1" BodyType="Static">
<SceneObject.CollisionShapes>
<Polygon>
<Point>-0.5 -1.5</Point>
<Point>0.5 -1.5</Point>
<Point>-0.5 1.5</Point>
<Point>0.5 1.5</Point>
</Polygon>
</SceneObject.CollisionShapes>
</SceneObject>
</Tile>
</TmxMapAsset.Tiles>
</TmxMapAsset>The only step left now is to load this up in T2D MIT
%mapSprite = new TmxMapSprite()
{
Map = "ToyAssets:testmap";
};
SandboxScene.add( %mapSprite );Easy right? Under the hood that will generate a CompositeSprite for each map layer, put them on the correct scene layers, and will spawn all the SceneObjects linked by tags in the correct locations as well. The entire map is anchored to the TmxMapSprite, so you can position it anywhere in the scene.
Here's a quick video of this map rendering in the sandbox. I even added an animated sprite in the level and threw it against a collision to get it bouncing around.
I have a work in progress branch at my GitHub repo: github.com/whilke/Torque2D/tree/feature/tmx_maps
About the author
#2
Those are your basic issues with trying to move away from a standard 2d view.
After that you just have to understand that the box2d physics is only in two planes.
02/28/2013 (4:30 pm)
Sure can. T2D is pretty robust with it's inter-layer render sorting. Mix that with the basic layer order rendering, and you can support most views with any type of custom occlusion. Those are your basic issues with trying to move away from a standard 2d view.
After that you just have to understand that the box2d physics is only in two planes.
#3
03/01/2013 (12:10 am)
Awesome work William and a great job presenting it as well, you've certainly took the bull by the horns here!
#4
03/01/2013 (8:01 am)
Great idea. As soon as I heard T2D MIT would have no editors I thought of TMX!
#5
Can't shake the feeling that the level colors remind me of Space Quest 1's opening spaceship.
03/01/2013 (9:31 am)
Good work, William! Way to show initiative!Can't shake the feeling that the level colors remind me of Space Quest 1's opening spaceship.

Torque Owner Demolishun
DemolishunConsulting Rocks!