Say what a standing tilemap costs in play (#284)

- Tilemaps: what is cached, that a writer of cells has to call
  cellsChanged, and the measured numbers.
- Development: 1613 editor checks.
admin committed 2026-10-01 09:53:05 +02:00
1 parent ba34f366eb
commit c8cc9cdc2f
2 files changed
+23 -3

No files matched your search

+1 -1
@@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun
# has and the web server's container has not (SKIP there)
php tests/php/snapshots.test.php # the snapshot store (#231), the same way
php tests/php/releases.test.php # the release store (#266), the same way
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1610 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1613 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
+22 -2
@@ -323,8 +323,11 @@ frame. Before, each of them cut every outline into its quarters and pieced every
again, so a map that only stood there cost a frame. Now:
- The tiles of a layer, the blocking cells, their rectangles and polygons are kept per content.
The content is compared cell by cell, not by object, because a stroke paints the cells in place.
A painted cell, a tile switched off Solid, a new outline or a new tile kind is seen at once.
A stroke paints the cells in place, so the object being the same says nothing. Whoever writes
into cells says so with `cellsChanged(cells)`: the brush while a stroke is under way, and
`PaintTilesCommand` on execute and undo. Only then is the content compared cell by cell, and
only a real difference makes a new version. A painted cell, a tile switched off Solid, a new
outline or a new tile kind is seen at once. Code that replaces the cells object needs no word.
- A tile's cut outline is kept per outline list. The model replaces the list instead of editing
it, so the list stands for its corners.
- The same cells hand out the very same rectangles and polygons. The physics tells by that, and by
@@ -335,6 +338,23 @@ tile and an outlined hill tile (5 outlines), script time per frame on the main t
17.7 to 5.8 ms with nothing selected, from 26.2 to 8.6 ms with the map selected and from 29.9 to
8.7 ms in Play. That is 52, 38 and 33 fps before and 60 fps in all three after.
A second round (#284) took out what a map that only stands there still cost in Play:
- The cells were compared on every question, some sixty times a frame for one map. That was the
largest single cost of the run. Now a painter's word decides, see above.
- A view with an animated tile on it was drawn twice a frame: once by the run and once more by
`animate`. `animate(drawnBefore)` now leaves a view alone that was drawn since the tick began.
- Every mesh of the map got a new geometry with each drawing. `TilemapField` keeps what a mesh
was built from and builds again only when the cells, the tile size, the origin or the picture
differ. `groupByTile` and `layerRows` hand out the very same lists for the same cells, which is
how a mesh tells. An animated tile rebuilds its own mesh when it steps on, the others stay.
- The physics went through every collider of a map each tick to switch it on or off. A map whose
shapes and switch did not change is skipped.
Measured in Play on the 30x18 map of the reference project with 222 entities, per frame on the
main thread of a slow machine: Physics 2.64 to 0.97 ms, Drawing 6.89 to 2.56 ms. The same scene
without the map and its crates takes 0.30 and 1.63 ms.
A frame still costs what it touches: an object standing **inside** many outlined cells is tested
against each of them, so an outline of a hundred corners around every cell of a lake is dearer than
a few around its shore. Draw as few corners as the shape needs.