LittleKt supports loading and rendering a Tiled map. It currently only supports the .tmj
/ .json
files. The XML .tmx
is not supported.
Loading
A Tiled map can be loaded using the resourcesVfs
file by using the readTiledMap()
extension. This returns an TiledMap
which can be used to access the maps layers, objects, tilesets, and render it.
We can also pass in our own TextureAtlas
to attempt to save on draw calls when the TiledMap
is loaded.
val tiledMap: TiledMap = resourcesVfs["tiled/my-ortho-map.tmj"].readTiledMap()
Using a TextureAtlas
As mentioned above, we can pass in a TextureAtlas
which the internal TiledMapLoader
will use, if available, to create the TiledTileSet
objects from.
Two things we must do for this to work correctly:
- Load a
TextureAtlas
that contains all of the tileset images and image backgrounds used in LDtk. This can be created strategically so that all the images used for each level are on a single texture. We could also load eachTexture
individually and use aMutableTextureAtlas
to combine them at runtime. - Ensure that the names of each invidiual texture that is packed into the atlas matches the filename with extension of the image being loaded. For example, if we have a tileset image in the directly
tiled/my_tileset.png
. We would ensure that in theTextureAtlas
it has the name ofmy_tileset.png
. No directory path.
Rendering
There are multiple ways to render the LDtk map.
- Render the entire map at once
- Render specific layers of a level of the map.
Render the entire map at once
If the map needs to be rendered entirely at one time, the TiledMap
class offers a render method that can do just that.
val batch = SpriteBatch(context)
val camera = OrthographicCamera(context.graphics.width, context.graphics.height)
batch.use(renderPass, camere.viewProjection) {
map.render(it, camera)
}
Render specific layers of a map
One can access specific layers of a map by using the layers
property or the get
operator on the LDtkLevel
object.
val layer = map["MyCustomTilesLayer"]
As with the LDtk map object, rendering the layer is done the same:
val batch = SpriteBatch(context)
val camera = OrthographicCamera(context.graphics.width, context.graphics.height)
batch.use(renderPass, camere.viewProjection) {
layer.render(it, camera)
}
Rendering each layer separately can be advantageous due to being able to render other items of the application on top or below certain layers if needed.
val bgLayer = map["background"]
val foregroundLayer = map["foreground"]
batch.use(renderPass, camere.viewProjection) {
bgLayer.render(it, camera)
player.render(it)
foregroundLayer.render(it, camera)
}
Objects
Tiled offers creating “object layers” which we can use create objects with certain shapes and properties. We can access these objects on these layers and use the properties to do whatever we need, such as instantiating our own Entity class based off it as an example.
We can do that by first grabbing an objects layer from the TiledMap
. We can do that by using either the id
of the layer or the name
of the layer. We then acess objects a similar way on the TiledObjectLayer
by grabbing by id
or name
. We can also grab a list of objects
by passing in a type
.
val mobsLayer = it["mobs"] as TiledObjectLayer
val mobs: List<TiledMap.Object> = mobsLayer.objects
val boss: TiledMap.Object = mobsLayer["BigBoss"]
val health: Int = boss.properties["health"]?.int ?: 100
// our own game related logic using the object data
val bossInstance = BigBoss(boss.x, boss.y, health)
Properties
We can also access objects property values by using the properties
map on the object which returns a Property
type. A Property
contains a few fields for converting the value into the correct type so we can do it instantly without having to manually cast anything. Warning, it will through an a runtime exception if the value cannot be converted to the type, as it would normally. We can use the int
, float
, bool
, and string
properties to convert and return the value we want.
val boss: TiledMap.Object = mobsLayer["BigBoss"]
val healthProp: TiledMap.Property? = boss.properties["health"]
val health: Int = healthProp?.int ?: 100 // converts the prop to an Int
Note: for file, color, and object properties they will be returned as a String
inside the Property
.
Disposing
Disposing of a TiledMap
Once we are finished with the TiledMap
we can call the dispose()
method on the loaded map. This will dispose any of the textures it owns. If a TextureAtlas
was passed in then the loader won’t own any of the textures and therefor won’t dispose of any.
tiledMap.release()