docs(02): capture phase context
This commit is contained in:
93
.planning/phases/02-core-gameplay/02-CONTEXT.md
Normal file
93
.planning/phases/02-core-gameplay/02-CONTEXT.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Phase 2: Core Gameplay - Context
|
||||
|
||||
**Gathered:** 2026-03-10
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Add scoring system, second paddle (human Player 2 + AI opponent with 3 difficulty levels), and match-end condition. Phase 3 adds real UI screens — Phase 2 delivers a fully playable game using temporary on-canvas UI. No visual effects, power-ups, or menus yet.
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### Mode Activation (temporary — Phase 3 replaces with real screens)
|
||||
- Key press at game start: press '1' for Solo vs AI, press '2' for 2-Player local
|
||||
- Difficulty selected by key press before match: press '1' for Easy, '2' for Medium, '3' for Hard
|
||||
- This temporary selection state lives in GameState (e.g. GameState.mode, GameState.difficulty)
|
||||
- Phase 3 wires its mode select screen to set these same GameState values — no refactor needed
|
||||
|
||||
### Match End (temporary — Phase 3 replaces with real game-over screen)
|
||||
- On-canvas winner text: "Player 1 Wins! Press R to restart" (or "AI Wins!")
|
||||
- R key resets state and returns to mode/difficulty key selection
|
||||
- Phase 3 replaces this on-canvas message with its game-over screen
|
||||
|
||||
### Target Score
|
||||
- First to 7 points wins
|
||||
- Stored as a constant in GameConfig (WIN_SCORE: 7) for easy tuning later
|
||||
|
||||
### Ball Re-serve After Score
|
||||
- ~1 second pause to let the score update register visually
|
||||
- Ball auto-serves after the pause — no player input required
|
||||
- Server direction: alternates or goes to the player who just scored (Claude's discretion)
|
||||
|
||||
### AI Strategy
|
||||
- Predictive interception: AI calculates the ball's y-position when it reaches the AI's x-position, then moves toward that target
|
||||
- Handles wall bounces in the prediction (ball trajectory traced to AI x, accounting for reflections)
|
||||
|
||||
### AI Difficulty via Reaction Delay + Speed Cap
|
||||
- **Easy**: slow max paddle speed + late reaction start (ball must cross a threshold before AI begins tracking)
|
||||
- **Medium**: moderate speed + small reaction delay
|
||||
- **Hard**: fast speed + minimal reaction delay — not perfect, still beatable with skill
|
||||
- All values stored in GameConfig as named difficulty presets (e.g. AI_EASY, AI_MEDIUM, AI_HARD objects)
|
||||
|
||||
### Claude's Discretion
|
||||
- Exact speed/delay values per difficulty (tune for feel after initial implementation)
|
||||
- How ball serves direction is chosen after scoring
|
||||
- Score display typography and positioning (on-canvas, minimal)
|
||||
- Whether prediction re-calculates every frame or on a throttled interval
|
||||
|
||||
</decisions>
|
||||
|
||||
<specifics>
|
||||
## Specific Ideas
|
||||
|
||||
- No specific requirements — open to standard approaches
|
||||
|
||||
</specifics>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- `GameState.paddle1`: has x, y, width, height, speed, color — `paddle2` should mirror this structure
|
||||
- `Input.getVerticalInput()`: returns -1/0/1 for Player 1 (W/S) — add `getVerticalInput2()` for Up/Down arrows
|
||||
- `Physics.update(deltaTime)`: currently handles ball + paddle1 movement — extend to handle paddle2 (human or AI branch)
|
||||
- `GameConfig`: central constants object — add WIN_SCORE and AI difficulty presets here
|
||||
- `Renderer.drawRect()` / `Renderer.drawCircle()`: reuse for drawing paddle2, score text, etc.
|
||||
|
||||
### Established Patterns
|
||||
- Module-object pattern: all new logic goes into existing objects (Physics, GameState, Input) or a new `AI` object
|
||||
- `GameLoop.main()` calls `Physics.update()` then `Renderer.*` — AI update should run inside Physics.update or a dedicated AI.update call before rendering
|
||||
- Single HTML file — all additions stay in `index.html`
|
||||
|
||||
### Integration Points
|
||||
- `Physics.update(deltaTime)` is where paddle movement and collision live — Phase 2 adds paddle2 movement (human or AI) here
|
||||
- `GameState` needs score fields (score1, score2), match state (playing/paused/gameover), mode, and difficulty
|
||||
- `GameLoop.main()` needs a check after Physics.update to detect scoring (ball passes left/right edge) and trigger pause → re-serve cycle
|
||||
|
||||
</code_context>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
- None — discussion stayed within phase scope
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 02-core-gameplay*
|
||||
*Context gathered: 2026-03-10*
|
||||
Reference in New Issue
Block a user