Transparency Masking TileMapLayer tiles (Clipping?)

Godot Version

4.5

Question

I’m doing a top down game and want to slowly break the tiles stepped on to show the animated gif below the tiles. In most engines I can throw a mask on an object so the alpha takes out part of the texture and change the mask as more ‘damage’ is done. I’ve seen how to manually setup clipping for normal objects, but obviously I need to do this via code and to a TileMapLayer made object. Can I not have nice things and have to avoid TileMapLayer and just make my own tile system?





If you’re only using TileSetAtlasSource (and not TileSetScenesCollectionSource), you can use what’s called “alternative tiles” for the different damage levels:

  • Write some mask shader like normal, for example:
shader_type canvas_item;

uniform sampler2D mask;

void fragment() {
    COLOR *= texture(mask, UV);
}
  • For each tile, create one alternative tile per damage level (create_alternative_tile)
  • Attach the shader to all the TileDatas (get with get_tile_data) and set uniform sampler2D mask to the mask corresponding to their damage levels
  • Now you can set the damage of a tile by setting its alternative tile (using the last parameter of set_cell): tile_map_layer.set_cell(coords, source_id, atlas_coords, damage_level)
An example
# Tile as an example class containing atlas coords
for tile: Tile in tiles:
    for i in range(DAMAGE_STEPS):
        # we start at 1 because there is already an alternative tile '0' by default
        if i >= 1:
            tile_set_atlas_source.create_alternative_tile(tile.atlas_coords, i)

        var tile_data: TileData = tile_set_atlas_source.get_tile_data(tile.atlas_coords, i)
        if tile_data == null:
            push_error("Failed to get tile data of tile at %s for alternative tile %d" % [str(tile.atlas_coords), i])
            return

        var shader_material := ShaderMaterial.new()
        shader_material.shader = shader
        shader_material.set_shader_uniform("mask", masks[i])

        tile_data.material = shader_material

This is all assuming you’re creating the tiles in code, if not I don’t know how one would do it, sorry :confused:

Oh, yes. That seems perfect. I probably won’t get to try it out until Wednesday, but it looks exactly like what I was hoping for. Thanks! I’ll respond when I try it out!