Matter.js Plinko Board with Live Bell-Curve Histogram — Free Game Snippet

Matter.js Plinko Board with Live Bell-Curve Histogram · Games · Plain HTML, CSS & JS · Live preview

CategoryGames

What's included

Features

Triangular peg grid
11 rows of offset static circles.
Slot sensors
isSensor bodies counted with collisionStart.
Independent balls
Negative collision group, no ball-to-ball hits.
Binomial overlay
Expected share per slot drawn as ticks.
Live histogram
Actual landing shares as bars.
Multiplier scoring
Rare edge slots pay the most.
Body cleanup
Landed balls removed for performance.
Queued drops
Timed release for large batches.

About this UI Snippet

Plinko and the Galton Board — Probability You Can Watch With Matter.js

Screenshot of the Matter.js Plinko Board with Live Bell-Curve Histogram snippet rendered live

A Plinko board is a game show favourite and, underneath, a Galton board: a demonstration that many independent random events add up to a bell curve. Each peg sends a ball left or right; after eleven rows, landing in the middle is common and the edges are rare. This snippet plays the game and draws the statistics while it does.

Pegs as coin flips

The pegs form a triangle: each row has one more peg than the row above, offset by half a gap. The number of rightward bounces across eleven rows decides the slot — if each bounce is a fair coin flip.

Real bounces aren't fair coins

Here's the interesting part: with pure physics, they aren't. A ball keeps some sideways momentum from the previous peg, so free bouncing drifts outward and the edge slots fill up many times more often than probability predicts. (Tuning restitution alone doesn't fix it: lively balls skip columns, dead balls roll along the pegs.) So on every ball–peg collision the snippet sets the ball's sideways speed to a fixed value in a random direction — one fair left/right decision per peg — and leaves gravity and collisions to do the rest. That's the idealised Galton board the maths describes, and the histogram shows it matching.

Guard walls

Two slanted walls run parallel to the edges of the peg triangle, half a gap outside the outermost pegs. The gap is narrower than a ball, so a ball knocked wide comes back into play.

Sensors count landings

Each slot has an invisible sensor body (isSensor: true). Sensors take part in collision detection but produce no physical response, so balls pass straight through while Events.on(engine, 'collisionStart') reports the contact. The handler finds which body in the pair is the ball and which is the sensor, counts the ball once, adds the slot's multiplier to the score, and removes the ball shortly after so hundreds of drops stay smooth.

Collision groups keep balls independent

In a real board, balls knock into each other and pile up. Giving every ball the same negative collisionFilter.group means bodies in that group never collide with each other, while still colliding with pegs and walls. Each ball's path stays independent, which is what the statistics assume.

Histogram versus theory

Below the board, yellow bars show the actual share of balls in each slot, drawn in an SVG whose viewBox matches the canvas width so every column lines up with its slot. A pink tick shows the expected share from the binomial distribution, C(n, k) / 2ⁿ. After fifty or a hundred drops the bars settle around the ticks — the law of large numbers in action. The multipliers are highest at the edges because those slots are the least likely.

Drop queue

Drops are queued and released every 110 ms so a "Drop 50" doesn't spawn fifty overlapping balls at once.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI assistant like Claude and ask it to explain collision groups versus categories and masks. Ask it to add a risk slider that changes the multipliers, sound effects on peg hits, a bet-and-balance game loop, or a comparison mode that lets balls collide so you can see how the distribution changes. It can also compute the expected score per ball from the multipliers and binomial probabilities.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a Plinko (Galton board) game with Matter.js 0.20 (from a CDN) in plain HTML, CSS and JavaScript on a dark purple theme.

Requirements:
- A triangle of static round pegs (11 rows, each with one more peg than the last), slot dividers, a floor and side walls.
- One invisible static sensor per slot; count landings in a collisionStart handler, counting each ball once, adding the slot's multiplier to a score, and removing landed balls after a short delay.
- Balls share a negative collision group so they never collide with each other; drop them near the top centre with a small random offset.
- Make every peg a fair coin flip: on each ball–peg collision, set the ball's horizontal velocity to a fixed speed in a random direction (and cap its downward speed), and add guard walls parallel to the peg triangle's edges, half a gap outside the outermost pegs.
- Buttons to drop 1, 10 or 50 balls through a timed queue, and to reset; drop 20 balls on load.
- Only inner slot dividers: the two edge slots extend to the side walls (with their sensors widened to match) so balls that bounce wide still land in an edge slot.
- In the renderer's afterRender event, draw each slot's multiplier and count; below the canvas, an SVG histogram (viewBox matching the canvas width) with a bar for the actual share of balls per slot, a tick at the binomial expected share C(n, k)/2ⁿ, and percentages, plus a dropped counter.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

Requires
<div class="pk">
  <div class="pk-top">
    <div>
      <h2>Plinko</h2>
      <p>Each peg is a coin flip. Drop enough balls and the landing counts trace a bell curve.</p>
    </div>
    <div class="pk-score"><span id="pkScore">0</span><small>points</small></div>
  </div>
  <div class="pk-stage" id="pkStage"></div>
  <svg class="pk-hist" id="pkHist" viewBox="0 0 600 96" role="img" aria-label="Landing histogram"></svg>
  <div class="pk-controls">
    <button type="button" data-drop="1">Drop 1</button>
    <button type="button" data-drop="10">Drop 10</button>
    <button type="button" data-drop="50">Drop 50</button>
    <button type="button" id="pkReset" class="ghost">Reset</button>
    <span class="pk-count" id="pkCount" aria-live="polite"></span>
  </div>
</div>

Step by step

How to Use

  1. 1
    Watch the opening dropTwenty balls fall on load.
  2. 2
    Drop moreDrop 1, 10 or 50; balls are queued so they don't overlap.
  3. 3
    Read the histogramYellow bars are actual shares; pink ticks are the binomial expectation.
  4. 4
    Track your scoreEach landing adds its slot's multiplier.
  5. 5
    ResetClears balls, counts and score.

Real-world uses

Common Use Cases

Casual games
A satisfying Plinko mini-game.
Statistics lessons
The central limit theorem made visible.
Learning Matter.js
Sensors, events and collision filtering.
Giveaways and promos
Prize boards with weighted slots.
Data storytelling
Explain randomness and distributions.
Related: Matter.js Collision Filter Categories
Related: Histogram
A standalone histogram chart: Histogram.

Got questions?

Frequently Asked Questions

Put a static body with isSensor: true in the slot and listen to Events.on(engine, 'collisionStart'). Each event has pairs; check whether one body is your sensor and the other is a ball.

Give them the same negative collisionFilter.group value. Bodies sharing a negative group never collide with each other but still collide with everything else.

Each peg is roughly a 50/50 left-or-right bounce, and the final slot depends on how many bounces went right. That count follows a binomial distribution, which approaches a normal (bell) curve as the number of rows grows.

Remove bodies once they've landed with Composite.remove, and release drops over time rather than all at once.

No. Balls carry sideways momentum from peg to peg, so pure physics drifts toward the edges. This snippet makes each peg a fair coin by setting the sideways velocity to a fixed speed in a random direction on every peg hit. Remove that handler to see how different unmodified physics is.