- README: rewrite Difficulty section (per-network LEVELS ∝ block time, WOW=5min, multi-level descent, corrected casino size); document game_event + depth in the Socket.IO table. - NEW docs/BALANCE_SIM.md: the block-timed edge math (exponential deadline), the headless sim over the real engine, what it proved (size self-cancels, fast monster fails on slow chains), and the per-network NETWORK_TUNING model. - NEW docs/MULTI_LEVEL.md: descent mechanic, vault-only treasure, per-level provably-fair seeding, config, file map, open polish. - NEW docs/RENDER_PACKS.md: modes-vs-packs, the RK.fx layer, iso/tiled/zoom/cat. - docs/ARCHITECTURE.md: mark the block-time-difficulty gotcha RESOLVED; add render kit + balance/pacing sections and cross-links. - docs/TODO.md: 2026-07 done/pending section.
3.0 KiB
Render kit: modes, packs & FX
The client render kit (html/js/render/, namespace RK) draws the same Scene in multiple
techniques and art styles, so the tavern and dungeon are rich, interchangeable environments and new
art can be added as products.
Modes vs. packs
- Render modes = techniques (how a scene is drawn):
Tiled,ASCII,Iso,3D(renderModes.js). Each declares aprojection(topdown/iso/3d). - Packs = sets/styles within a projection (chosen via the pack picker): e.g. topdown Roguelike
Interior ↔ Roguelike Dungeon, iso Dungeon ↔ Medieval. Registered in
packRegistry.js/assetPacks.js. "Fancy" is not a mode — it's a pack (tiles + FX). - A premium mode unlocks once the user has any unlocked pack for its projection.
- The scene model is kind-based (
floor/wall/table/torch/monster/…), so one pack renders both the tavern (sceneFromTavern) and the dungeon (sceneFromGameState) — that's what makes packs interchangeable across both.
Entitlement: packs are gated by the operator-owned cosmetic catalog (cosmetic_catalog table,
src/multiplayer/entitlements.js) — free / grant / lifetime-spend / subscription-tier. ?unlock=1
sets a sticky local QA bypass. See MONETIZATION.md.
The FX layer (fxLayer.js, RK.fx)
Pure-canvas animated FX (CSP-safe, no WebGL), shared by the tiled and iso renderers so a scene lights up the same way in either projection:
RK.fx.fire— dancing two-layer flame + warm glow (torches, hearths).RK.fx.hazard— pulsing overlay for hazard tiles (lava/poison/spikes) with a footprint-clip callback so it fits square cells and iso diamonds alike.RK.fx.flicker/pulse/glow— the primitives.
A tile carries fx: 'fire' or hazard: '<kind>' in the scene legend (sceneModel.js); the renderer
draws only the tile's floor base in the static pass and lets RK.fx paint the animated layer in
the live loop. The tavern has wall braziers + a hearth; the dungeon hazard kinds are wired and render
the moment the generator emits their chars (L/P/^) — pending the generator + gameplay stakes.
Other pieces
| File | Role |
|---|---|
isoRenderer.js |
Canvas isometric projection. Orientation-aware walls (_S for x-runs, _W for y-runs, corner tile), floor variety, contact shadows + vignette juice. Kenney iso dungeon set (assets/kenney/iso-dungeon/). |
tileRenderer.js |
Top-down atlas renderer. over compositing (object tiles drawn on a base tile), torch-lit vignette, ember/flicker loop, animated fire/hazard emitters. |
zoomControl.js |
RK.attachZoom(host) — wheel/pinch zoom (0.4–4.0), dblclick reset, pixelated scaling. |
catSprites.js |
Animated tavern cat (Pet Cats Pack idle strips). |
packRegistry.js |
Multi-pack-per-projection registry: active-pack selection persisted per projection, entitlement-gated, graceful fallback. Node-testable. |
Tests: test/renderPackResolver.test.js, test/packRegistry_ultra.test.js.