Tiled P1 — core orthogonal load: rt_tmap model, GID resolver, render #69

Closed
opened 2026-09-01 12:29:25 +02:00 by orkun · 1 comment
Owner

Follow-up P1 of the Tiled design (#66). Design record: Design: Tiled maps §2.

Scope — core orthogonal load + render

The heart of the feature. Introduce the richer model and draw it.

  • rt_tmap model (design §2): map header + ordered layers (dense int32 GID arrays) + tilesets. Heap-allocated to w·h; lifts the 96×64 cap.
  • Tileset + GID resolver: gid → (tileset, localId, flipH, flipV, flipD); flip flags (0x80000000/0x40000000/0x20000000) masked off before local-id lookup, returned alongside (design §3.3). gid==0 = empty.
  • Compatibility projection: project a designated collision layer down to the legacy rt_map/rt_tile byte grid so Grid.*/Path.*/esys_move keep working unchanged; old code stays byte-identical.
  • Tiled.* namespace (Tiled.load, Tiled.gid, Tiled.resolve, Tiled.draw), spliced on demand like Regex.*/Grid.*.
  • Render finite CSV/base64/base64+zlib tile layers in file order through the existing renderer, applying flips at draw.
  • Replace the hand-authored string rows in the grid and physics_tiles demos with a loaded map.

Golden fixtures

Kenney sampleMap.tmx (via #68) and its TMJ export (via #67 JSON path).

Acceptance

  • Kenney sample loads and renders identically from both .tmx and .tmj.
  • Flipped tiles draw with the correct orientation.
  • grid/physics_tiles demos run off the loaded map with unchanged Grid.*/esys_move behaviour.

Depends on #67, #68. Blocks P2/P3.

Follow-up P1 of the Tiled design (#66). Design record: [Design: Tiled maps](https://git.workshopsoft.io/workshopsoft/ludic/wiki/Design%2FTiled) §2. ## Scope — core orthogonal load + render The heart of the feature. Introduce the richer model and draw it. - **`rt_tmap`** model (design §2): map header + ordered layers (dense `int32` GID arrays) + tilesets. Heap-allocated to `w·h`; lifts the `96×64` cap. - **Tileset + GID resolver**: `gid → (tileset, localId, flipH, flipV, flipD)`; flip flags (`0x80000000`/`0x40000000`/`0x20000000`) masked off before local-id lookup, returned alongside (design §3.3). `gid==0` = empty. - **Compatibility projection**: project a designated collision layer down to the legacy `rt_map`/`rt_tile` byte grid so `Grid.*`/`Path.*`/`esys_move` keep working unchanged; old code stays byte-identical. - **`Tiled.*` namespace** (`Tiled.load`, `Tiled.gid`, `Tiled.resolve`, `Tiled.draw`), spliced on demand like `Regex.*`/`Grid.*`. - **Render** finite CSV/base64/base64+zlib tile layers in file order through the existing renderer, applying flips at draw. - Replace the hand-authored string rows in the `grid` and `physics_tiles` demos with a loaded map. ## Golden fixtures Kenney `sampleMap.tmx` (via #68) and its TMJ export (via #67 JSON path). ## Acceptance - [ ] Kenney sample loads and renders identically from both `.tmx` and `.tmj`. - [ ] Flipped tiles draw with the correct orientation. - [ ] `grid`/`physics_tiles` demos run off the loaded map with unchanged `Grid.*`/`esys_move` behaviour. Depends on #67, #68. Blocks P2/P3.
orkun added the
area:stdlib
area:rendering
labels 2026-09-01 12:29:25 +02:00
Author
Owner

P1 landed in main (bc301c8) — the heart of the feature: load a map and draw it.

  • rt_tmap model (Tmap/TmLayer/TmTileset): map header + ordered layers (dense int32 GID arrays, heap-allocated to w·h, lifting the old 96×64 cap) + tilesets. Built from the P0.5 intermediate tree, so TMX and TMJ both feed it.
  • GID resolver (Tiled.resolve): gid → (tileset, localId, fh/fv/fd); the three flip flags (0x80000000/0x40000000/0x20000000) masked off before the local-id lookup and returned alongside. gid==0 = empty.
  • Render (Tiled.draw): every visible tile layer in file order, blitting each tile from its tileset image with flips applied at draw.
  • Compatibility projection (Tiled.project, auto on load): a designated collision layer projects to the legacy byte tilemap — '#' solid, '=' one-way (via the oneway property), space empty — so Grid.*/Path.*/esys_move are byte-identical.
  • Tiled.load reads either format, resolves external tilesets + images relative to the map file, and auto-projects a collision/solids/walls layer.

Acceptance

  • Kenney sample loads and renders identically from both .tmx and .tmj — tiled_p1.ludic draws each to the framebuffer and hashes it: byte-identical.
  • Flipped tiles draw with the correct orientation — an asymmetric tile drawn normal vs. H-flipped mirrors pixel-for-pixel.
  • grid/physics_tiles demos run off the loaded map with unchanged Grid.*/esys_move behaviour — both converted to Tiled.load (grid_maze.tmx, physics_map.tmx), output byte-identical.

Two compiler fixes fell out of this: emit_index_addr set g_addr_ty before evaluating the index, so slice[obj.field] came back mis-typed (fixed: set it last, like the raw-pointer branches); and @strcmp was declared by both the world table and the fs prelude (centralised in the head prelude) so a game using Fs/Path links.

x test: 92 passed; self-host bootstrap fixpoint intact. Unblocks P2/P3. Proven by examples/library/tiled_p1.ludic (14 assertions).

**P1 landed** in `main` (bc301c8) — the heart of the feature: load a map and draw it. - **`rt_tmap` model** (`Tmap`/`TmLayer`/`TmTileset`): map header + ordered layers (dense `int32` GID arrays, **heap-allocated to `w·h`**, lifting the old `96×64` cap) + tilesets. Built from the P0.5 intermediate tree, so TMX and TMJ both feed it. - **GID resolver** (`Tiled.resolve`): `gid → (tileset, localId, fh/fv/fd)`; the three flip flags (`0x80000000`/`0x40000000`/`0x20000000`) masked off before the local-id lookup and returned alongside. `gid==0` = empty. - **Render** (`Tiled.draw`): every visible tile layer in file order, blitting each tile from its tileset image with flips applied at draw. - **Compatibility projection** (`Tiled.project`, auto on load): a designated collision layer projects to the legacy byte tilemap — `'#'` solid, `'='` one-way (via the `oneway` property), space empty — so `Grid.*`/`Path.*`/`esys_move` are byte-identical. - **`Tiled.load`** reads either format, resolves external tilesets + images relative to the map file, and auto-projects a `collision`/`solids`/`walls` layer. ### Acceptance - [x] Kenney sample loads and renders identically from both `.tmx` and `.tmj` — `tiled_p1.ludic` draws each to the framebuffer and hashes it: byte-identical. - [x] Flipped tiles draw with the correct orientation — an asymmetric tile drawn normal vs. H-flipped mirrors pixel-for-pixel. - [x] `grid`/`physics_tiles` demos run off the loaded map with unchanged `Grid.*`/`esys_move` behaviour — both converted to `Tiled.load` (`grid_maze.tmx`, `physics_map.tmx`), output byte-identical. Two compiler fixes fell out of this: `emit_index_addr` set `g_addr_ty` before evaluating the index, so `slice[obj.field]` came back mis-typed (fixed: set it last, like the raw-pointer branches); and `@strcmp` was declared by both the world table and the fs prelude (centralised in the head prelude) so a game using `Fs`/`Path` links. `x test`: 92 passed; self-host bootstrap fixpoint intact. Unblocks P2/P3. Proven by `examples/library/tiled_p1.ludic` (14 assertions).
orkun closed this issue 2026-09-01 13:43:47 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: workshopsoft/ludic#69
No description provided.