Back to Gravity Dots

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

  • Open src/gravity-dots.html in a modern web browser (Chrome, Firefox, Safari, or Edge)
  • Click a level button (1-7) to start
  • Click the canvas to place gravity wells (blue/purple/red dots)
  • Press Space to launch the particle
  • Watch it curve toward the gravity wells — listen for the SFX
  • Try to hit the golden target
  • Complete the level with as few wells as possible to earn stars
  • 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

    InputActionContext
    Click (canvas)Place gravity wellBefore launch, wells < 3
    Click (well)Remove gravity wellBefore launch
    SpaceLaunch particleAfter placing wells, before launch
    RReset levelAnytime during gameplay
    MToggle mute on/offAnytime (persists in localStorage)

    Level Select Screen

    Click any level button to load that level. All 7 levels are always available — no locks.

    Gameplay

  • Place Wells: Click the canvas to place gravity wells (max depends on level)
  • - Wells are color-coded by mass: Blue (0.5), Purple (1.0), Red (2.0) - Mass is assigned per level in placement order (you don't choose mass) - Cannot place wells inside wall obstacles - Each placement plays a "whomp" sound (110 Hz, 0.3 sec)

  • Launch: Press Space to launch the particle from the left edge
  • - Particle starts at (32, 400) moving at 400 px/sec rightward - A rising-tone SFX plays (400-600 Hz sweep) - All wells lock in place — no placement or removal after launch

  • Hit Target: Particle center must enter the golden target (32 px radius)
  • - Level complete! Victory jingle + chime cascade + star pings play - Star rating screen shows your score

  • Fail: Particle off-screen or hits a wall
  • - "Thud" SFX plays + screen shakes (5-10 px, 0.2 sec) - Press R to reset and try again

    Star Rating

    • 3 stars: Wells used <= par
    • 2 stars: Wells used = par + 1
    • 1 star: Wells used > par + 1
    Stars are saved to browser localStorage and persist across sessions.

    Audio

    All audio is generated procedurally via Web Audio API — no external audio files.

    EventSoundFrequency
    Place wellWhomp110 Hz, 0.3 sec decay
    Launch particleRising tone400-600 Hz sweep, 0.4 sec
    Hit targetVictory jingleA4-B4-C5-D5, 0.8 sec
    Hit targetChime cascadeE6-G6-B6-E7, 0.6 sec
    Stars earnedStar pingsG6 (1568 Hz), 0.1 sec each
    Wall/missThud80 Hz noise, low-pass 200 Hz
    Press M to toggle mute. Mute state persists across sessions.


    Examples

    Level 1 — Tutorial (Par: 1)

    shell
    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)

    shell
    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)

    shell
    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

    LevelParWells AvailableWallsDifficulty
    111 weak (0.5)NoneTutorial
    211 weak (0.5)NoneTutorial
    321 weak + 1 mediumNoneIntermediate
    422 weak + 1 medium1 wallIntermediate
    521 weak + 2 medium2 wallsIntermediate
    631 weak + 1 medium + 1 strong2 wallsExpert
    731 weak + 1 medium + 1 strong3 wallsExpert

    Architecture

    Dual-File Pattern

    Pure-Function Logic Modules (src/*.js):

    • physics.js — Gravity, collision detection, particle movement
    • game-state.js — State management, well placement, star ratings
    • particles.js — Trail points, spark particles
    • audio.js — Web Audio API sound generation
    • levels.js — Level configurations (source of truth)
    • game-logic.js — Re-exports all modules
    Deployment File (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

    bash
    node --test tests/*.test.js

    159 tests across 5 test files, all passing:

    FileTestsCoverage
    physics.test.js32Gravity forces, collisions, boundaries
    game-state.test.js44State management, wells, star ratings
    particles.test.js26Trails, sparks, pruning
    audio.test.js26Sound generation, frequencies, durations
    levels.test.js31Level 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

    shell
    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

    SituationBehavior
    Click when 3 wells placedNo effect, no sound
    Space with no wellsNo launch, no sound
    Space during flightIgnored
    Particle off-screenThud + screen shake, press R to retry
    Particle hits wallThud + screen shake, press R to retry
    Invalid level numberReturns null, no crash

    Browser Compatibility

    • Chrome 90+
    • Firefox 88+
    • Safari 14+
    • Edge 90+
    Requires: HTML5 Canvas, Web Audio API, ES6, localStorage


    Credits

    Development Team

    • Jordan Cruz (TDD, test suite)
    • Taylor Singh (implementation, physics engine, audio integration)
    • Riley Okafor (documentation)
    Built for Dark Factory Corp as Project 010 — Canvas Physics Puzzle Game.

    © 2026 Jonathan Leahy · v1.0.1