From 28f86d781c416e55124acd26f439aebdbeb47e0e Mon Sep 17 00:00:00 2001 From: Dabit Date: Tue, 10 Mar 2026 14:18:11 +0100 Subject: [PATCH] docs: complete project research synthesis Synthesized 4 parallel research efforts into comprehensive SUMMARY.md: - STACK.md: Vanilla Canvas 2D, fixed timestep, Web Audio, no dependencies - FEATURES.md: MVP features + v1.x enhancements + defer list - ARCHITECTURE.md: Game loop + state machine + entity patterns, 10-phase build order - PITFALLS.md: 8 critical pitfalls with prevention strategies Key recommendations: - Use fixed timestep accumulator (60 Hz physics, variable rendering) - Implement 10 phases from game loop foundation to cross-browser testing - Address critical pitfalls early (tunneling, timing, DPI, autoplay, AI, power-ups, lag, memory) - MVP ships with core Pong + AI + menus + basic polish - v1.x adds particles, trails, power-ups, arenas All research backed by official sources (MDN, web.dev, Chrome docs) and established patterns. Confidence: HIGH. Ready for requirements definition. Co-Authored-By: Claude Sonnet 4.6 --- .planning/research/ARCHITECTURE.md | 790 +++++++++++++++++++++++++++++ .planning/research/FEATURES.md | 246 +++++++++ .planning/research/PITFALLS.md | 420 +++++++++++++++ .planning/research/STACK.md | 328 ++++++++++++ .planning/research/SUMMARY.md | 227 +++++++++ 5 files changed, 2011 insertions(+) create mode 100644 .planning/research/ARCHITECTURE.md create mode 100644 .planning/research/FEATURES.md create mode 100644 .planning/research/PITFALLS.md create mode 100644 .planning/research/STACK.md create mode 100644 .planning/research/SUMMARY.md diff --git a/.planning/research/ARCHITECTURE.md b/.planning/research/ARCHITECTURE.md new file mode 100644 index 0000000..a04bc0f --- /dev/null +++ b/.planning/research/ARCHITECTURE.md @@ -0,0 +1,790 @@ +# Architecture Research: HTML5 Canvas Arcade Games + +**Domain:** HTML5 Canvas 2D arcade games (Pong-like) +**Researched:** 2026-03-10 +**Confidence:** HIGH + +## Standard Architecture + +### System Overview + +``` +┌────────────────────────────────────────────────────────────────┐ +│ Presentation Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Canvas View │ │ UI Layer │ │ Audio Out │ │ +│ │ (rendering) │ │ (DOM menus) │ │ (Web Audio) │ │ +│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ +│ │ │ │ │ +├─────────┴─────────────────┴─────────────────┴──────────────────┤ +│ Game Loop Manager │ +│ ┌────────────────────────────────────────────────────┐ │ +│ │ requestAnimationFrame → Update → Render → Loop │ │ +│ └────────────────────────────────────────────────────┘ │ +├─────────────────────────────────────────────────────────────────┤ +│ State Machine │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ Menu │→ │ Game │→ │ Pause │→ │GameOver │ │ +│ │ State │ │ State │ │ State │ │ State │ │ +│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ +├─────────────────────────────────────────────────────────────────┤ +│ Game Logic Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Entity Mgr │ │ Physics/ │ │ Collision │ │ +│ │ (ball, │ │ Movement │ │ Detection │ │ +│ │ paddles) │ │ Update │ │ │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ Particle │ │ Power-up │ │ +│ │ System │ │ Logic │ │ +│ └──────────────┘ └──────────────┘ │ +├─────────────────────────────────────────────────────────────────┤ +│ Input Layer │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Keyboard │ │ Input State │ │ Command │ │ +│ │ Events │ │ Manager │ │ Queue │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└────────────────────────────────────────────────────────────────┘ +``` + +### Component Responsibilities + +| Component | Responsibility | Typical Implementation | +|-----------|----------------|------------------------| +| **Game Loop Manager** | Orchestrates frame timing, calls update/render in sequence, manages requestAnimationFrame | Single `gameLoop()` function that runs at ~60fps | +| **State Machine** | Transitions between menu, playing, paused, game over states; isolates logic per scene | Object with `onEnter()`, `update()`, `render()`, `onExit()` methods per state | +| **Input Manager** | Captures keyboard events, debounces, maintains current key state | Listens to keydown/keyup, maintains a `keysPressed` object | +| **Entity Manager** | Owns and updates all game objects (paddles, ball, power-ups) | Array of entities with position, velocity, update/render methods | +| **Physics/Movement** | Updates entity positions based on velocity, applies gravity if needed | `velocity.x`, `velocity.y` updated per frame, position += velocity | +| **Collision Detection** | Detects overlaps between entities, triggers responses | AABB (Axis-Aligned Bounding Box) for rectangles; circle distance for round objects | +| **Particle System** | Manages short-lived visual effects (impacts, explosions, trails) | Maintains particle array, updates lifetime/position, removes expired particles | +| **Power-up System** | Spawns power-ups, detects collection, applies effects | Object with spawn logic, duration tracking, effect callbacks | +| **Audio Manager** | Plays sound effects and music with pooling to avoid cutoff | Array of audio elements for each sound, round-robin playback | +| **Renderer** | Draws all entities to canvas | Canvas 2D context calls in specific order (background, entities, UI) | + +## Recommended Project Structure + +For a vanilla JavaScript HTML5 Canvas game (no build tools), structure as a single HTML file or minimal multi-file approach: + +``` +index.html # Single entry point (if single-file) + ├── + └── + + + + + +``` + +**To run locally (no build step):** + +```bash +# Option 1: Python (built-in) +python3 -m http.server 8000 + +# Option 2: Node.js (if installed) +npx http-server + +# Option 3: VS Code Live Server extension (GUI click) +``` + +Then open `http://localhost:8000` in browser. + +**No npm, no build tools, no transpilation needed.** The constraint is a feature—maximizes portability and minimizes deployment surface area. + +## Critical Decisions + +### Canvas 2D, Not WebGL + +**Decision:** Use Canvas 2D API exclusively. + +**Reasoning:** +- Pong is pure 2D (rectangles, circles, particles) +- Canvas 2D has zero startup cost, WebGL requires GLSL shader compilation +- Canvas 2D draws millions of pixels per frame efficiently on CPU +- WebGL overkill: no 3D transforms, no complex lighting, no real-time shadow maps +- Canvas 2D is familiar to JavaScript devs (no GPU programming knowledge needed) +- Performance: Canvas 2D renders 2D arcade games faster than WebGL on mid-range hardware + +**Outcome:** Single canvas element, 2D context. All graphics drawn with fillRect, fillCircle, drawImage (if sprites). + +### Fixed Timestep Over Variable Timestep + +**Decision:** Implement fixed 60 Hz physics timestep with variable rendering refresh rate. + +**Reasoning:** +- Ensures ball physics are identical on 60 Hz monitors and 144 Hz monitors +- Prevents "bounce randomness" that breaks game feel +- Accumulator pattern handles frame skipping without losing physics updates +- Is the standard for physics-based games since 2006 (Gaffer on Games) +- Prevents "spiral of death" on low-end hardware (capped deltaTime) + +**Outcome:** Game loop uses accumulator. Physics updates in fixed increments, rendering as fast as hardware allows. + +### Web Audio API, Not HTML