Files
2026-09-01 14:37:28 +10:00

87 lines
6.6 KiB
Markdown
Raw Permalink 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.
# Implementation Plan — Times Table Invaders
## 1. Game name
**Times Table Invaders** — a Space Invaders homage that conveys both multiplication practice and descending aliens. (Alternatives: "Alien Arithmetic", "UFO Down!", "Cosmic Times".) Used in `<title>`, the welcome overlay, and the faded sky title.
## 2. Deliverables
```
/workspace/
├── README.md
├── PLAN.md ← this plan
├── index.html ← single entry point (links style.css + game.js)
├── style.css ← layout, HUD, overlays, responsive rules
└── game.js ← all logic; vanilla JS, classic <script> tag (no modules/build)
```
No dependencies, no build step; must work when `index.html` is opened directly (`file://`).
## 3. Technical decisions
- **Scene on `<canvas>`** (stars, faded title, UFOs, ground, houses, cannon, laser, explosions): full cartoon control, easy particle effects, one render loop.
- **HUD + overlays in DOM**: input / Fire button / score below the scene; welcome and game-over overlays.
- **Fixed 3:4 portrait aspect** for the scene, centered and height-capped on desktop → responsive from phones to desktops with no layout branches.
- **Virtual coordinate system** (~90 × 120 units) + one uniform scale + devicePixelRatio-aware backing store → resizing is trivial; all game logic is resolution-independent.
- **rAF loop with delta time clamped to 50 ms** (prevents jumps after tab switches).
- **localStorage** key `tti.leaderboard.v1` = JSON array of top-3 `{name, score}`; wrapped in try/catch for private browsing.
## 4. Architecture (game.js)
- `CONFIG` object with every tunable: phase table, spawn/speed ramps, sizes, timings.
- One `Game` state object: `ufos[]`, `stars[]`, `houses[]`, `particles[]`, laser/cannon animation state, score, elapsed time; states `WELCOME | PLAYING | GAME_OVER`.
- Plain-function systems, each with update + draw: starfield, spawner/mover, difficulty, shot queue, input, leaderboard, renderer.
## 5. Game mechanics (precise)
- **UFO generation**: pick table `b` from the currently unlocked set, multiplier `m` ∈ 2..12 (table 1 excluded entirely); display `b × m` or `m × b` (random order); store product. Radius ≈ 9 units; text sized to stay readable at a 360 px phone width.
- **Motion**: `y += speed·dt` with per-UFO speed = phase base × rand(0.9–1.1); wobble `x = baseX + A·sin(ωt+φ)`, A ∈ [1.5, 3] units (the "ondulating trajectory").
- **No overlap**: on spawn, reject x positions within `r₁+r₂+2` of any live UFO; up to 8 retries, else defer the spawn. Multiplications always stay readable.
- **Shooting**: on submit value `v`, all UFOs with product == v enter a shot queue (bottom-most first, ~200 ms apart = "rapid succession"); +1 score each. No match → cannon still fires as miss feedback.
- **Game over**: any UFO's bottom reaches the ground line → freeze scene, show overlay.
## 6. Difficulty progression (elapsed time; all values tunable in CONFIG)
| Phase | At | Tables added | Spawn interval | Fall speed |
|---|---|---|---|---|
| 1 | 0 s | 2, 10 | 4.0 s | 10 u/s |
| 2 | 60 s | +4, 5 | 3.5 s | 12 u/s |
| 3 | 150 s | +3, 7, 8, 9 (+6*) | 3.0 s | 14 u/s |
| 4 | 300 s | +11, 12 | 2.6 s | 16 u/s |
After phase 4: continuous gradual ramp — spawn interval eases down to a 1.4 s floor, fall speed rises toward ~40 u/s cap.
\* Table 1 is excluded from all phases (user request). The README also omits table 6; assumption: **6 joins phase 3**.
## 7. UI spec
- **Sky**: night gradient; ~90 stars regenerated each game with pulsating alpha (random phase/speed per star); faded game title centered in the sky (~7% white).
- **Ground** (bottom strip of canvas): 3–5 simple cartoon houses randomized per game; cannon in the foreground, centered.
- **Cannon animation**: on shot → recoil + muzzle flash; laser beam (bright core + wide glow) from barrel tip to target for ~150 ms per hit; explosion = 18–26 fading particles + expanding ring (~450 ms), UFO disappears quickly.
- **HUD below the scene**: `[ input ] [ Fire ] [ score ]`. Input: `inputmode=numeric`, digits-only filter, hard cap at 3 digits (extras ignored), auto-focused on load/start/after each submit, Enter or Fire submits, field cleared after submit. Score counter sits next to the Fire button.
- **Responsive**: scene width = `min(100%, height-derived)`; touch-friendly targets (≥44 px); works 360×640 → 1920×1080.
## 8. Leaderboard & screens
- **Top 3** in localStorage. On game over, if score > 0 and qualifies (fewer than 3 entries or strictly greater than the lowest) → congratulation popup with a name field (≤16 chars, required) → insert at correct rank, evict lowest, persist.
- **Welcome overlay**: game title, 2–3 line instructions, leaderboard table (rank / name / score, with "no scores yet" empty state), Start button → regenerates stars/houses, resets state, focuses input, starts the loop.
## 9. Implementation steps
1. Write this plan to `/workspace/PLAN.md`.
2. Scaffold `index.html` + `style.css` + `game.js` (layout, canvas, HUD, both overlays); verify layout in a browser.
3. Engine: virtual coords, DPR-aware resize handling, rAF loop with clamped dt, state machine.
4. Background: starfield + pulsation, faded title, ground/houses, cannon idle drawing.
5. UFOs: phase-based spawning, wobble motion, overlap-safe placement, cartoon UFO rendering with `a × b`.
6. Shooting: input rules, match detection, sequential shot queue, laser/recoil/flash, explosion particles, score updates.
7. Post-phase-4 gradual speed/spawn ramp.
8. Game-over flow + leaderboard persistence + name-entry popup.
9. Welcome overlay wiring (Start, leaderboard display).
10. Responsive pass + edge cases (empty input, rapid double-Enter, resize mid-game, `file://`), then run the QA checklist.
## 10. QA checklist (manual)
- Opens from `file://`, no console errors, vanilla JS only
- Correct answer destroys matching UFO(s); multiple matches all destroyed in sequence; +1 each
- Wrong/empty input: cannon fires, nothing hit, field cleared and refocused
- Digits-only enforcement; >3 digits ignored; Enter and Fire both submit
- Early game shows only 2/10 tables; later phases add tables; late game gets faster
- UFOs never overlap illegibly; wobble visible; stars pulse and differ per game; faded title present
- Cannon animates on shot; explosions quick
- A landed UFO ends the game
- Top-3 popup asks for a name; leaderboard ranks/saves/evicts correctly and persists across reloads
- Playable at phone and desktop sizes
## Flagged assumptions
1. Name: **Times Table Invaders** (alternatives listed in §1).
2. Table 6 included in phase 3 (the README's phase list omits it); table 1 excluded from all phases.
3. No audio — out of scope (possible WebAudio stretch goal).