Search code examples
javadictionarylibgdxrendertiled

(LIBGDX) Rendering Sprite (character) hides a Wall


I'm making a game with Libgdx and I'm using isometric perspective. I have a problem when rendering my character because the map is loaded from Tiled Map Editor and character is a Sprite.

If I have a wall on layer 0 of the map, when drawing the wall before the Sprite, if the sprite is behind the wall, we will see the Sprite instead of wall (we should see the wall), if rendering the Sprite first, we will see the wall instead of the Sprite when the sprite is in front of the wall (we should see the Sprite). Any idea about fixing this?


Solution

  • I haven't really worked with tiled maps, but I think it goes something like this.

    First, in TileEd, create an object layer that will be used for your character sprite. So the layer should be between background stuff and stuff that should obscure your player. Name it something like "characters".

    Then, create a MapObject subclass that can render a sprite. Something like this:

    public class SpriteMapObject extends MapObject {
    
        private Sprite sprite;
    
        public SpriteMapObject (Sprite sprite) {
            this.sprite = sprite;
        }
    
        @Override
        public Color getColor () {
            return sprite.getColor();
        }
    
        @Override
        public void setColor(Color color){
            sprite.setColor(color);
        }
    
        public void render(Batch batch){
            Color spriteColor = sprite.getColor();
            float originalAlpha = spriteColor.a;
            spriteColor.a *= getOpacity();
            sprite.draw(batch);
            spriteColor.a = originalAlpha;
        }
    }
    

    Now after you load your map and your sprite, you can put the sprite on that layer you prepared:

    map.getLayers().get("characters").add(new SpriteMapObject(playerSprite));
    

    You also need to subclass the map renderer so it will render the sprite for you. Use your subclassed version instead of the original. For instance:

    public class SpritesOrthogonalTiledMapRenderer extends OrthogonalTiledMapRenderer {
    
        //Override whichever constructor(s) you need
        public SpritesOrthogonalTiledMapRenderer (TiledMap map, Batch batch) {
            super(map, batch);
        }
    
        @Override
        public void renderObject(MapObject object) {
            super.renderObject(object);
            if(object instanceof SpriteMapObject) {
                ((SpriteMapObject) object).render(batch);
            }
        }
    }
    

    That's the basics of how it works. But if you want your player to be able to be in front or behind of a wall like you described, then you will need to create multiple extra layers, and move your sprite object to different layers when necessary.

    Looks to me like Libgdx could use a feature enhancement to OrthogonalTiledMapRenderer so it can draw objects automatically merged into a TileLayer and inserting them into the draw order based on row.