butano-ldtk
butano-ldtk is a LDtk level importer for the Butano engine.
Parallax level bgs example | Typical 2d platformer example |
---|---|
![]() | ![]() |
Features
- Render LDtk levels as GBA backgrounds with only one line of C++ code.
- Access almost all datas in the LDtk JSON as
constexpr
objects.- IntGrids, Entities, Enums, Level fields, ... anything useful is imported.
- Provides usage examples and API documentation.
Getting started
Prerequisites
Setup
- Clone (or download) this repo to your desired location.
git clone https://github.com/copyrat90/butano-ldtk.git
Install Python dependencies (Pillow).
cd /path/to/butano-ldtk pip install -r requirements.txt
- Edit the
Makefile
of your own project.Add
BUILDLDTK
andLIBBUTANOLDTK
right below theLIBBUTANO
.BUILD := build LIBBUTANO := /path/to/butano/butano + BUILDLDTK := build_ldtk + LIBBUTANOLDTK := /path/to/butano-ldtk
Add butano-ldtk folders (including will-be-generated ones) to your
SOURCES
,INCLUDES
andGRAPHICS
.- SOURCES := src - INCLUDES := include + SOURCES := src $(LIBBUTANOLDTK)/src $(BUILDLDTK)/src + INCLUDES := include $(LIBBUTANOLDTK)/include $(BUILDLDTK)/include DATA := - GRAPHICS := graphics + GRAPHICS := graphics $(BUILDLDTK)/graphics
- Add python script execution to convert your
*.ldtk
project file.- EXTTOOL := + EXTTOOL := @$(PYTHON) -B $(LIBBUTANOLDTK)/tools/butano_ldtk.py --input=/path/to/your_project.ldtk --build=$(BUILDLDTK)
- This will convert
your_project.ldtk
to every time you runmake -j$(nproc)
.
- This will convert
Add
$(BUILDLDTK)
toUSERBUILD
- USERBUILD := + USERBUILD := $(BUILDLDTK)
- If not sure, you can take a look at any of the examples' Makefile.
- Run
make -j$(nproc)
to see if your project builds.
Basic usage
You can create a level as GBA backgrounds with this:
// DO NOT use angular brackets <> for butano-ldtk headers! #include "ldtk_core.h" #include "ldtk_level.h" #include "ldtk_project.h" #include "ldtk_level_bgs_ptr.h" // These are all the generated header files you might want to include #include "ldtk_gen_project.h" #include "ldtk_gen_enums.h" #include "ldtk_gen_idents.h" #include "ldtk_gen_iids.h" #include "ldtk_gen_tags.h" #include <bn_core.h> int main() { bn::core::init(); // Initializes butano-ldtk, this should be after `bn::core::init();` ldtk::core::init(); // Locate the constexpr `gen_project` instance. // // This corresponds to the "root" of LDtk JSON. // With its member functions, you can access most of datas. constexpr const ldtk::project& gen_project = ldtk::gen::gen_project; // Get the level with its identifier. // (Assuming your project has a level named "level_0") constexpr const ldtk::level& level_0 = gen_project.get_level(ldtk::gen::level_ident::level_0); // Create a `ldtk::level_bgs_ptr` with the level. // // Internally, each layer with visible tiles would create one `bn::regular_bg_ptr` ldtk::level_bgs_ptr level_0_bgs = level_0.create_bgs(); while (true) bn::core::update(); }
Build examples
You might want to take a look at examples/
directory for more sophisticated examples than above.
To build those examples, you need to do either:
- Put the
butano-ldtk/
library folder alongsidebutano/
library folder. - Edit each
Makefile
of the examples, so thatLIBBUTANO :=
correctly points tobutano/
library folder.
Going further
You can read the API documentation to figure out the API that's not covered in the examples.
If you have questions, you can go to the GitHub Discussions or find me in the gbadev Discord server.
Notes
Limitations
butano-ldtk requires your LDtk project to use
Full lowercase
identifier convention.
You can set it on your project settings.
- Parallax scaling of layers is not supported.
If you set a parallax value, you need to uncheck the
[ ] Scale ?
box.
- Importing external enum files is not supported.
- Some field types are not supported:
- File path
- Tile
- Tile size that's not multiple of 8px is not supported.
- This is because GBA hardware tiles are 8×8.
- Tiles not aligned to the grid are not supported.
- Tile stacking in the same layer is not supported.
- If you have 2 or more tiles stacked in the same layer, tiles other than the top one is discarded.
This might result in visual artifacts.
- If you have 2 or more tiles stacked in the same layer, tiles other than the top one is discarded.
- Different layer opacity values are not supported.
- This is because GBA only supports one global BG transparency alpha.
- If you have more than 4 layers with visible tiles, the converter will error out.
- This is because GBA only supports 4 regular BGs visible.
- You can have many layers without a visible tile, that won't create regular BG.
- Metadatas associated with LDtk Enums are not imported.
- This is because enums are directly converted to C++ enums.
- Unused tiles in the tilesets are not imported.
Caveats
- LDtk 1.5.3 has a bug that when you update the definitions of layers, entities, etc, it is not propagated properly to all the instances.
When this happens, unexpected results might happen.- To avoid this, when you make any changes to the definitions, do this:
- Change the identifier convention to
Full uppercase
temporarily. - Save the project.
- Change it back to
Full lowercase
- Save the project again.
- Change the identifier convention to
- To avoid this, when you make any changes to the definitions, do this:
- Identifiers, IIDs, tags are converted as enum values.
- The identifiers of those enum values are mostly same as LDtk's, but there are exceptions:
Level fields & entity fields are converted like this:
ldtk::gen::level_field_ident::LEVEL_level_name_FIELD_field_name ldtk::gen::entity_field_ident::ENTITY_entity_name_FIELD_field_name
Layer int grid values & int grid value groups are converted like this:
ldtk::gen::layer_int_grid_value_ident::LAYER_layer_name_INT_GRID_VALUE_value_name ldtk::gen::layer_int_grid_value_group_ident::LAYER_layer_name_INT_GRID_VALUE_GROUP_group_name
- IIDs are prefixed with single underscore
_
. Also,-
is replace with_
too:cpp // 6abe6740-7820-11ed-b9f3-df5bd7818ec4 ldtk::gen::entity_iid::_6abe6740_7820_11ed_b9f3_df5bd7818ec4
- The identifiers of those enum values are mostly same as LDtk's, but there are exceptions:
- While the layer opacity value enables the blending of the BG of that layer,
the global transparency alpha value itself is not touched.- This is because you might be controlling the transparency alpha value elsewhere.
To apply the transparency, you can simply do this:
#include "ldtk_gen_project.h" #include <bn_blending.h> ... bn::blending::set_transparency_alpha(ldtk::gen::gen_project.opacity());
ldtk::entity_ref
is differ from theEntityReferenceInfos
in the LDtk JSON specsldtk::
uses level & layer identifiers other than IIDs to turn the O(N) search cost into O(1) lookup.entity_ref - This means that you need to take both the level & layer identifiers to uniquely distinguish a layer instance of a level.
Others
- DO NOT access anything named with
priv
directly.- Those are private headers that might be changed in the future.
So, always access members starting fromldtk::gen::gen_project
member functions.
- Those are private headers that might be changed in the future.
Licenses
Source codes
Directly included sources
butano-ldtk is licensed under the zlib license, mostly.
Those source codes have SPDX license identifiers on top.
There are few parts I don't write myself, which is licensed differently:
tools/LdtkJson.py
- Generated with quicktype with LDtk JSON schema file.
- I believe this one should use the same license as LDtk's MIT license?
src/bn_top_left_utils.h
- Copied from Butano, which is licensed under the zlib license.
src/ldtk_div_utils.h
- Copied from this stackoverflow answer, license unknown.
There are few parts I borrowed ideas from Butano:
include/ldtk_level_bgs_ptr.h
&src/ldtk_level_bgs_ptr.cpp.h
- Borrowed ideas from
bn::regular_bg_ptr
- Borrowed ideas from
include/ldtk_level_bgs_builder.h
&src/ldtk_level_bgs_builder.cpp.h
- Borrowed ideas from
bn::regular_bg_builder
- Borrowed ideas from
src/ldtk_level_bgs_manager.h
&src/ldtk_level_bgs_manager.cpp
- Borrowed ideas from
bn::bgs_manager
- Borrowed ideas from
Indirectly used third-party programs
- Butano is licensed under the zlib license.
- LDtk is licensed under the MIT license.
- Pillow is licensed under the MIT-CMU license.
API Documentation
API Documentation is generated via Doxygen, which is licensed under the GNU GPL v2.
m.css Doxygen C++ theme is licensed under the MIT license.
Assets
License files of the graphics used for examples can be found in each example folders. (examples/*/licenses/
)
For now, all of them are CC0 1.0 Universal.