Loading LDtk maps in HaxeFlixel

This tutorial was made assuming you’re using Haxe 4.2, HaxeFlixel 4.9 and LDtk 0.9.3. The instructions may be different for future versions.

After finding LDtk, I fell in love with the editor for its ease of use and customisable pattern-matching auto-tiling rules. What does that mean? Well, it means that you can use an IntGrid layer within LDtk to set a value where a wall or other tile should be on your level, and LDtk will pick the correct tile based on the pattern of tiles around it.

This is pretty addictive; once you get the rules set up for your tiles, it’s satisfying to watch your maps transform as you paint tiles. After all this fun, how do you actually get the levels into HaxeFlixel?

Well, there are two ways. One is to use a JSON parser from LDtk’s JSON output, which is an approach needed for other frameworks like MonoGame but also works in HaxeFlixel if you’re more used to it that way. The other is to use LDtk’s ldtk-haxe-api, which contains helpful code to read the map data into FlxSpriteGroups. This tutorial explains how to use the official API.

Setting up the API

This is the easy part. Follow the instructions at the GitHub page for the API. Make sure you also install deepnightLibs. I’m not sure if you have to also install heaps, but I did anyway.

Include these libraries (except heaps) in your project’s Project.xml file, in the Libraries section, so it looks similar to this:

1
2
3
<haxelib name="flixel" />
<haxelib name="deepnightLibs" />
<haxelib name="ldtk-haxe-api" />

It’s also necessary to add a file to your project’s source folder, called (for example) MyProject.hx, containing the following:

1
2
3
private typedef _Tmp =
    haxe.macro.MacroType<[ ldtk.Project.build("path/to/myProject.ldtk")
]>;

Accessing your map data

First, we need a bit of setup for your project. Create an instance of your project in your code:

1
var project = new LdtkProject();

Now you can access your world’s levels, and thereby your level’s fields and layers. It’s best to have a look at the API’s included samples. Layers are accessed as a member field with the prefix l_; for example, l_myLayer. For now, we can use some basic fields and layers like this:

1
2
3
4
5
6
7
var background:FlxSpriteGroup = new FlxSpriteGroup();
var project = new LdtkProject();
// project.getLevel takes either the level UID or level name
var myLevel = project.getLevel("Level 1");

myLevel.l_background.render(background);
add(background);

In this code we define background as the sprite group to hold the tiles, get the level named “Level 1” from the LDtk project and then load the tiles into the sprite group. After that, do what you like - in this case, we’re adding them straight to the state.

Entities, Enums and Fields

What if we want to use a map object to set where the player should spawn in? If we have an entity layer and an entity named, for example, PlayerStart, you can iterate through all instances of that object in the current map and use it how you like. We can access its fields by using the f_myField property (replacing myField as appropriate). In this example, we can use an enum field to change the player’s colour using the entity’s PlayerColour field; the actual implementation of setColor is up to you.

1
2
3
4
5
// Assuming we have a FlxSprite variable called player
for (p in myLevel.l_Entities.all_PlayerStart) {
    player.setPosition(p.pixelX, p.pixelY);
    player.setColor(p.f_PlayerColour);
}

Level fields

Levels themselves can also have custom fields. This is useful for things like playing a certain music track on your level - a dark, gloomy track for a dungeon or a lively, happy track for a lush field. As before, we can use an enum field; this example uses an enum that has all the possible music tracks.

1
2
3
4
5
6
function playLevelMusic(level:Ldtk_Level) {
    FlxG.sound.playMusic(switch(level.f_MusicTracks) {
        case Overworld: AssetPaths.Overworld__ogg;
        case Dungeon: AssetPaths.Dungeon__ogg;
    });
}

Field types

There are other types that can be used as fields for both levels and entities. They are:

  • Integer
  • Float
  • Boolean
  • String
  • Multi-line string
  • File path
  • Colour (hex value)
  • Enum

What now?

Now you know the basics of how to use your map data. So get making some levels and, more importantly, make the code that uses your levels!