reikhelm/reikhelm-web/explore.html
Parley Hatch ed00e31009 feat(render): real-geometry depth export + first-person explorable atlas
Render actual generated dungeons through the AI pipeline — both top-down and
first-person (Eye-of-the-Beholder style) — instead of synthetic test depth.
All renderer-side: derived from the envelope's tiles+regions+theme, the core
stores none of it.

- depth.js: top-down height-field depth exporter (walls raised, pools recessed,
  pillars as bumps, subtle per-theme relief), calibrated to the proven room_depth
  levels so one tall room can't crush every floor dark.
- fpv.js: first-person depth via a Wolfenstein-style grid raycaster (16:9),
  reports straight-ahead distance for opening detection.
- explore.js: room->room nav graph derived from REAL tile openings (scan
  boundary gaps, bin by cardinal, flood the corridor to the destination room) —
  nav + open share one source of truth with the rendered passages.
- bake_atlas.py: bakes per-room x4-facing pixel-art frames; per-theme + per-facing
  (wall vs passage) prompts, fixed diffusion seed for cross-frame style coherence,
  per-run unique prefixes so re-bakes don't silently skip.
- explore.html + explore-viewer.js: WASD first-person dungeon explorer
  (room-to-room movement, turning, minimap), integer-pixel fullscreen.
- serve.py: stdlib dev server — static web root + /out tree + POST /save, no-store.
- main.js/render.js/style.css: export hooks, the depth button, distanceToWall export.
- tools/README.md: Stage 0/1/2/3 docs; .dev/2026-06-01-fpv-prompts.md: prompt
  research (cfg-1 negatives are inert; trigger words summon hands; empty-ruin
  reframe; fixed seed = consistency).

Proven end-to-end on seed 7 (17 rooms). Outputs organized under git-ignored
tools/out/. Control strength: 0.80-0.85 top-down, 0.85 first-person.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 00:02:14 -06:00

42 lines
2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>reikhelm · dungeon explorer</title>
<style>
:root { --accent: #d4a54a; --ink: #e0d4cc; }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: #000; color: var(--ink);
font: 13px/1.4 ui-monospace, "SF Mono", Menlo, Consolas, monospace; overflow: hidden; }
/* The pre-rendered frame, integer-pixel scaled to fill the screen. */
#frame { position: fixed; inset: 0; width: 100%; height: 100%;
object-fit: contain; image-rendering: pixelated; background: #000;
transition: filter .12s; }
.vignette { position: fixed; inset: 0; pointer-events: none;
box-shadow: inset 0 0 220px 60px rgba(0,0,0,0.7); }
#hud { position: fixed; top: 14px; left: 16px; padding: 8px 12px;
background: rgba(8,8,11,0.62); border: 1px solid rgba(212,165,74,0.35);
border-radius: 6px; backdrop-filter: blur(2px); }
#hud b { color: var(--accent); }
#hud .dim { color: #8a8a98; }
#minimap { position: fixed; bottom: 14px; left: 16px; image-rendering: pixelated;
background: rgba(8,8,11,0.55); border: 1px solid rgba(212,165,74,0.30);
border-radius: 4px; padding: 6px; }
#miss { position: fixed; inset: 0; display: none; place-items: center; text-align: center;
color: #8a8a98; }
#miss.show { display: grid; }
.keys { position: fixed; bottom: 16px; right: 18px; color: #6a6a76; text-align: right; }
.keys b { color: var(--ink); }
</style>
</head>
<body>
<img id="frame" alt="dungeon view">
<div class="vignette"></div>
<div id="hud">loading atlas…</div>
<div id="miss"><div>⛏ this view isn't baked yet<br><span id="miss-detail"></span></div></div>
<canvas id="minimap" width="180" height="120"></canvas>
<p class="keys"><b>W</b>/<b>S</b> forward·back · <b>A</b>/<b>D</b> turn</p>
<script type="module" src="explore-viewer.js?v=3"></script>
</body>
</html>