What if Tiled or any of the other supported editors do not suit your needs? After all, they are all based on tiles and not all games use the same approach for their levels. Take the popular game Braid, for example, where levels are made of nonsquare images. You might want to use a different tool to edit levels or even roll out your own editor!
Luckily enough, Libgdx's 2D maps API is fully extensible. That is the beauty of this framework: simple, clean, and extensible. It does not impose a single way of doing things.
Throughout this recipe, you will learn how to easily add full support for bespoke level formats.
This recipe does not come with a code sample, so you do not need to prepare anything special before carrying on. Nevertheless, it is highly advisable that you understand all the concepts previously explained in this chapter.
Let's say you want to use an editor that is currently not supported by Libgdx. You will have to write your own MapLoader
and MapRenderer
implementations.
Let's cover level loading now. Pay attention to the features your editor supports and how the export format works. Once that is clear, ask yourself the following question: can I support everything I need with the built-in map classes?
The documentation for the maps
package in Libgdx can be found by visiting http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/maps/package-frame.html.
If the answer is no, then you need to extend them and add new ones when necessary.
Now, imagine we have a custom-level editor we want to support in our Libgdx game. We create a CustomMap
class that extends Map
. You can add whatever Map
is missing to support all the features your editor offers:
public class CustomMap extends Map { ... }
We need a CustomMapLoader
class that can give us CustomMap
instances from FileHandle
. It would also be nice to support AssetLoader
for nice asynchrony and reference counting, so we will make it extend the AssynchronousAssetLoader
class. For more details about asset handling, please refer to Chapter 7, Asset Management:
public class CustomMapLoader extends AsynchronousAssetLoader<CustomMap, CustomMapLoader.Parameter> { public static class Parameter extends AssetLoaderParameters<CustomMap> { ... } public CustomMapLoader(FileHandleResolver resolver) { super(resolver); } public CustomMap load (String fileName, Gleed2DMapLoader.Parameters parameters) { ... } @Override public void loadAsync(AssetManager manager, String fileName, FileHandle file, Parameters parameter) { ... } @Override public CustomMap loadSync(AssetManager manager, String fileName, FileHandle file, Parameters parameter) { ... } @Override public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, Parameters parameter) { ... } }
Finally, we need to tell our AssetManager
class that CustomMapLoader
is the one responsible for dealing with CustomMap
objects:
assetManager.setLoader(CustomMap.class, new CustomMapLoader(new InternalFileHandle));
Obviously, the actual loading of the level will depend on the format you are dealing with. Do not fear to dive into other Libgdx loaders at https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/maps/tiled/TmxMapLoader.java to learn from them.
Great! You have your fantastic level loader and you are wondering how to get it on the screen. Add a CustomMapRenderer
class that implements the MapRenderer
interface.
The setView()
method is typically used to set the SpriteBatch
projection matrix. This will determine which parts of the map are going to be visible on the screen. It has two versions: one takes a camera while the other takes a projection matrix and the view bounds.
Override the render()
method to draw all the visible layers by iterating through all their entities. It can take an optional array of layer indices that will determine the layers that will be rendered as well as the order in which that will happen. The code is as follows:
public class CustomMapRenderer implements MapRenderer { public CustomMapRenderer(CustomMap map) { ... } @Override public void setView(OrthographicCamera camera) { ... } @Override public void setView(Matrix4 projectionMatrix, float viewboundsX, float viewboundsY, float viewboundsWidth, float viewboundsHeight) { ... } @Override public void render() { ... } @Override public void render(int[] layers) { ... } }
Keep in mind that you will have to be careful in order to make rendering fast enough. Something you should always try to achieve is to only render what is on screen. Do not try to draw all the objects in every layer every single frame, for that is absolute madness! Study other renderers at https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/maps/tiled/renderers/OrthogonalTiledMapRenderer.java to see how they are implemented.
Brilliant! You just added full support to a new level format to Libgdx. Consider contributing back to the community!
Here are a few options you might want to consider:
18.188.131.255