Flame Tiled: Batch caching by image name leads to incorrect painting.
Current bug behaviour
Tiled maps multiple images (either multiple atlases, or multiple single-sourced images) will not render correctly in staggered modes. It may not operate correctly in other modes as well.
Expected behaviour
Maps that match what Tiled renders.
Steps to reproduce
- Create a tiled map (isometric, staggered, x-asis, even or odd).
- Use multiple, oversized images for the tileset (for overlapping). a. A good CC-0 set: kenny.nl
- Place images such that the overlap.
More information
What Flame does today is optimized for batch rendering (performance), but that means map authors need to know about the limitations. A quick rundown of what happens:
-
flame_tiledcreates aSpriteBatchfor every image in the tiled map. Images can be N*(Atlas||Single Image). - These batches are stored in a map keyed on the source file name (
_cachedSpriteBatches) - While sweeping each layer, and then sweeping each row, and then sweeping each tile in the row, the batch is looked up.
- "cache tiles": transforms generated from the layer->row->tile are stored for each image, not for each tile (
batch.addTransform) - render loop: walk over all visible layers. walk over all cached batches (remember: this is image keys, not tile keyed). call sprite batch render.
What could be done about it?
- You tell everyone in documentation and perhaps runtime warning: don't use multiple images/atlases when generating tiled maps.
- We could collapse every image into an image atlas on load and have only one atlas to draw from for every layer.
- Convert RenderableTileMap to not actual render - just do all the parallax / shifting / tile layout. Leave the render step to another class that flips between sprite batching or sprite painting depending on map conditions.
Option 1 seems harsh, but not uncommon - its an optimization build step. Option 2 could lead to increased load times, higher memory usage - flips could double that if incorrectly handled. 2D-rect-bin packing is NP-hard. Option 3 could be a bit of work, but also might lead to easier to animate tiles, or positioning players on the maps.
The goal is to go from randomly having this:

To having this:

Which is achievable with option 1 for now.
wssy on discord also suggested dynamically creating new batches could also be a solution.
Generating a single Atlas from all the images in a layer works and appears performant. I know the Atlas is made one per layer - further optimizations would be to make one and only one Atlas for the map.
