A lightweight 2D rigid-body physics engine built from scratch — circles, wall bounce, impulse resolution and a slingshot game — compared against Matter.js.
The working code for the article "How Does Game Physics Work? Writing a Physics Engine From Scratch on Canvas". It contains three things:
- Mini 2D physics engine (
src/engine/) — dependency-free, ~120 lines: Euler integration, circle-circle collision (impulse), wall bounce, contact events. - Slingshot game (
src/main.ts) — fling the black ball with drag-and-release, break the ring of stones, rescue the pink ball in the middle. A hard hit breaks a stone, a slow one bounces. - Matter.js comparison (
src/matter-demo.ts) — the same scene with an off-the-shelf engine.
npm installnpm run devhttp://localhost:5173/→ the game with the from-scratch enginehttp://localhost:5173/matter.html→ the Matter.js version
How to play: Click the black ball, pull, release. It flies in the direction opposite to the pull (slingshot logic). Stones only break on a fast hit (threshold: 400 px/s); on a slow hit the ball bounces. Touch the pink ball and you win.
npm test14 unit tests verify the engine's physics claims: Euler integration, static bodies staying put, wall bounce (the bounciness ratio), impulse resolution, overlap correction, the "don't interfere with separating bodies" rule and the severity report of contact events.
src/
engine/
vec.ts # Vec2 helpers (add, sub, scale, dot, normalize)
body.ts # Body + createBody (the invMass trick)
world.ts # World.step: integration → walls → collisions
main.ts # Game: slingshot, ring of stones, rules (in the contact events)
matter-demo.ts# The same scene with Matter.js
tests/
engine.test.ts
- While dragging,
pointermove/pointerupare listened for on window; listen on the canvas and a slingshot released outside the canvas stays stuck. - In Matter.js a thin wall + high speed = tunneling (the ball passes through the wall). The fix: a thick wall + a cap on the launch speed.
- TypeScript
- Vite
- Vitest
- HTML5 Canvas 2D
- Matter.js (comparison demo only)
MIT