Rainbow Jelly Bear

jellybear

OpusTerra
Opus$13.16 · 39m41s
Claude Opus 5.5$13.16 · 39m41s
Claude Opus 5.5 $13.16 · 39m41s
Winner
Terra$4.15 · 25m00s
ChatGPT-6.1 Terra$4.15 · 25m00s
ChatGPT-6.1 Terra $4.15 · 25m00s
CheapestFastest

Opus wins.

Remix in Claude

The prompt

Build **"Rainbow Jelly Bear"**: a real-time, interactive 3D **giant rainbow gummy bear** that people **poke**, **squish**, **bite**, **feed** and **bury under a rain of small gummy bears**, as ONE self-contained HTML file with **synthesised sound**.

It should feel like a glossy candy commercial shot in macro: the big bear heavy, wobbly and translucent like real gummy candy, and pressing Pour should be pure joy: a clattering rain of tiny bears that bounce, squash, pile up and make the big one jiggle.

## Tech

- three.js r170 with `WebGPURenderer` (automatic WebGL2 fallback). Load it with an importmap from jsDelivr: map "three", "three/webgpu" and "three/tsl" to `https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.webgpu.min.js`, and "three/addons/" to `https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/`. These are the **only** network requests allowed: no other libraries, fonts, images, models, textures or audio files. Use TSL node materials. Physics and simulation are your own code (no physics libraries).
- Start with `<!doctype html>`, `<meta charset="utf-8">` and a viewport meta tag. System font stacks only.
- It must run inside `<iframe sandbox="allow-scripts allow-pointer-lock">` (no `allow-same-origin`): `localStorage` and cookies throw there, so wrap every storage access in `try/catch` and keep values in memory. No `alert`, pop-ups, microphone or top-level navigation.
- Fixed simulation timestep (120 Hz) with bounded substeps, decoupled from frame rate; on a slow frame, drop simulation time rather than exploding. Let the big bear sleep once fully at rest (skip the solver) and every small bear sleep on its own once it stops; wake on any input or contact.
- Preallocate every buffer, geometry and material at start-up, sized for the caps below (small bears, bites, pieces); nothing is created during interaction, pouring and biting included.
- A quality scaler that lowers pixel ratio, then shadows, then post effects, then the small-bear cap when frames get slow, never the physics feel. Target 60 fps on a mid-range phone **with 200 small bears on screen**.
- Known three r170 pitfalls, avoid them:
  - the scene background is drawn after transparent objects: draw the backdrop as a mesh (or give transparent objects `depthWrite: true`);
  - never `.clone()` a `CanvasTexture` (the clone uploads black);
  - create every `InstancedMesh` at its full count and never draw one with fewer than 2 instances (wrong-size uniform buffer, black screen): park unused instances out of sight at scale 0 instead of lowering `count`;
  - never let a helper overwrite a shared temp vector its caller still uses;
  - on WebGL2 an `InstancedMesh` of roughly 250-1000 instances keeps its matrices in a 16 KB uniform block and fails to compile: keep instanced meshes under 250 (or above 1000).

## Priorities

Build it in this order, and finish each tier properly before starting the next. A polished tier 1 beats a broken everything.

1. **Must be excellent:** the big bear's wobble (heavy, slow, ears and arms lagging the body); the gummy material (translucent rainbow, glossy, colour deepening with thickness); the rain of small bears (they bounce, squash, dent the big bear and pile up without jitter); the demo mode.
2. **Must work:** Bite, Feed and growing, Shake, Drop, Empty, throwing small bears by hand, the sliders and colour presets, sound, the interface.
3. **Polish:** coloured light through the jelly, the Sugar coating, the Easter egg, the cinema mode.

Never ship a feature half-working: if something from tier 3 can't be done well, leave it out cleanly.

## The bears

- **Tray:** a wide, shallow, round ceramic tray (diameter about 2.8x the big bear's width, rim height 0.12) in a soft warm grey glaze, on a light warm-oak table. The rim keeps the small bears in; a soft glaze, never a mirror: its highlights must never outshine the candy.
- **Big bear:** the classic gummy-bear silhouette, standing, height 1.0: a round head (width 0.46) with two small round ears, a pear-shaped body, two short arms held forward, two short stubby legs with flat feet on the tray. Soft rounded everything, no sharp edges. A **moulded face and belly** like real gummy bears: shallow eyes, a little snout and nose, a smile line, a belly button and paw pads, all as gentle relief in the surface (they deform with the jelly), plus a faint mould seam running around the silhouette.
- **Rainbow:** six horizontal bands through the **whole body**, from the feet up: red, orange, yellow, green, blue, purple (the ears purple). Each band a slightly different height, with soft, slightly wavy boundaries and a thin brighter line where two colours meet. Colour deepens where the bear is thicker, so the belly and head are richer than the ears, arms and edges.
- **Inside:** 40-80 tiny suspended air bubbles (instanced, they move with the jelly) and a faint internal grain, so depth reads.
- **Small bears:** the same silhouette at height 0.12, in classic gummy colours: red, orange, yellow, green, clear (white-ish) and, rarely (1 in 25), a tiny rainbow one. Each one slightly different in tint and a few percent in size. Cap **200** small bears on screen; past the cap the oldest one that is at rest shrinks away smoothly.
- **Dispenser:** a glass candy jar hung upside down above the bear, full of small bears, its brass spout just visible at the top of the frame. Pour opens the spout with a clack and the bears tumble out in a slightly random stream that spreads as it falls. The jar slowly refills on its own; the level is visible.

## Physics

- **Big bear:** a volumetric soft body: a tetrahedral mesh (about 2,000-4,000 tets) solved with **XPBD**, elastic constraints plus volume preservation, the smooth high-resolution surface skinned to the tets (barycentric embedding). The neck, wrists and ear roots are slightly softer, so the head nods, the ears flap and the arms swing a beat after the body.
- **Jelly, not rubber:** after any input it wobbles 4-6 times with decreasing amplitude and comes to rest in 2-4 s. Low-frequency, heavy, a little shear; no instant snap-back, no endless buzzing, no high-frequency jitter. Its feet stick to the tray (friction); it sways but stays standing.
- **Small bears:** rigid bodies, each a compound of 4-5 spheres (head, belly, two legs, a small ears sphere), with mass, spin, friction and a little restitution. On impact each one **squashes** along the hit direction and springs back (about 150 ms), so they read as gummy, not plastic. They collide with the tray, the rim, each other (spatial hash) and the big bear's surface.
- **Two-way contact:** every small bear hitting the big bear pushes its jelly: a visible dent that rebounds with a ripple, and many hits make the whole bear jiggle and lean. Small bears stick a little to the big bear (gummy is tacky) and slide off slowly; a pile around its feet presses on it and it bulges a little.
- **Piles are calm:** a pile of 200 bears settles in 1-2 s and then sleeps completely: no jitter, no creeping, no slow sinking into each other or into the tray. Fast falling bears never tunnel through the tray, the rim or the big bear (cap their speed or sweep).
- **Stability is not optional:** no inverted tets (detect and recover), no explosions, no permanent collapse, nothing through the tray. The big bear's volume stays within a few percent of rest.
- **Firmness** changes stiffness smoothly without resetting the shape (soft = slow, deep sag; firm = quick, small wobble). **Wobble** changes damping.

## Tools

A tool picker with **Hand** (`1`) and **Bite** (`2`), plus a big round **Pour** button. A press that ends within 6 px and 450 ms counts as a tap. One finger acts; two fingers or right-drag orbit. Nothing is hover-only.

- **Hand:** tap the big bear to poke a dimple that rebounds with a ripple. Press and drag grabs the surface point under the cursor and pulls it (an ear, an arm, the belly): deformation is local and follows the finger, stretch is dramatic but capped (never tears); releasing during a fast drag keeps the momentum (flick). Press on a small bear to pick it up (it dangles and squashes a little in your fingers) and **throw** it: it flies with your release speed. Double-tap the big bear (or `D`) to lift it a little and drop it: it squashes, the head lands a beat later, the ears flop.
- **Pour:** tap the button (or `P`) to drop a handful of about 25 small bears; hold it for a steady stream (about 40 per second) until you let go or the jar runs dry. Tap anywhere above the big bear while holding `Shift` to pour from that spot.
- **Bite:** tap the big bear to take a **bite**: a rounded scoop removed with a scalloped edge of tooth marks, as if someone really bit it. Carve it properly: remove the tets inside the bite, then snap the remaining vertices near the bite surface onto it, so the bitten face is smooth and clean, never stair-stepped and never see-through; the bitten face is slightly rougher and wetter and shows the bands in cross-section. A bite that cuts a part off (an ear, a hand, the head) leaves that part as its own little soft body that drops and wobbles. Up to about 12 bites; then a toast "That's enough bear." and further bites are ignored gracefully. Tap a small bear to bite its head off (the classic): it becomes a headless small bear, the head a separate tiny piece.
- **Feed:** a small bear you drop or throw with the Hand onto the big bear's head or belly gets eaten (poured bears never do), and `F` feeds the 10 nearest: each one squishes **into** the big bear, swirls inside as a soft blob of its colour, dissolves into the nearest band, and the big bear swells by about 2% with a satisfying wobble. Growth caps at 2x height (50 bears); the camera eases back to keep it in frame. Toasts at 10, 25 and 50 fed ("Giant bear.").
- **Shake:** `S` (or a button) jolts the tray: the pile jumps, bears tumble, the big bear jiggles hard and settles.
- **Empty:** `E` (or a button) tips the tray a little and sweeps every small bear off the edge, out of frame.

## Easter egg

- **Wet-dog shake:** when small bears cover most of the big bear (buried up to the chest with some on its head) and everything has settled, it waits a second, then shivers itself free like a wet dog: a fast side-to-side jelly shimmy that flings the bears off its head and shoulders. Toast: "Shook it off." Once per burial.

## Sound

- Synthesize everything with WebAudio; create the `AudioContext` on the first gesture only; a mute button and `M`.
- Poke: a soft wet squelch whose pitch drops with firmness; wobble: a quiet low "wub" that fades with the motion; Pour: a candy rattle made of many tiny ticks (aggregate them: never one voice per bear); small bear on the big one: a soft "pap"; on the tray: a light tick; Shake: a big rattle; Bite: a gummy chomp with a little stretch-and-snap; Feed: a squishy gulp and a rising "wub" as it grows; the Easter egg: a quick wobbly brrr. Nothing clips or piles up (voice limit).

## Look

Aim for a premium candy commercial, not a game asset.

- **Colour:** sRGB output, **AgX** tone mapping, exposure about 1.0, HDR internally: the candy colours stay saturated and juicy, never washed out.
- **Lighting:** a procedural environment (`RoomEnvironment` through `PMREMGenerator`, no HDR files) for the glossy reflections, a large soft warm key from the front-left (daylight from a window), a soft fill, and a cool rim from behind that outlines the ears and makes the edges glow. Soft shadows (PCF soft, 2048, 1024 on phones) and a contact shadow under the big bear, the small bears and the tray.
- **Coloured light through the jelly:** the big bear's shadow on the tray is **tinted** by its bands, not grey: blend a projected, slowly wobbling colour pattern (a cheap caustic, brightest under thin parts like the ears and arms, following the deformation) into the shadow area.
- **Materials:**
  - **Big bear:** a physical material with transmission 1, thickness from the real geometry, IOR 1.4, attenuation colour per band and attenuation distance so the belly and head are deep and the edges glow, roughness about 0.12 (gummy is satin-glossy, a touch less wet than jelly), clearcoat 0.6, a strong Fresnel sheen at grazing angles, faint procedural roughness variation and tiny surface dimples so it never looks CG-perfect. Never glass-hard, never plastic, never opaque.
  - **Small bears:** one instanced mesh with a colour per instance; a translucent candy look **without** an extra transmission pass per bear: physical with clearcoat, sheen and a soft back-lit glow tinted by its colour (brighter where thin, like the ears), so they still read as gummy next to the big one.
  - **Sugar coating** (switch): both big and small bears turn frosted: rougher (about 0.55), with fine sparkling sugar-crystal glints that twinkle as the camera or the jelly moves.
  - **Tray:** warm grey glaze with clearcoat and a soft sheen; **table:** light warm oak, matte; **jar:** clear glass with a brass spout.
- **Post:** a light vignette only. No full-screen bloom (a glossy tray's highlights are as bright as anything and a bloom hazes the whole scene milky), no heavy chromatic aberration or grain.
- **Saturation:** the six bands stay clearly distinct and juicy at the default exposure (yellow reads yellow, purple reads purple, not blue); the bear is never milky or pastel in the Rainbow preset, and never so deep that it looks opaque.
- **Backdrop:** a soft studio gradient (warm cream to dusty peach) in a **mid-light tone, never pure white or pure black**.
- **Framing:** the default camera shows the big bear and the tray filling about 75% of a **square** frame, three-quarter view from slightly above, the face turned a little towards the camera, the jar's spout at the top edge.
- **Motion:** everything eases, overshoots a little and settles; nothing pops or teleports.

## Interface

- **Top left:** a big bold heading "Rainbow Jelly Bear." with a small subtitle "One big bear. Two hundred small ones."
- **Right:** a rounded control card "Candy box": the two tools as tiles with a small drawn icon and their key; a big round glossy **Pour** button (hold for a stream) with the jar level; **Shake**, **Feed 10** and **Empty** buttons; **Firmness** (soft to firm) and **Wobble** sliders with live values; **Colours** pills: Rainbow, Pastel, Sour (lime, lemon, cherry, grape: all bands change together, smoothly cross-fading); switches for **Sugar coating** and **Slow motion** (¼ speed); **Reset** (one whole big bear at normal size, no small bears, jar full).
- **Bottom:** a one-line hint "Tap to poke. Drag to squish. Hold Pour." that changes with the tool (Bite: "Tap to bite. Ears first?") and fades after a few uses. A small counter "Bears: 143 · Fed: 12".
- A status pill `WEBGPU · LIVE` or `WEBGL2 · LIVE`; toasts for milestones (first 100 bears, first bite, fed 10/25/50, the Easter egg), each once. Collapses to a compact bottom sheet at phone width with Pour always reachable; the UI never covers the bear.
- If neither WebGPU nor WebGL2 works, a clear, designed message.

## Camera and keys

- Orbit around the tray within limits (never under the table), zoom within limits; the big bear always stays in frame, also at full size. `R` reset, `Space` pause, `C` cinema (hide UI, slow orbit), `M` mute, `P` pour (hold for a stream), `S` shake, `F` feed 10, `D` drop, `E` empty, `1`-`2` tools.
- Respect `prefers-reduced-motion`: softer UI transitions, slower cinema orbit; the physics still responds fully.

## Test hook

If the URL has `?test=1`, expose `window.__toy` with no visible change: `poke(x, y)`, `pour(n)`, `shake()`, `feed(n)`, `bite(x, y)`, `drop()`, `empty()`, `reset()`, and `getState()` returning `{ renderer, fps, smallBears, smallAwake, fed, scale, bites, pieces, volumeRatio, kineticEnergy, asleep }`.

## Demo mode (required)

If the URL has `?demo=1`, auto-play a 4-second loop with no user input: the object drops in, wobbles, gets poked or sliced once, then settles.

For this toy that means:
- Hide all UI and the cursor. Never create an `AudioContext`.
- One fixed quality preset, fixed seed, default camera, Rainbow colours, Sugar coating off.
- A deterministic loop restarting every 4.0 s of real time from the identical state (big bear alone on the tray):
  - **0.0 to 0.8 s:** the big bear drops onto the tray from a small height: it squashes, the head lands a beat later, the ears flop.
  - **0.8 to 2.2 s:** the jar pours about 40 small bears: they rain onto the big bear's head and shoulders, each hit leaving a dent, bounce off, squash on the tray; the big bear jiggles under the hail.
  - **2.2 to 3.2 s:** the small bears tumble into a little pile around its feet, a few stuck to its shoulders slide down; the big bear sways and settles.
  - **3.2 to 4.0 s:** the small bears shrink away smoothly while the big bear wobbles down, back to the state at 0.0 s.
- Start moving within 1 s of load; the action must read clearly at 15 fps (the demo is recorded in a slow software renderer).
- Support `?demo=1&t=<seconds>` to freeze the demo at that time.

## Before you finish

Self-check against this list and fix anything that fails:
- Poke, squish, pull the ears and arms, flick and drop the big bear at Firmness soft and firm, Wobble low and high: it always jiggles like gummy, ears and head lag the body, and it always settles standing.
- Hold Pour until 200 bears: still 60 fps on a mid-range phone, the pile settles and sleeps, nothing jitters, creeps or sinks, nothing falls through the tray or the big bear, the oldest bears fade out gracefully at the cap. Shake and Empty with a full pile.
- Bite everywhere: ears, arms, head, belly, many bites in one spot, bites on a bear buried in small ones; look into every bite from several angles: no see-through holes, no stair-stepped faces, no inverted tets. Bitten-off parts wobble on their own. Bite small bears.
- Feed to the 2x cap: the growth is smooth, the camera keeps the bear in frame, physics stays stable at full size.
- Every tool, slider, switch, colour preset, button and key; pause and resume; Cinema; resizing to phone width with touch.
- Sound: every action has its effect, Pour never turns into noise, nothing plays before the first gesture, mute works.
- It works inside `<iframe sandbox="allow-scripts allow-pointer-lock">` with storage blocked.
- `?demo=1` matches the timeline, loops cleanly, shows no UI and plays no sound; `?test=1` exposes `window.__toy`.
- No console errors or WebGPU validation errors on WebGPU **and** on WebGL2 (force the fallback to check), and it stays smooth on a mid-range phone.

Put the big bear's wobble and the rain of small bears first. Holding Pour and watching the big one get buried should be the best part.

More like this