Marching into enemy territory changes visibility every step, and each change
rebuilt the whole on-screen fog band. A tile's fog depends only on its own
level and its six neighbours', so the exact dependency radius is one tile, far
tighter than the vision radius.
- Every tile owns a fixed slot in one fog buffer, so rebuilding a tile never
shifts another's vertices and only the touched row spans are re-uploaded.
_applyKnowledge now diffs the visible/explored sets and hands the renderer
the changed tiles; buildFogTiles rebuilds them with their rings. On a 100x100
map a frontier patch is ~3-4 ms against ~80 ms for the band.
- A pan that leaves the built rows now builds only the newly exposed rows, and
the escape margin scales with the viewport, so dragging rebuilds rarely.
- _frame schedules the next animation frame before doing any work and catches
an error, so a one-off failure can no longer stop the frame loop for good.
- Added tests for the per-tile patch and the incremental pan.
Marching into unexplored or enemy land reveals a tile every step, and each
reveal rebuilt the whole-map fog mesh: about 1.8M vertices and 50 MB on a
160x160 map, regenerated at the rebuild throttle. Walking through
already-explored home land reveals nothing, which is why the stutter only
showed up on a border crossing, with a single unit.
- buildKnowledge now takes a row range and builds only the rows on screen; the
row table stays full length so the existing row-banded draw keeps working.
- _flushFog rebuilds on a visibility change or a pan to a new row band, still
coalesced, and the draw clamps to the band that was built.
- A mode/zoom change schedules the band rebuild instead of building the whole
mesh, and uniform interior tiles skip the per-vertex blur kernel.