Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Coin Jackpot

A single-file three.js coin explosion. Coins burst out of the centre of the screen straight into the camera, collide with each other in real time, and catch the light like polished gold. No build step, no npm install, no bundler — one index.html you can open by double-clicking it.

Drop in any .glb and it becomes the coin.

▶ Live demo


Features

  • Real-time collision physics. A hand-rolled solver — gravity, impulse resolution with configurable restitution, spatial-hash broad phase, fixed sub-steps at 1/120 s — so hundreds of coins bounce off each other instead of passing through.
  • Instanced rendering. Every coin is one InstancedMesh instance: a single draw call for the whole swarm, 700-coin pool, 60 fps on a mid-range GPU.
  • Procedural HDR environment. No external .hdr download — the environment map is painted to a canvas and run through PMREMGenerator at startup, so gold has something real to reflect.
  • Bring your own model. Drag a .glb / .gltf anywhere on the page, or use the Load your own button. Multi-mesh files are flattened and merged automatically.
  • Built for video work. Green-screen and true-alpha background modes, plus one-click WebM capture straight from the canvas — drop the clip into After Effects / Premiere and key it out.
  • Bounded lifetime. Every coin is hard-capped at 6 seconds and recycled through a pool, so the scene never accumulates cost no matter how long it runs.
  • Works on phones. Below 820px the control panel becomes a bottom sheet behind a hamburger button — swipe it down or tap the backdrop to dismiss. Touch builds also drop the pixel ratio, halve the bloom resolution and start at a lighter coin count, so a mid-range phone still holds a steady frame rate.
  • Zero dependencies to install. three.js is pulled from a CDN via an import map; the demo model is inlined as base64, so the page also works from file://.

Quick start

git clone https://github.com/USERNAME/coin-jackpot.git
cd coin-jackpot

Then open index.html in a browser. That's it — there is no build step.

To serve it locally instead (needed only if you swap the inline model for a fetched file):

npx serve .          # or: python3 -m http.server 8080

Controls

Control What it does
Coins per second Emission rate, 2–160
Animation speed Time scale for the whole simulation, 0.15×–2.5×
Launch power Initial velocity out of the emitter
Gravity Downward acceleration; 0 gives a weightless space-drift look
Coin size World radius — also drives the collision radius and the emitter spread
Spin Angular velocity on spawn and the tumble kick on impact
Bloom UnrealBloomPass strength
Restitution Collision bounciness, 0 = fully inelastic, 0.9 = superball
Roughness Gold material roughness — low is mirror-like, high is brushed
Background Dark / green screen / transparent alpha
Key Action
H Hide or show the control panel (hamburger button on touch devices)
Space Pause / resume
B Fire an extra burst

Using your own coin

Drag any .glb or .gltf onto the page. The loader:

  1. bakes world matrices into every mesh it finds,
  2. strips everything down to position / normal / uv and de-indexes it, so merging is safe for arbitrary files,
  3. merges the parts into one geometry, recenters it, and measures its bounding sphere.

That bounding sphere is what the Coin size slider scales against, so a model authored in millimetres and one authored in metres both land at the same on-screen size. Textures and materials from the file are discarded on purpose — every instance shares one gold MeshStandardMaterial, which is what keeps the whole swarm at a single draw call.

To bundle a different model permanently, base64-encode it and replace the DEMO_GLB constant in index.html:

base64 -w0 my-coin.glb

How it works

The simulation is deliberately not a physics-engine integration. Coins are treated as spheres with equal mass:

  • Broad phase — a spatial hash keyed on floor(pos / cellSize), cell size equal to one coin diameter, so each coin only tests the 27 cells around it.
  • Narrow phase — sphere overlap, split depenetration (clamped so a dense spawn cluster can't launch coins out of frame), then a standard impulse j = -(1 + e)·v_rel / (1/m₁ + 1/m₂) along the contact normal.
  • Rotation — quaternion integration from an angular-velocity vector, with a random tumble impulse added on each impact and a cap to keep things readable.
  • Sub-stepping — the frame delta is split into at most six fixed steps so the solver stays stable when you push Animation speed to 2.5× or the tab drops frames.

Emission is a cone with a strong +Z bias from a small disc at the world origin; coins retire when they pass the camera plane, leave the frustum, or hit the 6-second cap, and their pool slot is immediately reusable.

Browser support

Any browser with WebGL 2 and ES module import maps — Chrome / Edge 89+, Firefox 108+, Safari 16.4+. WebM capture uses MediaRecorder and is Chromium-only in practice; the button disables itself elsewhere.

License

MIT — see LICENSE. The bundled demo coin in assets/ is included as sample content; swap it for your own artwork in anything you ship.

About

Physics-driven three.js coin explosion in a single HTML file. Drop in any .glb — get a jackpot burst straight into the camera.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages