Skip to content
animorio
IT
All components

Knock them all down

Games, PhysicsCanvas, GSAPAdvancedCompressed weight: Demo 21 KBGSAP 28 KBFreeDownload the zip

The fairground tin can alley, played for a discount code: six enamel-painted tins in a pyramid on a wooden shelf over a striped counter, and a cloth ball in a slingshot. Pull the ball back and let go, or let the button throw it; from there it is all real rigid-body physics: the tins spin, knock into each other, bounce and fall. Three balls: clear the shelf and the ticket with the code comes up.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Knock them all down</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the tin can alley of a shop's promotion: six painted tins stacked on a fairground shelf, a cloth ball in a
         slingshot. Pull the ball back and let go, or press Throw; the tins are rigid bodies that tumble, knock into
         each other, bounce and fall. Three balls: clear the shelf and the ticket with the code comes out -->
    <section class="game" aria-labelledby="game-title" data-game data-autoclic>
      <header class="game__head">
        <h2 class="game__title" id="game-title">Knock them all down</h2>
        <p class="game__rule">Three balls. Clear the shelf for 15% off.</p>
      </header>

      <div class="booth" tabindex="0" role="application" aria-roledescription="tin can alley"
           aria-label="Six tins on a shelf and a ball in a slingshot. Drag the ball back and let go to throw. With the keys: up and down aim, left and right set the strength, Enter throws."
           aria-describedby="game-say" data-booth>
        <canvas class="booth__scene" aria-hidden="true" data-scene></canvas>
        <canvas class="booth__fade" aria-hidden="true" data-fade></canvas>

        <!-- the prize: a fairground ticket that comes up when the shelf is clear -->
        <div class="ticket" data-ticket hidden>
          <div class="ticket__paper">
            <svg class="ticket__star ticket__star--l" viewBox="-10 -10 20 20" aria-hidden="true"><path d="M0-9l2.6 5.6 6 .7-4.4 4.1 1.2 6L0 4.4-5.4 7.4l1.2-6-4.4-4.1 6-.7z"/></svg>
            <svg class="ticket__star ticket__star--r" viewBox="-10 -10 20 20" aria-hidden="true"><path d="M0-9l2.6 5.6 6 .7-4.4 4.1 1.2 6L0 4.4-5.4 7.4l1.2-6-4.4-4.1 6-.7z"/></svg>
            <p class="ticket__kicker">Shelf cleared</p>
            <p class="ticket__prize" data-prize>15% off</p>
            <p class="ticket__line" data-prize-line>your whole order</p>
            <button class="ticket__code" type="button" data-copy>
              <span class="ticket__code-text" data-code>TINCAN15</span>
              <span class="ticket__copy" data-copy-label>Copy</span>
            </button>
          </div>
        </div>
      </div>

      <div class="bar">
        <div class="say" aria-live="polite" id="game-say">
          <p class="say__big" data-say>Pull the ball back and let go</p>
          <p class="say__small" data-say-small>Three balls left</p>
        </div>
        <button class="throw" type="button" data-throw><span class="throw__face"><span class="throw__label" data-throw-label>Throw</span></span></button>
      </div>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

45 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “Knock them all down” from Animorio and fit it into my site

What it does

On a white background the title Knock them all down and the rule (Three balls. Clear the shelf for 15% off.), then the scene drawn on a canvas: on the right a fairground counter in red and cream stripes between two gilded posts, with a scalloped valance and a pine shelf on top; on the shelf six tins in a pyramid, three, two and one, each painted in enamel in its own way (stripes, zigzag, stars, diamonds, bands, waves), with its tin rim, the lid seen from above and a few scratches. On the left a wooden slingshot with the cloth ball in its pouch and two more balls on the floor. You grab the scene with a finger or the mouse and pull back: the ball goes with the pouch, the bands stretch and thin, and a row of dashes shows the way it will go. Let go, the ball leaves and the empty pouch snaps back and forth; Throw does the same with a pretend hand that aims at the lowest tin. From there the tins are real rigid bodies: the ball hits them, they spin end over end and round their own axis, knock into each other, bounce on the shelf and on the floor, fall to the side or fly off fading; the ball squashes in the hit and the scene shakes a touch. When everything is still the line says how many fell (Three down, three to go) and the next ball hops from the floor into the slingshot. If the shelf is clear the raffle ticket comes up with its stars turning, 15% off written wide and the code TINCAN15 to copy, while little paper stars fly from behind it; if after three balls something still stands the line says how many tins held on and the button becomes Try again. Play again or Try again put the tins back in a pyramid with an arc and a little bounce.

How it works

A small rigid-body engine

Every tin is a rectangle with mass and inertia, the ball a circle, the shelf, the counter and the floor bodies that do not move. At each step of 1/120 of a second gravity pulls, then the contacts are found: between two rectangles the face that overlaps least is taken, the edge of the other is clipped against its sides and up to two points remain; for the ball, the point of the rectangle nearest its middle. Each contact has a key made of the edges it came from.

Impulses that remember

Twelve passes over all the contacts: an impulse along the normal that never pulls (it only pushes) and one along the surface limited by friction, with a small extra push that takes the overlap out. Last step's impulses start again from the same key, and that is what keeps the pyramid still. A hard knock bounces (BOUNCE), the cloth ball hardly at all; whatever stays still for half a second goes to sleep, and wakes when something moving touches it or when its support goes.

The tin, a real cylinder

The label is painted once on a canvas two turns long and then wrapped round in 24 strips: each strip takes the piece of label at the angle asin(x / radius), so at the sides the pattern narrows as on a real tin, and drops a little with the cosine to follow the curve of the rim seen from above. Lit side, dark side and the sharp shine are worked out from the normal of each point against the light, with the tin's angle at that moment; the lid shows on the side that looks up.

The slingshot and the ball's way

Pulling, the pouch follows the finger, limited to PULL pixels, never down among the waiting balls nor out of the scene; the ball leaves with a speed of POWER for every pixel pulled. The dashes are the same integration as the physics, step by step, so the ball takes exactly that way until it touches something. Throw and the keys look for the angle that takes the ball onto the chosen tin, trying a quarter of a degree at a time.

The ticket, the keys and the preview

Shelf clear: the ticket comes up with elastic.out, the stars turn, the prize widens with Anybody's wdth axis and little paper stars fall with gravity and air drag. With the scene in focus the arrows aim and set the strength, Enter throws. A click from a script (the library's preview) makes two throws that are always the same, because the physics steps are fixed and the result is the same each time: the pyramid falls, the ticket comes up, then everything goes back.

Values to change

NameFileDefaultWhat it changes
BALLSscript.js3How many balls a go, from one to four.
GRAVITYscript.js1500How hard everything falls, in pixels a second squared.
POWERscript.js14.2How fast the ball leaves for every pixel the band is pulled back.
PULLscript.js66How far the band can be pulled back, in pixels.
BOUNCEscript.js0.3How much the tins bounce off each other, the shelf and the floor: 0 not at all.
GRIPscript.js0.42How much the tins grip what they touch as they slide.
HEAVYscript.js5How many times heavier than a tin the cloth ball is.
AIMscript.js5How far, in pixels, Throw may miss the tin it aims at.
TINSscript.js[['#d8333b', '#f8ecd4', 'stripes'], …]The paint of the six tins, from the bottom row up: the colour, the second colour and the pattern (stripes, zigzag, stars, diamonds, bands, waves).

Try them in the Playground

When to use it

For an online shop's promotion, the page of a fair or a village festival, the pop-up that gives away a discount, a newsletter with a prize, the site of a place that lets its customers play: anywhere a discount code can be won by playing instead of just handed out.

On phones

The scene is at most 340 pixels wide and narrows with the screen, but the physics always works in its own units (340 by 320), so it throws and falls the same. The finger grabs the scene and pulls the slingshot without scrolling the page (touch-action none), and the ball never leaves the edges.

With reduced motion

No flight or fall to watch: the throw is worked out at once and the scene fades from how it was to how it ends; the next ball appears in the slingshot with a fade, the ticket appears without pops and the pyramid goes back with a fade. The slingshot can still be pulled by hand, with the dashes.

Pitfalls

  • Without remembering last step's impulses the pyramid trembles and slumps on its own: each contact has a key made of the edges it came from, and starts again from the impulse it had.
  • The still pyramid must stay still for ever: the tins sleep until something moving touches them, but a tin asleep on top of one that flew away has to wake, or it stays hanging in the air.
  • A cloth ball rolling on a tin lying down never stops and keeps awake everything it touches: in contact with something it loses its spin and speed at once, like a beanbag.
  • With the same bounce as the tins the ball came back off the bottom of the pyramid like a rubber ball: between two moving bodies the lower bounce counts.
  • For the preview the two throws must always end the same way: the physics takes fixed steps of 1/120 of a second, whatever the screen's speed, and the random bits (the label's spin, the shake) never touch the physics.
  • Pulled all the way down the ball ended up among the ones on the floor and out of the left edge: the pouch has a limit below and one on the left, and Throw's aim leaves out the angles that would cross them.

Libraries

GSAP 3.15.0, Anybody (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 21 KB; the libraries: GSAP 28 KB.

Testing

Tested on 17 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components