--- phase: 01-foundation plan: 02 subsystem: ui tags: [canvas, physics, ball-movement, collision-detection, zone-deflection, vanilla-js, game-loop] # Dependency graph requires: - phase: 01-01 provides: "index.html scaffold with HiDPI canvas, GameLoop, Renderer, Input, Physics skeleton, GameState" provides: - "GameConfig object with initialBallSpeed (220px/s), speedIncrement (18px/s), paddleSpeed (400px/s)" - "Physics.serveBall() serving from center at random angle and direction" - "Physics.update() with full ball movement via vx/vy * deltaTime" - "Wall bounce: top and bottom with Math.abs vy inversion" - "Out-of-bounds detection: ball re-serves automatically when exiting left/right edge" - "Physics._checkPaddleCollision() with 5-zone AABB deflection and per-hit speed increment" - "On-canvas speed debug display for Phase 1 verification" affects: [Phase 2, Phase 3, Phase 4, Phase 5] # Tech tracking tech-stack: added: [] patterns: - "Zone-based paddle deflection: 5 zones mapped to [-60, -30, 5, 30, 60] degrees" - "AABB collision detection with ball-radius buffer on all four sides" - "Ball pushed out of paddle post-collision to prevent double-collision on next frame" - "GameConfig as tunable constants object: allows per-value adjustment without touching Physics logic" - "serveBall() serves at random angle (-45 to +45 deg) in random horizontal direction" - "Speed stored as scalar on ball.speed; vx/vy recomputed from speed + angle each paddle hit" key-files: created: [] modified: [index.html] key-decisions: - "Angles [-60, -30, 5, 30, 60] degrees: center zone uses 5 degrees (not 0) to prevent infinite horizontal loops" - "Speed increments on every paddle hit via GameConfig.speedIncrement=18 px/s; resets to initialBallSpeed=220 on serve" - "Collision only checked when ball.vx < 0 (moving left toward paddle1): eliminates false positives when ball passes through after deflection" - "Ball pushed to paddle.x + paddle.width + ball.radius + 1 post-collision: 1px safety margin prevents double-trigger" - "Tunneling risk documented in comment: risk begins above 4800px/s; current rallies top out ~800px/s; Phase 5 can add substep if needed" - "Debug speed display kept for Phase 1 manual verification (costs nothing, aids confirmation)" patterns-established: - "Physics methods added to Physics object without disturbing existing structure: serveBall(), _checkPaddleCollision() added alongside update()" - "GameConfig placed before GameState at script top: all tunable values centralized, readable before any system references them" requirements-completed: [CORE-01, CORE-02, CORE-03, CORE-04] # Metrics duration: 1min completed: 2026-03-10 --- # Phase 1 Plan 02: Ball Physics Summary **Ball physics with 5-zone angle deflection, per-hit speed increment from 220px/s, wall bounce, and automatic re-serve on out-of-bounds — Phase 1 fully playable** ## Performance - **Duration:** 1 min - **Started:** 2026-03-10T13:49:45Z - **Completed:** 2026-03-10T13:51:12Z - **Tasks:** 2 - **Files modified:** 1 ## Accomplishments - Ball moves from center at 220px/s initial speed in a random direction on page load and after every out-of-bounds - Wall bounce (top and bottom) with angle-of-incidence = angle-of-reflection via Math.abs vy inversion - Paddle collision with 5-zone deflection: top edge deflects at -60 deg, center at 5 deg, bottom edge at 60 deg - Speed increases by 18px/s per paddle hit and resets to 220px/s on every serve - On-canvas debug display shows current speed in real-time for Phase 1 verification ## Task Commits Each task was committed atomically: 1. **Task 1: Ball physics — movement, wall bounce, serve, and GameConfig** - `46b8f7b` (feat) 2. **Task 2: Paddle-ball collision refinement and speed acceleration verification** - included in Task 1 (angles, tunneling comment, and debug display all implemented together; no additional code changes needed) **Plan metadata:** (docs commit follows) _Note: Task 2 was purely verification — angles from the plan spec were correct as implemented, tunneling comment was added in Task 1, and debug display was already present. No separate commit needed._ ## Files Created/Modified - `/home/dabit/projects/gijs/index.html` - Added GameConfig, Physics.serveBall(), full Physics.update() with ball movement and wall bounce, Physics._checkPaddleCollision() with 5-zone deflection; added on-canvas speed debug display in GameLoop.main() ## Decisions Made - **5-degree center zone:** Zone 2 angle is 5 degrees, not 0 degrees. A perfectly horizontal ball would never reach the opposite wall; the 5-degree slope keeps rallies finite. - **vx/vy recomputed from speed + angle per hit:** After each collision, ball.vx and ball.vy are fully recomputed from the new speed and the zone angle. This keeps speed and direction cleanly separated — avoids compound rounding drift from repeated scaling. - **Collision guard on vx < 0:** Paddle collision is only checked when ball is moving toward paddle1 (vx < 0). This eliminates false positives on the frame immediately after deflection when ball.x is still near paddle edge. - **1px safety margin post-collision:** Ball is pushed to `paddle.x + paddle.width + ball.radius + 1` after collision. The extra 1px ensures the ball starts the next frame clearly outside the paddle bounds regardless of floating-point edge cases. ## Deviations from Plan None - plan executed exactly as written. Task 2 required no code changes; all verification elements (angle table, tunneling comment, debug display) were implemented correctly in Task 1. ## Issues Encountered None. ## User Setup Required None - no external service configuration required. Open index.html directly in any modern browser to play. ## Next Phase Readiness Phase 1 is complete. All 6 success criteria are met: - CORE-01: Ball moves continuously and bounces off top/bottom walls - CORE-02: Player 1 paddle deflects ball on collision - CORE-03: Zone-based angle deflection produces 5 visually distinct trajectories - CORE-04: Speed increments per hit (visible in debug display), resets per serve - CORE-07: W/S keys move paddle responsively (from Plan 01-01) - VFX-05: Canvas renders sharply on HiDPI/Retina displays (from Plan 01-01) Phase 2 should extend Physics without touching zone deflection logic: - Add `GameState.paddle2` with AI movement - Add scoring state and reset logic - Add second AABB collision in `_checkPaddleCollision()` or a symmetric `_checkPaddle2Collision()` - The `serveBall()` function is already direction-agnostic (random left/right) — no changes needed for 2-player bouncing --- *Phase: 01-foundation* *Completed: 2026-03-10*