Skip to content

feat!: Upgrade flame_tiled to tiled 0.12.0 - #4073

Merged
spydon merged 1 commit into
mainfrom
feat/flame-tiled-tiled-0.12
Sep 30, 2026
Merged

spydon merged 1 commit into
mainfrom
feat/flame-tiled-tiled-0.12

Conversation

@ufrshubham

@ufrshubham ufrshubham commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Description

Upgrades flame_tiled from tiled 0.11.0 to 0.12.0.

0.12.0 has the new TileLayer tile access APIs (tileAt, setTileAt, forEachTile,
contentBounds), which infinite map support needs. That support is in #4074, which is stacked on
this PR. This PR only does the upgrade, so the breaking part can be reviewed on its own.

The breaking change in 0.12.0 comes from flame-engine/tiled.dart#72: external tilesets and
templates are now resolved through ParserProvider instead of TsxProvider, and
TileMapParser is gone. flame_tiled re-exports package:tiled/tiled.dart, so this reaches
Flame users directly.

Changes:

  • Loading external files: RenderableTiledMap.fromString passes a loader to the new async
    TiledMap.fromString. tiled calls it with the path of every external file the map references,
    relative to the map, and the loader reads it from the asset bundle. Before, flame_tiled had to
    create a TsxProvider per tileset. External object templates (.tx) now load through the same
    path, not only tilesets.
  • FlameTsxProvider: now implements ParserProvider instead of the removed TsxProvider, so
    it can still be passed to TiledMap.parseTmx/parseJson for a preloaded tileset. parse,
    filename, data, getSource and getCachedSource are still there.
  • Dependencies:
    • flame_tiled no longer depends on xml directly. It was only used to build an XmlParser,
      and Parser.fromString from tiled does that now.
    • flame_kenney_xml now allows xml 7 (>=6.5.0 <8.0.0). tiled 0.12 requires xml: ^7.0.0,
      and the workspace resolves a single version, so without this the workspace doesn't resolve.
      flame_kenney_xml doesn't depend on tiled, and its tests pass on xml 7.0.1.

TiledComponent.load and RenderableTiledMap.fromFile/fromString are used exactly as before.
The existing tests for external tilesets and FlameTsxProvider pass unchanged.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • [-] I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Migration instructions

Nothing changes if you only load maps through TiledComponent.load or RenderableTiledMap. If
you use the tiled parsing APIs that flame_tiled re-exports:

  • TileMapParser.parseTmx(xml, tsxList: [...]) becomes
    TiledMap.parseTmx(xml, providers: [...]), and TileMapParser.parseJson(json) becomes
    TiledMap.parseJson(json).
  • Custom TsxProvider implementations become ParserProvider implementations: implement
    canProvide(path) and getSource(path) instead of filename, getSource(filename) and
    getCachedSource(). The path is relative to the map file.
  • The loader passed to TiledMap.fromString now returns the contents of the requested file
    instead of a TsxProvider:
    TiledMap.fromString(contents, (path) => bundle.loadString('$directory$path')).
  • FlameTsxProvider is no longer a TsxProvider. Pass it through providers: of
    TiledMap.parseTmx/parseJson.

Related Issues

Needed for #2855 and #3932 (infinite map support), which #4074 resolves.

tiled 0.12.0 resolves external tilesets and templates through
ParserProvider and replaces TsxProvider, so flame_tiled is updated to
the new API.

- Load external files through the async TiledMap.fromString loader,
  which is given the path of each referenced file. Object templates are
  resolved through it as well now, not only tilesets.
- FlameTsxProvider implements ParserProvider instead of the removed
  TsxProvider, so it can still be passed to TiledMap.parseTmx and
  TiledMap.parseJson for a preloaded tileset.
- Drop the direct xml dependency from flame_tiled, it is not used
  anymore.
- Allow xml 7 in flame_kenney_xml, since tiled 0.12 requires it and the
  workspace resolves a single version.

BREAKING CHANGE: flame_tiled re-exports tiled 0.12.0, which replaces
TsxProvider with ParserProvider. FlameTsxProvider no longer implements
TsxProvider; it implements ParserProvider instead.
@spydon
spydon merged commit 7109f15 into main Sep 30, 2026
11 checks passed
@spydon
spydon deleted the feat/flame-tiled-tiled-0.12 branch September 30, 2026 19:48
spydon added a commit that referenced this pull request Sep 30, 2026
Stacked on #4073, which upgrades `flame_tiled` to `tiled` 0.12.0.

Adds support for infinite maps from the Tiled editor.

Until now, loading an infinite map crashed with a null check error.
Infinite maps don't have a
single `tileData` grid. Tiled stores their tiles in chunks, usually
16×16, placed at any tile
coordinate, including negative ones when you paint left of or above the
origin. `flame_tiled`
assumed a `width × height` grid starting at `(0, 0)` everywhere:
`cacheTiles()` started with
`layer.tileData!`, and cached transforms were indexed as
`transforms[x][y]`.

This PR builds on the new `TileLayer` tile access APIs from
flame-engine/tiled.dart#94
(`contentBounds`, `tileAt`, `setTileAt`, `forEachTile`), which work the
same way for finite and
infinite layers.

**Tile layers** (`FlameTileLayer` and the four orientation layers):

- The transform cache now covers the layer's `contentBounds`: `(0, 0,
width, height)` for finite
layers, and the area covered by all chunks for infinite ones. Transforms
are stored relative to
that area's top-left corner (`originX`/`originY`), so negative
coordinates work. `transformAt`
and `storeTransform` do the offset, so nothing indexes the cache
directly anymore.
- Tiles are painted in row order: rows sorted by `y`, each row sorted by
`x`, through
`tilesByWorldRow()`. This matters because infinite layers store tiles
chunk by chunk. Painting
them in that order would draw all of one chunk before the first row of
the chunk next to it.
Tiles that overlap their neighbours (isometric, staggered, hexagonal and
oversized tiles) would
then stack wrongly along chunk borders. Finite maps are visited in the
same order as before, so
  they render exactly the same.

**`RenderableTiledMap`:**

- `getTileData`/`setTileData` (and the `ByLayerIndex` variants) use
`TileLayer.tileAt`/
`setTileAt`. They take the tile coordinates shown in the Tiled editor,
so negative coordinates
work on infinite maps. For cells outside the map (or outside every
chunk), `getTileData` returns
`null` and `setTileData` does nothing. Before, both threw a `RangeError`
for cells outside a
  finite map.
- `tileStack` uses `transformAt`, so it also works at negative
coordinates.

**Current limitations** (also documented in `tiled.md`):

- All chunks in the file are cached at load time. Streaming chunks based
on the camera isn't
  implemented yet.
- `TiledComponent`'s size still comes from the map's `width` and
`height`, so tiles at negative
  coordinates render outside the component's bounds.
- `setTileData` can't create new chunks.

**Tests:**

- Loading an empty infinite map, and reading, writing and `tileStack` at
negative coordinates.
- Three goldens, rendered with a new `renderMapRegionToPng` helper that
can capture negative
  coordinates:
- `infinite_map.png`: a whole infinite map, with two layers across six
chunks.
- `infinite_oversized_tiles_orthogonal.png`: a dungeon room across the
chunk border at `x = 0`,
with a 32×32 door standing in front of the top wall, so its frame
overlaps the walls of both
chunks. I checked that this golden fails if tiles are painted chunk by
chunk: the wall of the
    right chunk then covers half the door.
- `infinite_oversized_tiles_isometric.png`: an isometric scene across
the four chunks around the
    origin.

---------

Co-authored-by: Lukas Klingsbo <me@lukas.fyi>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants