Commit Graph
17 Commits
Author SHA1 Message Date
jwinterm 89398335c7 feat: productionize paid modes and PvP capture 2026-07-21 20:41:27 -04:00
jwinterm 175effd6fa fix(iso): zoom direction + wall cutaway for readable openings
Zoom: the wheel handler based its step on a hardcoded 1.7, but iso defaults to 1.0 — so the first
scroll (either direction) jumped up to ~1.7 and read as "always zoom in". Base the step on the
CURRENT effective zoom via SP._defaultZoom() instead. Same mode-aware default now used by the camera.

Iso occlusion: tall walls (184px) hide the floor/openings behind them (inherent to iso painter
order). Add a cutaway — walls between the camera and the player (higher x+y, within ~3 cells) draw
at 0.28 alpha so you can see yourself and the openings right in front of you.
2026-07-16 03:23:46 -04:00
jwinterm 11732531d2 fix(render): iso black — override max-height/object-fit on the SP canvas
Root cause of iso rendering fully black: `.rotdis canvas { max-height:100%; object-fit:contain }`
(styling meant for the legacy ROT canvas) also applied to the render-kit canvas. SP only overrode
max-width. A canvas TALLER than the host (iso: ~2445px vs ~900px host) got object-fit-shrunk to
~0.37x while the CAMERA translate is computed in buffer space — so the player landed far off-screen
(black). Tiled/ascii canvases usually fit the host, so they escaped it. Fix: override max-height:none
+ object-fit:fill so the buffer maps 1:1 and the camera transform alone controls scale/position.
Iso default zoom set to 1.0 (its 84px tiles are large); tiled/ascii keep 1.7.
2026-07-14 12:12:26 -04:00
jwinterm b45c0851c5 fix(render): 3D lazy-loads THREE; ASCII torch lights; iso never-black placeholder
Three mode-switch issues:
- Picking 3D gave "original": SP._ensureRenderer used the sync createRenderer, which falls back to
  Tiled when THREE (lazy CDN load) is not ready. Now it kicks off RK.ensureThree and re-mounts as
  real 3D once loaded (renders Tiled meanwhile so it is not blank).
- ASCII torches were inert glyphs: they now draw a warm flickering radial glow (actual light source)
  with the glyph at full brightness, driven by a throttled ~22fps RAF (cancelled on destroy).
- Switching to iso could show black while the pack images load: tiles now draw a legend-coloured iso
  diamond placeholder until the real image is ready, so the dungeon shape + camera always read.
2026-07-13 14:55:26 -04:00
jwinterm 4c7b256c9a feat(3d): real player-follow camera (not fit-to-view)
3D is a paid rung and should behave like the other modes. Rework the THREE camera to FOLLOW the
player instead of framing the whole level: canvas now sizes to the host (setSize updateStyle),
the ortho frustum is a fixed player-centered zoom (span 8) with host aspect, and _animate re-targets
the camera to the player world position every frame (keeps the iso (8,9,8) offset; glides smoothly
since the player mesh lerps). SP._applyCamera no longer CSS-transforms the 3D canvas (it fills the
host and THREE owns the camera). Handles host resize via _fitToHost.
2026-07-13 08:49:23 -04:00
jwinterm 2bbdffe867 fix(render): switching to ASCII mid-game no longer blacks out (+3D fit guard)
The ASCII renderer never set focusPoint, so switching to it mid-game left the SP camera with no
focus → scale-only transform pinned the grid to the corner and the explored area sat off-screen
(black). AsciiRenderer.render now sets focusPoint on the player cell (sticky), and the camera
fallback covers name==="ascii" too (cell-based, same as tiled). Iso already reports focusPoint.
3D drives its own THREE camera + sizes its canvas to the level, so _applyCamera now scale-to-FITS
the 3D canvas into the host (centered, no player-follow) instead of applying a broken zoom.
2026-07-13 08:43:03 -04:00
jwinterm c4c7d71191 fix(camera): derive focus from last player pos when renderer focusPoint is missing
The SP camera still intermittently pinned the whole level to the top-left at game start: the
per-frame _applyCamera read renderer.focusPoint as null (a start-of-game race, or a tick reading
a just-(re)created renderer instance before its first render) and fell back to a scale-only
transform. Add a fallback: when focusPoint is absent, derive it from SP._lastState.player (tiled
coords, cell=24) so the camera always has a target and centers the player. Also read host dims
via clientW/H||offsetW/H for resilience.
2026-07-13 08:32:59 -04:00
jwinterm b1b103c9d7 fix(fog): fade explored memory to black + unify off-map dark (no map-edge leak)
Explored-but-not-visible tiles rendered at a flat 0.25 brightness — a hard-edged grey block
that outlined the explored map (and its edge). Now explored memory dims AND fades toward black
with distance from the player, so the remembered area melts into the dark with no revealing
edge. Also set the render host background to pure #000 so the area beyond the map edge is the
SAME black as an unexplored in-bounds tile (previously #0a0c0f vs #000 — a shade seam that
traced the boundary). Currently-visible lighting unchanged.
2026-07-13 08:24:48 -04:00
jwinterm e9650f9843 fix(render): reliable SP camera fill, clean wall torches, subtler wait juice
Camera: mount the render-kit host with inset:0 (fill #game-display) instead of
min(100%,78vh)+translate(-50%) centering. #game-display is grid-bounded (container is
100vh/overflow-hidden), so filling it gives the camera reliable clientWidth/Height every
frame — fixes the intermittent "player stranded in a top band, black below" off-centering.

Torches (in-game): drop the pack torch SPRITE composite — several sheets place it off-center/
rotated, reading as misaligned. Keep wall base + procedural RK.fx flame: a clean wall-mounted
torch that looks right in every pack.

Wait animations: shrink the juice bursts (18-24 -> 6-7 particles, spread 1.8-2.4 -> 0.6-0.7)
and remove the red death/caught bursts, so a grab/escape reads as a tight glint on the hero
instead of an explosion spraying onto the wall torches.
2026-07-12 21:08:16 -04:00
jwinterm ad4e10d363 revert(render): waiting screen back to the ROT treasure-hunt animation
The render-kit "waiting room" replaced the beloved scripted drama (player races for a
pulsating treasure, grabs it, escapes or is devoured by a monster pack, death shockwave +
ESCAPED! celebration, randomized variants) with a static lit room — a big downgrade. Restore
BOTH ROT waiting animations (block-wait AND awaiting-payment, selected via Game._awaitingPayment)
by hiding the render-kit host and letting the ROT display own the waiting screen. Remove the
now-unused SP.showWaiting/hideWaiting/waitingScene bridge code. The pack/mode still applies in
actual gameplay, which is what matters.
2026-07-12 20:14:11 -04:00
jwinterm 46f3cc204d feat(render): waiting screen renders through the render kit (pack/mode)
The next-block wait now draws a small lit "mining room" Scene through the ACTIVE renderer
(RK.SPGame.showWaiting) — floor/walls/torches in your chosen pack (Tiled/Iso/3D), camera
centered, torches flickering via the FX loop — with the "Mining the next block" text as an
overlay. So the wait inherits your tiles/mode instead of being the plain ROT animation.
Falls back to the ROT WaitingScreenAnimator if the kit is unavailable. SP.render clears the
overlay when the real game starts.
2026-07-12 19:33:07 -04:00
jwinterm 8a3b254935 fix(ux): honest block-time wording + smooth (lerped) SP camera
- Modal: "Safe — full block window" overstated it (blocks arrive randomly, Poisson). Now
  "Start fresh · blocks land at random" / "Jump in · race the time left".
- Camera: was snapping to the player every frame (jerky on canvas resize / level teleport).
  Now glides (lerp 0.3) and only snaps on a big jump; snap-centers on new-game start.
2026-07-12 15:38:53 -04:00
jwinterm 03fd82c44c fix(camera): sticky focusPoint + per-frame camera loop (stop corner-snap mid-run)
The player-centered camera snapped the dungeon to the top-left corner after a while: the
renderer nulled focusPoint on a transient player-less frame, so the transform lost its
translate. Fix: focusPoint is now sticky (keep the last if the player is momentarily
absent), and the SP bridge re-applies the camera every frame via its own RAF loop, so a
canvas resize or a stale frame can no longer break centering.
2026-07-12 12:32:35 -04:00
jwinterm dd7d70aec8 fix: fog-of-war entities, multi-level descend feedback, camera centering, fewer levels
- FOG: sceneFromGameState only emits exit/entrance/treasure/items once their cell is EXPLORED,
  and the monster only while IN VIEW — no more exit stairs leaking through the fog.
- DESCEND FEEDBACK: reaching a non-final exit descends (multi-level) and used to silently dump the
  player at a new entrance (read as a bug). Server now sends depth/maxDepth on game_event; the
  client shows "Stairs down! Level N of M — keep going". Also lowered level counts (WOW 4->2,
  BTC 8->3, XMR 2->1) — clearing 4-8 levels in one block was unwinnable; kept modest until proper
  multi-level calibration + UX.
- CAMERA: the host filled the very-tall #game-display so centering put the player low; it's now a
  bounded viewport (min(100%,78vh)) centered in #game-display, so the player stays on-screen-centered.
Suite 62/435 green.
2026-07-12 11:50:40 -04:00
jwinterm 277ef72c99 fix(render): SP camera host fills #game-display, beats .rotdis canvas clamp
The render-kit dungeon host was a flex item in a centered flex container (.rotdis) with
sibling canvases, so it got shrunk + shoved into a corner; and .rotdis canvas has
max-width:100% !important which clamped the camera canvas. Fix: host is now
position:absolute inset:0 (fills #game-display, which is position:relative), and the
canvas overrides max-width via setProperty(..., important). Dungeon now renders centered
on the player in the game area.
2026-07-12 11:06:22 -04:00
jwinterm d925df1ae9 feat(render): re-enable render-kit SP dungeon with player-centered camera + goblin monster
Commit to the render kit as THE single-player renderer (legacy = hard fallback only). Fixes
the two things that broke it:
- CAMERA: each renderer now exposes focusPoint (the player's pixel pos); the SP bridge mounts
  a self-sizing 16:10 viewport host and CSS-transforms the canvas to centre the player at a
  readable zoom (wheel to zoom). Renderer-agnostic (tiled/iso/3d). No more whole-level-in-a-corner.
- MONSTER: the tiled renderer drew a hardcoded red dot; now it draws the Goblin character sprite
  (char-goblin, the same path the tavern draws characters), red orb only as last-resort fallback.
Re-enabled: _drawGameScreen prefers RK.SPGame; spRenderPicker ENABLED. Suite 62/435 green.

NEXT (still owed): make the splash + both waiting animations render through the kit too, so
they use the chosen pack/mode instead of the ROT text screens.
2026-07-12 10:56:14 -04:00
jwinterm 1325b49b42 feat(render): single-player dungeon renders through the render kit (packs in gameplay)
The migration that makes the pack ladder pay off IN the dungeon, not just the tavern.
The SP game now draws via RK (Tiled/ASCII/Iso/3D + unlocked packs) instead of the
legacy ROT display.

- Adapter: sceneFromGameState now consumes the CLIENT state shape (sparse {y:{x:v}}
  tile maps, not just server arrays) via maxDims(). Verified + unit-tested.
- Bug fix: RK.sceneFromGameState was never actually exposed (only RK.scene.*), so
  matchClient + tavern spectator were silently no-op-ing. Aliased onto RK.
- Bridge (spGameRenderer.js, RK.SPGame): mounts an RK renderer in a dedicated host
  inside #game-display, toggles the legacy ROT canvases, zoom-enabled. Game._draw
  GameScreen prefers it and FALLS BACK to RenderEngine on any failure, so the live
  game can never blank. ROT still draws the splash/win/lose text screens.
- Picker (spRenderPicker.js): homepage mode + pack selector, gated by entitlements
  (free = Tiled/Original + ASCII; ladder unlocks Iso/3D/packs), rebuilds on identity.
- index.html loads the render-kit renderers + the bridge/picker.

Bundled with the catalog ladder (migration 028): free Original bare pack, ladder
1/5/10/20/40/50. Deploying makes the free tavern bare (by design) AND the dungeon
render-kit-ed. v1 renders the whole explored level + zoom (player-centered camera is
the next polish). Suite 62/435 green; adapter smoke-verified.
2026-07-12 10:14:56 -04:00