From 2cd0462a46d2bc67cad17729918d1bec1985af71 Mon Sep 17 00:00:00 2001 From: Dabit Date: Tue, 10 Mar 2026 20:54:02 +0100 Subject: [PATCH] =?UTF-8?q?docs(phase-02):=20research=20core=20gameplay=20?= =?UTF-8?q?=E2=80=94=20Player=202=20control,=20AI=20opponent,=20scoring=20?= =?UTF-8?q?system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documented standard stack (vanilla JS, HTML5 Canvas), architecture patterns (extend Physics for paddle2, add AI module, score detection at GameLoop level), common pitfalls (tunneling, AI balance, input lag, memory leaks), and validation architecture for Phase 2 requirements. Verified with locked decisions from CONTEXT.md and prior phase research. Ready for planning. Co-Authored-By: Claude Sonnet 4.6 --- .../phases/02-core-gameplay/02-RESEARCH.md | 945 ++++++++++++++++++ 1 file changed, 945 insertions(+) create mode 100644 .planning/phases/02-core-gameplay/02-RESEARCH.md diff --git a/.planning/phases/02-core-gameplay/02-RESEARCH.md b/.planning/phases/02-core-gameplay/02-RESEARCH.md new file mode 100644 index 0000000..6ab1974 --- /dev/null +++ b/.planning/phases/02-core-gameplay/02-RESEARCH.md @@ -0,0 +1,945 @@ +# Phase 2: Core Gameplay - Research + +**Researched:** 2026-03-10 +**Domain:** HTML5 Canvas Pong — second paddle (Player 2 / AI), scoring system, game state management +**Confidence:** HIGH + +## Summary + +Phase 2 builds on the Phase 1 foundation (ball physics, wall bounce, zone deflection, speed increment) by adding: + +1. **Second Paddle Control:** Player 2 controls paddle with Up/Down arrow keys independently from Player 1 (W/S) +2. **Scoring System:** Points awarded when ball passes opponent's paddle; first to 7 wins +3. **AI Opponent:** Predictive interception with 3 difficulty levels (Easy, Medium, Hard) using reaction delay + speed cap +4. **Game Mode Selection:** Temporary key-press selection (1 = Solo vs AI, 2 = 2-Player local) +5. **Difficulty Selection:** Temporary key-press selection (1 = Easy, 2 = Medium, 3 = Hard) +6. **Match-End Condition:** Winner displayed on-canvas; R key restarts +7. **Ball Re-serve Logic:** ~1 second pause after score, then auto-serve + +The architecture remains **module-object pattern** in a single HTML file. All new logic integrates into existing modules (Input, Physics, GameState, Renderer) or introduces minimal new modules (AI object). + +**Primary recommendation:** Extend Physics.update() to handle paddle2 movement (human or AI branch). Add AI object with predictive interception logic. Add scoring detection to GameLoop.main() after Physics.update(). Separate AI difficulty constants in GameConfig. Handle input cleanup and event listener management to prevent memory leaks. + +--- + + +## User Constraints (from CONTEXT.md) + +### Locked Decisions +- Mode activation: temporary key press (1 = Solo vs AI, 2 = 2-Player local); phase 3 wires real screens to same GameState fields +- Match end: temporary on-canvas winner text ("Player 1 Wins! Press R to restart"); phase 3 replaces with real game-over screen +- Target score: first to 7 points (WIN_SCORE: 7 constant in GameConfig) +- Ball re-serve: ~1 second pause, then auto-serve; no player input required +- AI strategy: predictive interception with ball trajectory traced to AI x-position, handles wall bounces in prediction +- AI difficulty: reaction delay + speed cap (Easy: slow speed + late reaction; Medium: moderate speed + small delay; Hard: fast speed + minimal delay) + +### Claude's Discretion +- Exact speed/delay values per difficulty (tune for feel after initial implementation) +- How ball serves direction is chosen after scoring (alternates or goes to player who scored) +- Score display typography and positioning (on-canvas, minimal) +- Whether prediction re-calculates every frame or throttled interval + +### Deferred Ideas (OUT OF SCOPE) +- None — all Phase 2 scope contained in discussion + + + + +## Phase Requirements + +| ID | Description | Research Support | +|----|-------------|-----------------| +| CORE-05 | Player scores point when ball passes opponent's paddle | Scoring detection at GameLoop level after Physics.update(); point awarded to opponent of player whose side ball left from | +| CORE-06 | Match ends when a player reaches target score (first to N points) | WIN_SCORE: 7 constant in GameConfig; match-end detection in GameLoop checks if score1 or score2 >= 7; temporary on-canvas display, phase 3 replaces | +| CORE-08 | Player 2 controls paddle with Up/Down arrow keys | Input.getVerticalInput2() mirrors Input.getVerticalInput(); listens to ArrowUp/ArrowDown key codes; physics.update() reads input and applies to paddle2 movement | +| AI-01 | AI opponent tracks and intercepts the ball | AI object implements predictive interception: calculates ball y-position when ball reaches AI paddle x-position, accounting for wall bounces; AI moves toward target y | +| AI-02 | Easy difficulty: AI reacts slowly with error margin — beatable by any player | GameConfig.AI_EASY: { speed: 200, reactionDelay: 0.3, errorMargin: 20 } — slow paddle, late reaction start (ball crosses threshold before AI begins tracking) | +| AI-03 | Medium difficulty: AI reacts at moderate speed — provides fair challenge | GameConfig.AI_MEDIUM: { speed: 320, reactionDelay: 0.1, errorMargin: 5 } — balanced speed/delay, small error margin | +| AI-04 | Hard difficulty: AI reacts fast but not perfectly — requires skill to beat | GameConfig.AI_HARD: { speed: 400, reactionDelay: 0.05, errorMargin: 2 } — fast but not instant; still beatable with skill | + + + +## Standard Stack + +### Core (No Dependencies) +| Component | Version | Purpose | Why Standard | +|-----------|---------|---------|--------------| +| **Vanilla JavaScript (ES6)** | Native browser | Ball physics, paddle control, AI logic, game state | No build step needed; single HTML file deployment. ES6 provides classes and arrow functions for clean code. All MDN docs reference ES6. | +| **HTML5 Canvas 2D Context** | Native browser API | Rendering paddles, ball, score, text | Standard for 2D games. All research and MDN docs assume Canvas 2D. | +| **requestAnimationFrame** | Native browser API | Game loop timing, delta time calculation | Required for responsive input, smooth animation, battery efficiency. Syncs with monitor refresh. | +| **Web Audio API** | Native browser (Phase 3) | Sound effects and music | Standard for browser games. Defer to Phase 3 per roadmap. | + +### Supporting (Integrated into Existing Modules) +| Module | Purpose | When to Use | +|--------|---------|------------| +| **GameState** | Central state object (scores, paddles, ball, game mode, difficulty) | Every update/render; single source of truth for game data | +| **Physics** | Movement and collision (extended for paddle2 and AI) | Every frame delta time; handles both ball and paddle physics | +| **Input** | Keyboard event handlers, key state map (extended for Arrow keys) | Every update; polls key state, not event-driven movement | +| **Renderer** | Canvas drawing (extended for score, paddle2, game-over text) | Every frame after Physics.update() | +| **GameLoop** | requestAnimationFrame orchestration, delta time capping, score detection | Every frame; top-level frame synchronization | +| **AI** (new) | Predictive ball interception, difficulty-based reaction delay and error margin | Every Physics.update() when mode == 'AI' | + +### No External Dependencies +This project uses vanilla JavaScript, HTML5 Canvas, and browser APIs only. No npm, no build tool, no framework. + +**Installation:** None required. Static HTML file runs directly. + +--- + +## Architecture Patterns + +### Recommended Project Structure + +Current structure (single `index.html` file): +``` +index.html + ├── + └──