barkour/MAP.md
w1n5t0n f57c1f16f8 feat: top-down 'Dogpit' arena mode (dota-like view)
Second game mode selectable at dog select (host-authoritative online):
- js/sim_arena.js: top-down sim, same export surface as sim.js — x/y plane
  plus a z hop axis (Space / comma); KOs by knocking dogs into abyss pits
- js/mapgen_arena.js: mirrored symmetric arenas — walls, pits, center
  clearing, guaranteed spawn-to-center corridors, crystals/spikes/launch
  pads, mirrored saw pairs; fallback pit pair since pits are the only KO
  mechanic
- specials re-imagined per dog: zoom dash, ram + hop-slam, zip-leash
  slingshot, blink, hover (floats over pits/saws/spikes)
- render: arena tiles with wall shadows + void pits, top-down dog drawing
  with z-lift over a ground shadow; new fall event/sfx
- B.HOP input bit so 'up' can mean north in top-down (Space also jumps in
  side view); mode toggle UI + mode carried in start/rematch net messages

Tested: arena mapgen determinism/symmetry/connectivity + chaotic matches +
pit/hop scenarios headless; local chaos + full P2P arena match (host mode
flip syncs to client) in two headless browsers with zero page errors.
2026-06-10 15:23:22 +02:00

28 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# MAP.md — Barkour code index
Vanilla-JS canvas game, no build step. ES modules under `js/`, served statically.
- `index.html` — DOM shell: all screens (menu/host/join/charselect/game/result) as overlay divs; loads PeerJS from CDN (online play only), then `js/main.js`.
- `style.css` — overlay/menu styling; canvas letterboxed to 16:9 via CSS.
- `js/consts.js` — grid (TILE=12, 80×45 → 960×540), tile enum `T`, input bitmask `B`, item ids, physics constants, snapshot rate.
- `js/rng.js` — seeded mulberry32 (`makeRng`); `randomSeed()` is UI-side only.
- `js/mapgen.js` — side-view `generateMap(seed)`: ground heightmap, pits, towers, islands, one-way platforms, crystals (hp 3), pads, spikes, rail saws, spawns; `PALETTES`; `sawPos()` polyline eval (ping-pong or loop).
- `js/mapgen_arena.js` — top-down `generateArena(seed)`: mirrored (left↔right) walls/pits, corner spawns, guaranteed corridors spawn→center, fallback pit pair (pits are the only KO mechanic), mirrored saw pairs.
- `js/physics.js` — center-based AABB vs tile grid: `moveEntity` (per-axis, one-way platform aware), `raycast`, `boxFree`, `standingOnPlat`.
- `js/characters.js``CHARS` data (stats + visual params) and `updateCharacter()`: per-dog special movement (air dash / charge+pound / grapple constraint / blink / jetpack).
- `js/sim.js`**authoritative, DOM-free side-view sim**: `createGame`, `step(game, inputs)` (60 Hz), combat (`hurt`: damage% → knockback), mining/items/hazards/KO/respawn/match-end, `snapshot`/`applySnapshot` for netplay. Sets `game.kind='side'`.
- `js/sim_arena.js` — top-down "Dogpit" sim, **same export surface as sim.js** (main.js swaps modules per match). x/y plane + z hop axis; KOs via pit falls; specials re-imagined per dog (dash cooldown, ram/slam, zip-leash, blink, hover). Sets `game.kind='arena'`.
- `js/input.js` — keyboard → bitmasks; slot 0 = WASD+FGH, slot 1 = arrows+KL;.
- `js/net.js` — PeerJS wrapper: `hostRoom`/`joinRoom`; room key = host peer id suffix; signaling via PeerJS cloud, game traffic pure P2P. Runs a 2s heartbeat + 8s watchdog (WebRTC close events are unreliable); broker `network` errors are ignored once the data channel is up.
- `js/render.js` — canvas: cached seeded background, tiles, procedural dog drawing, particles/ghosts driven by sim events (`fxEvents`), HUD, banners. Branches on `game.kind`: side view (`drawTiles`/`drawDog`) vs top-down (`drawTilesArena`/`drawDogTop`, z-height lifts the dog off its shadow).
- `js/audio.js` — WebAudio-synthesized sfx; `playEvents` maps sim events → sounds.
- `js/main.js` — app state machine: screens, char select (incl. mode toggle: `gameMode` 'side'|'arena', host-authoritative over the wire via `mode`/`start`/`rematch` messages), three match drivers (local / host / client) sharing one rAF fixed-timestep loop; `matchSim` points at the active sim module.
- `test/smoke.mjs``npm test`: headless mapgen determinism + chaotic full matches + targeted mining/stocks scenarios.
## Conventions & gotchas
- **Client never simulates.** In netplay the joiner only sends input bits and renders `applySnapshot` state; anything render reads must survive the snapshot round-trip (player `st` is re-shaped there).
- **Sim events are the only side-channel**: fx, audio, *and* client tile mutations (`tile`/`crack` events) ride on them. Host accumulates `pendingEvs` between snapshots.
- All sim/mapgen randomness must use the seeded RNG — never `Math.random()` inside `js/sim.js`/`js/mapgen.js`/`js/characters.js` paths.
- Velocities must stay < TILE (12 px/tick) or AABB collision tunnels.
- 7 as an arc end-angle in render means "> 2π" (full circle), a deliberate shorthand.