README
Gravity Dots
A physics-based puzzle game built on HTML5 Canvas 2D. Place gravity wells on a canvas, launch a particle, and manipulate its trajectory to hit targets using gravitational forces. Seven levels introduce progressively complex mechanics with wall obstacles and multi-well puzzles.
Delivered as a single self-contained HTML file with zero external dependencies. Includes procedural audio via Web Audio API.
Quick Start
src/gravity-dots.html in a modern web browser (Chrome, Firefox, Safari, or Edge)No installation, build step, or server required.
Installation
Prerequisites
- Modern web browser (Chrome, Firefox, Safari, Edge, latest versions)
- No Node.js or npm required for gameplay
- Optional: Node.js 18+ to run tests
Verification
Open src/gravity-dots.html in your browser. You should see:
- Level select screen with 7 buttons in a grid layout
- Each level shows: number, par (ideal well count), earned stars
- Clicking a level loads gameplay with space background, stars, nebula, and grid
Usage
Controls
| Input | Action | Context |
|---|---|---|
| Click (canvas) | Place gravity well | Before launch, wells < 3 |
| Click (well) | Remove gravity well | Before launch |
| Space | Launch particle | After placing wells, before launch |
| R | Reset level | Anytime during gameplay |
| M | Toggle mute on/off | Anytime (persists in localStorage) |
Level Select Screen
Click any level button to load that level. All 7 levels are always available — no locks.
Gameplay
Star Rating
- 3 stars: Wells used <= par
- 2 stars: Wells used = par + 1
- 1 star: Wells used > par + 1
Audio
All audio is generated procedurally via Web Audio API — no external audio files.
| Event | Sound | Frequency |
|---|---|---|
| Place well | Whomp | 110 Hz, 0.3 sec decay |
| Launch particle | Rising tone | 400-600 Hz sweep, 0.4 sec |
| Hit target | Victory jingle | A4-B4-C5-D5, 0.8 sec |
| Hit target | Chime cascade | E6-G6-B6-E7, 0.6 sec |
| Stars earned | Star pings | G6 (1568 Hz), 0.1 sec each |
| Wall/miss | Thud | 80 Hz noise, low-pass 200 Hz |
Examples
Level 1 — Tutorial (Par: 1)
Target: Right side at (1100, 400)
Strategy: Place one blue well (0.5 mass) below the horizontal center.
The particle curves downward and hits the target.
Result: 3 stars (1 well used <= 1 par)
Level 3 — Intermediate (Par: 2)
Target: Bottom-right at (1100, 600)
Strategy: Place first well (blue, 0.5) to start curving particle down.
Place second well (purple, 1.0) to accelerate toward target.
Result: 3 stars (2 wells used <= 2 par)
Level 6 — Expert (Par: 3)
Target: Right at (1000, 300) with wall obstacles
Strategy: Use all three wells to navigate around walls:
1st (blue, 0.5) — initial curve
2nd (purple, 1.0) — mid-path correction
3rd (red, 2.0) — strong final pull to target
Result: 3 stars (3 wells used <= 3 par)
Level Design
| Level | Par | Wells Available | Walls | Difficulty |
|---|---|---|---|---|
| 1 | 1 | 1 weak (0.5) | None | Tutorial |
| 2 | 1 | 1 weak (0.5) | None | Tutorial |
| 3 | 2 | 1 weak + 1 medium | None | Intermediate |
| 4 | 2 | 2 weak + 1 medium | 1 wall | Intermediate |
| 5 | 2 | 1 weak + 2 medium | 2 walls | Intermediate |
| 6 | 3 | 1 weak + 1 medium + 1 strong | 2 walls | Expert |
| 7 | 3 | 1 weak + 1 medium + 1 strong | 3 walls | Expert |
Architecture
Dual-File Pattern
Pure-Function Logic Modules (src/*.js):
physics.js— Gravity, collision detection, particle movementgame-state.js— State management, well placement, star ratingsparticles.js— Trail points, spark particlesaudio.js— Web Audio API sound generationlevels.js— Level configurations (source of truth)game-logic.js— Re-exports all modules
src/gravity-dots.html):
- Contains identical game logic inlined in
<script>block - Adds Canvas rendering, input handling, animation loop
- Integrates all audio with mute toggle
- Pure HTML/CSS/JS — no build step, no dependencies
Physics Model
- Gravity constant (G): 50,000
- Effect radius: 150 px (gravity only within this distance)
- Formula: Force = (G x mass) / distance^2
- Particle speed: 400 px/sec initial horizontal velocity
- Timestep: Fixed 1/60 sec (60 FPS)
- Target hitbox: 32 px radius
Testing
Run All Tests
node --test tests/*.test.js159 tests across 5 test files, all passing:
| File | Tests | Coverage |
|---|---|---|
physics.test.js | 32 | Gravity forces, collisions, boundaries |
game-state.test.js | 44 | State management, wells, star ratings |
particles.test.js | 26 | Trails, sparks, pruning |
audio.test.js | 26 | Sound generation, frequencies, durations |
levels.test.js | 31 | Level data, dual-file sync verification |
Browser-Only Test Scenarios
These require manual verification in a browser:
- Level select screen renders 7 buttons with correct layout
- Well animations: pulsing ring, spiral distortion, vortex dots
- Particle trail: 3 overlapping semi-transparent lines
- Spark emission: 5-10 particles per frame
- Audio plays at correct events (well, launch, hit, miss)
- Screen shake on wall/miss collision
- Mute toggle works and persists
- Background: stars twinkle, nebula visible, vignette at edges
- Target: golden bullseye with pulsing animation
- 60 FPS performance during gameplay
File Structure
projects/010-canvas-game/3-development/
├── src/
│ ├── gravity-dots.html (Deployable game — open in browser)
│ ├── game-logic.js (Re-exports all modules)
│ ├── physics.js (Gravity, collisions)
│ ├── game-state.js (State management)
│ ├── particles.js (Trails, sparks)
│ ├── audio.js (Web Audio API sounds)
│ └── levels.js (Level configurations)
├── tests/
│ ├── physics.test.js
│ ├── game-state.test.js
│ ├── particles.test.js
│ ├── audio.test.js
│ └── levels.test.js
├── docs/
│ ├── README.md (This file)
│ └── lint-output.txt (Lint diagnostic output)
├── package.json
└── DELIVERABLES.md
Error Messages
| Situation | Behavior |
|---|---|
| Click when 3 wells placed | No effect, no sound |
| Space with no wells | No launch, no sound |
| Space during flight | Ignored |
| Particle off-screen | Thud + screen shake, press R to retry |
| Particle hits wall | Thud + screen shake, press R to retry |
| Invalid level number | Returns null, no crash |
Browser Compatibility
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Credits
Development Team
- Jordan Cruz (TDD, test suite)
- Taylor Singh (implementation, physics engine, audio integration)
- Riley Okafor (documentation)