From a0f279a031332bb8aa16c094a8a7990d654aaa48 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Fri, 18 Sep 2026 09:17:49 +0200 Subject: [PATCH] Tilemaps: compact cell storage in the project file, check total 1017 (#134) Co-Authored-By: Claude Opus 5 --- Architecture.md | 2 +- Development.md | 4 ++-- Tilemaps.md | 20 ++++++++++++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Architecture.md b/Architecture.md index 93d40f5..21fe08a 100644 --- a/Architecture.md +++ b/Architecture.md @@ -71,7 +71,7 @@ src/core/graph/ graph model, NodeRegistry/NodeContext/values, interpreter lookup (what a node may look up: behaviors, state machines), keyRepeat; nodes/{events,flow,data,action,variable}/.ts src/core/particles/ nodes (the catalogue), compile (a graph → one function per output), emission (which particles are alive at a second — a pure rule, no state) -src/core/store/ serialize (untrusted JSON → Project), http (one API call), ProjectStore/HttpProjectStore, +src/core/store/ serialize (untrusted JSON → Project), tilemapCells (the compact form of a layer's cells in the file), http (one API call), ProjectStore/HttpProjectStore, FileStore (what the server holds of one kind) + HttpFileStore (one generic client over the three file collections) — TextureStore, FontStore and SoundStore are its type parameters, nothing else src/core/time.ts the global clock: one scaled step a frame, shared by the world, the particles, the shaders and the animation preview diff --git a/Development.md b/Development.md index 42785cd..d734eca 100644 --- a/Development.md +++ b/Development.md @@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs # code is lost (tail's is reported), so a red run reads as green npm run build # writes dist/ and regenerates index.html ./build.sh # the same under `set -o pipefail`, for callers that pipe the output -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1013 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1017 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result @@ -232,4 +232,4 @@ widths to find click points. The **render device is not in this repo** — `/dev and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`, -WebGL 2.0, and the same 1013 checks as here. +WebGL 2.0, and the same 1017 checks as here. diff --git a/Tilemaps.md b/Tilemaps.md index b00acc7..cadefb5 100644 --- a/Tilemaps.md +++ b/Tilemaps.md @@ -67,10 +67,26 @@ tile is on the same step, so animated water does not run out of phase between tw Drawing is done with **one mesh per tile and layer** rather than one sprite per cell, so a map of a thousand cells costs as many draw calls as it has tiles on that layer. +## In the project file + +While you edit, a layer holds its cells as a map from `"x,y"` to a tile. The project file stores +them more compactly (#134): per layer the tiles it uses **once**, the top-left painted cell, and +then **one line per row** as runs of `index*count`. `index` counts from 1 into the tile list, `0` +is an empty cell, and a single cell drops the count: + +```json +"tiles": ["grass", "path"], +"origin": { "x": 0, "y": 0 }, +"rows": ["1*40 0*3 2", "1*44"] +``` + +Cells outside the grid are stored as well, so a map that was made smaller gets them back when it +grows again. Measured: a full map of 100 × 100 cells on two layers went from 736 KB to 11 KB. +**Older projects** still load — their cells are read as they are and written in the new form on +the next save. + ## What it does not do yet - **No collision.** A tilemap is a picture; figures walk through it. Whether it should contribute colliders is a question of its own and is not decided. - Nothing fills an area by flooding it, and there is no picking up a tile off the map. -- The cells are stored one entry per painted cell (`"x,y"` → tile), uncompressed. Big maps - therefore make big project files; the format leaves room to pack them later.