The Sleeping Giant
This world didn't start here.
It needs WebGPU or WebGL2: try a recent Chrome, Edge or Safari, or open it on its own.
Open on its own
Goal & tips
Goal You are the button that fell off his shirt. Get back home to the empty buttonhole by his collar without waking him.
Try this
- Ring the chime by hopping, stand still for the frogs, wait at the windmill for a snore
- Press E by his ear to hum the lullaby
- When his eye opens: freeze until it closes
- Seven things he lost glint around him; roll on a snore to surf it
Keys WASD walkShift rollSpace hopE hum at his earH hintV Giant viewF full screenEsc pause
Secret He's ticklish, and his nose is sensitive. Who found out how?
Show hint (spoiler)
Stand on the tip of his nose for three seconds and he sneezes you into the air. Hop in his left palm and he giggles in his sleep.
The prompt
Build **"The Sleeping Giant"**: a small, cozy 3D world you walk around in, as ONE self-contained HTML file with **synthesised sound**. The whole valley is a giant asleep on his back under a blanket of grass, and you are the button that fell off his shirt, finding your way home.
It should feel like a premium animated short with a warm, gentle sense of humour: deep saturated greens, a red plaid shirt, a ginger moustache made of bushes, golden light, long soft shadows. The landscape is alive in one unmistakable way: **it breathes.** Calm, never hurried, nothing can hurt you.
## 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/`. Use TSL node materials. Movement and simulation are your own code (no physics libraries).
- The only other network request is the Fredoka font from Google Fonts; if it fails, fall back to a system rounded sans-serif. No other libraries, fonts, images, models, textures or audio files: every texture is drawn on a canvas or generated as data at start-up, every sound is synthesized.
- Start with `<!doctype html>`, `<meta charset="utf-8">` and a viewport meta tag.
- Read keys with `KeyboardEvent.code` (`KeyW`, `KeyE`, `Space`...), never `.key`: on a Ukrainian, Russian or AZERTY layout `.key` for W is `ц`/`z` and the game would not move. `preventDefault` on Space and the arrows, so the page around the game never scrolls.
- Focus: when the game loses keyboard focus (the visitor clicked the page around the iframe), pause and show "Click to continue"; before the first click show a small "Click to play" pill. After any on-screen button is clicked, hand focus back to the canvas (otherwise Space presses that button again).
- 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 or top-level navigation. The page takes keyboard focus when clicked.
- Fixed 60 Hz simulation timestep with bounded substeps, decoupled from frame rate; on a slow frame drop simulation time instead of speeding up.
- Preallocate every buffer, geometry and material at start-up; nothing is created during play.
- A quality scaler that lowers pixel ratio, then shadow map size, then bloom, then grass density when frames get slow. Target 60 fps on a mid-range phone. Respect `prefers-reduced-motion` (no camera shake, slower camera).
- Known three r170 pitfalls, avoid them:
- the scene background is drawn after transparent objects: draw the sky as a mesh (or give transparent sky 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); hide unused instances by scaling them to zero;
- never let a helper overwrite a shared temp vector its caller still uses;
- a vertex shader that reads a texture must sample it at an explicit level (`.level(0)` in TSL);
- the render loop's first `requestAnimationFrame` timestamp can be earlier than `performance.now()` at start-up: clamp the frame delta at 0.
## 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 giant as a landscape that reads as a sleeping person from above; the breathing (everything on the chest and belly rises and falls with it); the snore gusts rolling through the grass; the button walking and rolling; the demo mode.
2. **Must work:** the goal (three lullaby notes, the ear, deep sleep, the climb home), the stir meter and the opening eye, the sneeze, the palm lake, the cottage, the windmill, day and night, rain, sound, the interface, the phone controls.
3. **Polish:** the dream skies, the tickle, sheep, fireflies, Giant view and the intro reveal, photo mode.
Never ship a feature half-working: if something from tier 3 can't be done well, leave it out cleanly.
## The giant (the whole world)
The valley is about **130 x 180 m**, bounded by a soft forest ring with light haze. The giant lies on his back along it, **head north, feet south**, about 150 m from the crown of his head to his toes. Build him from smooth, softly blended shapes (heightfield or meshes, your choice), so he reads instantly as a body from a high camera:
- **Head** on a huge cream linen **pillow**, his hair a forest of **copper and amber trees** spread around it. A warm sandstone face with moss patches and rosy cheeks, all facing the sky:
- **closed eyelids** with long dark lashes;
- a big rounded **nose** you can climb;
- a **ginger moustache and eyebrows made of bushy shrubs**;
- a mouth half hidden under the moustache;
- ears on both sides;
- round cheeks and a chin as soft bumps, and painted details: smile lines, a rosy lower lip, a chin dimple, creases over the lids, freckles.
- **Shirt:** a red plaid flannel shirt shows from the neck to the blanket's edge, with a row of big teal buttons down the middle. The top one is missing: an empty buttonhole with a loose thread. **That is home.**
- **Blanket:** below the chest he is covered by a patchwork quilt that is a meadow, 9 m squares separated by stitched seams where the grass is shorter. Each square is a different lawn, like a different fabric:
- tall wild grass;
- mown stripes;
- mown checks;
- short blue-green clover with tiny white flowers;
- some squares are full of poppies, daisies or lavender.
The blanket's edge across his chest is a soft rolled hem. The pillow has a sewn piping along its edge.
- **Arms** lie at his sides in plaid sleeves:
- the **left hand** lies palm up, cupping a small clear **lake** with lily pads and frogs;
- the **right hand** lies palm down on the grass beside a tiny **cottage** (warm window, chimney smoke, a vegetable patch, a wind chime on the porch); you can see his knuckles and fingernails;
- two little buttons on each cuff.
- Next to the cottage is a **ball of red yarn the size of a hut** with two knitting needles stuck in it: someone is knitting him a new sock.
- **Knees** make two hills; a small **wooden windmill** stands on the right knee.
- **Feet:** the left foot is a peak under the blanket. The **right foot** sticks out in a huge **striped sock** (red and cream rings), heel down and toes up, with a big toe peeking through a hole.
- A few **sheep** graze on his belly and ride his breathing.
- Worn footpaths wind across the blanket and around him: someone walks on him every day.
### The breathing (the signature)
- He breathes slowly: in for about 2.5 s, out for about 3 s, a short pause, then again.
- His chest rises up to about **1.6 m** and his belly a bit less, with a smooth falloff. Everything on top rises and falls with it: the grass and flowers, the hem and the shirt buttons, the sheep, the button, and the camera when you stand there.
- On every breath out he **snores**:
- a low, rumbling, unmistakably funny sound;
- a **gust wave rolls out from his mouth** across the grass toward his feet, like a ripple on a pond;
- dandelion seeds puff out from under the moustache;
- big white cartoon **"Z z Z" letters** drift up from his mouth and fade (they grow with camera distance, so they read even in Giant view and on the card);
- the moustache bushes flutter;
- the windmill on his knee spins faster as the wave passes.
## The button (you)
- A round teal button, about 1.2 m across, thick and glossy, with a raised rim and **two holes for eyes**. Small dark pupils sit inside the holes; they look around and blink. A short loose thread sticks up like a tuft of hair.
- **Walking:** it stands on its edge, facing forward, and waddles side to side.
- **Running (Shift, or the joystick pushed to the edge):** it turns sideways and **rolls like a wheel**, turning back to face forward when you stop.
- **Space** hops, with a squash and stretch, and a flip when rolling.
- WASD or arrows move it relative to the camera. On phones: a virtual joystick bottom left, Hop and an action button bottom right. A single press of `E` (or the action button) is enough: it fills the bubble's ring by itself and fires when full; holding works too.
- The grass parts around it; flowers bend and drop a few petals.
## Goal: get home
1. **Notes:** the climb home crosses his chest, and his breathing is too strong there: each breath in pushes the button back down the shirt. He needs to sleep more deeply. Collect the **three notes of a lullaby**. Each one is a little adventure with its own verb, never just "press E":
- the **wind chime** on the cottage porch rings when you **hop** into it (E near it hops for you);
- the **frogs** in the palm lake are shy: they dip under when you move near and only sing when you **stand still** for a couple of seconds;
- the **windmill** on his knee only creaks when a **snore wave** reaches it and spins it fast: **wait** there for the next snore. The bubble's ring shows the coming breath out.
Each note flies into the interface with its own pitch.
2. **The ear:** press `E` beside his ear to hum the three notes back. He smiles in his sleep, his breathing grows slow and shallow (**deep sleep**), and the sky becomes **his dream** for a minute:
- pastel colours;
- giant soap bubbles drifting up across the valley;
- stars in daylight.
Pick one of three dream palettes at random.
3. **Home:** now the button can climb the shirt to the empty buttonhole. It hops in, threads stitch it into place with a sparkle, and the camera rises into **Giant view**: the whole valley at once, while he gives one long, happy sigh and **a big pink heart floats up from his chest**. Then the end card; Space hops out to keep exploring.
Toasts, once each: "Woke up on a sock", "First note", "All three notes", "Fast asleep", "Achoo!", "Ticklish", "One eye open", "Rode a snore", "He loses things in his sleep", "Everything he lost", "Home".
## The night run (the hook)
- A **timer** starts with your first step and stops when you're home (a small pill at the top centre, with the gold target or your best time).
- At Home an end card shows the time, a medal (Gold under 1:45, Silver under 3:00, Bronze), how many times he woke, snores surfed, lost things (x/7), secrets found (x/3), "Silent run" if he never woke, the best time (kept in memory; `localStorage` only inside `try/catch`), and Run again / Keep exploring.
- **Freeze!** While his eye is open and looking, a big "FREEZE!" appears and the button trembles if it stands still. If the button moves then, he notices, mumbles and snorts: the button is blown a few metres away from his head.
- **Surf the snores:** rolling as a snore wave passes you lifts you onto it: about 1.5 s at much higher speed with a sparkle trail. It's the trick for a fast run, and it makes the signature effect a mechanic.
- **He talks in his sleep:** short lines in a speech bubble above his mouth (pinned to the screen edge when his face is off screen), reacting to what you do:
- when he stirs: "...hm? who's walking on me...";
- when his eye opens: "...wha... a button?";
- when he spots you moving: "...shoo, little bug... *snort*";
- the tickle: "...hehe... stop it...";
- after the sneeze: "...bless me...";
- a partial lullaby: "...mm, nice...";
- the dream: "...the sea... so warm...";
- rain: "...is it raining?...";
- Home: "...there you are, little button...";
- and now and then: "...five more minutes...", "...one sheep... two sheep...". Give him a gentle, funny personality.
## Lost things (exploration)
Seven little things he lost in his sleep, each floating and glinting now and then so you can spot them:
- a blue marble on top of his left foot;
- a biscuit crumb on his chest;
- his belly-button fluff, visible through a **moth hole in the quilt** (a frayed hole showing his belly button);
- a lucky penny on the tip of his left thumb;
- a love letter by the corner of his mouth;
- Grandma's thimble on the pillow behind his ear;
- the garden-gate key in his copper hair.
Picking one up gives a sparkle, a toast "Found his lucky penny (3/7)" and a **memory he mumbles** ("...Martha's letter... she said yes...", "...my blue marble... I was six..."). The count shows by the map, in the pause menu and on the end card.
## Your brother on the shirt
The shirt button just below home is a button like you, with eyes. His pupils follow you and blink. When you're near he whispers in a small teal bubble ("Psst! Up here!", "Shh, don't wake him!", "Now! Climb!"). At Home he hops for joy: "Welcome home!".
## His heart
A slow lub-dub (faster when he's lightly asleep, slower in deep sleep): a warm glow pulses through the shirt over his heart, faint by day and lovely at night, with a soft thump when you're near.
## Don't wake him (the stir meter)
- Rolling on his body, hopping on him and the sneeze add to a **stir** meter; it calms down over time, and fills much more slowly once he is in deep sleep. The meadow around him doesn't count.
- When it fills, **one huge eye opens in the hillside**. The eyelid slides up, a glossy eye with an amber iris looks around, finds the button and follows it for a couple of seconds. If the button is far from his head, the camera swings over for a few seconds to show the eye opening, framed so the **whole head** (hair, brows, ears, moustache) fits on screen. He mumbles something sleepy, blinks twice and closes it again, and the meter drops back.
- Never a fail state: it is a reward for being naughty.
## Little things
- **Sneeze:** stand on the tip of his nose for about 3 s. The nose twitches ("hh... hhh...") and he sneezes: a big gust, a burst of seeds, a soft camera shake, and the button is **launched** high, spinning, to land somewhere on his chest or belly.
- **Tickle:** hop in his left palm: the fingers twitch and he giggles in his sleep.
- **Rain** (switch): soft rain, ripples on the palm lake, he frowns slightly (brows down, mouth corners down); a rainbow after it stops.
- **Night:** stars and moon, lit cottage window, fireflies over the palm lake and the cottage, his snores softer.
- **Storks:** a few storks circle lazily high over him; you mostly see their shadows sweep across the grass, and the birds themselves from Giant view.
- **Motes:** by day, a few sunlit specks of pollen drift around the button, brighter when you look toward the sun.
- **Leaves:** the wind now and then lifts a copper leaf from his hair.
- **In his dream:** hop onto a soap bubble and it bounces you high ("Boing!"); some bubbles rise near you.
## Sound
- WebAudio only; create the `AudioContext` on the first gesture and never before. A mute button and `M`. A master gain into a compressor, at most about 16 voices, every audio call in `try/catch`.
- The snore (filtered noise plus a low rumble, louder near his head, always faintly there), breathing in, wind, grass rustle, birds by day, crickets at night, rain.
- The button: wooden taps when walking (softer on the blanket, a soft thud on the shirt), a rolling rumble, a boing for hops.
- Notes: the wind chime (bell partials), the frog croak, the windmill creak, each also as a pitched note. The hummed lullaby, the mumble, the giggle, the sneeze, the stitching and a warm chord for Home.
## Look
Aim for a premium animated short, not a game asset.
- **Colour:** sRGB output, Neutral tone mapping (keeps the greens saturated), exposure about 1.0.
- **Palette:**
- grass from #2f8a2c to #9fd94a;
- shirt plaid #b8402c / #5a2420 / cream lines;
- skin #dca57a with moss #6f8f3e;
- moustache and hair copper #b8622a / #e08a3a;
- buttons teal #2f8f9d;
- pillow #efe7d6;
- sock red #c8402e / cream.
- **Lighting:** a procedural environment (`RoomEnvironment` through `PMREMGenerator`) for soft ambient, one warm directional sun that casts the shadows (soft PCF, 2048, 1024 on phones, the shadow box follows the player), a sky-coloured hemisphere fill. The environment lights only the PBR meshes, so dim it at night (to about a fifth) or the nose, eyelids, hair and trees glow against his moonlit skin. Shadows are long at golden hour. Big slow **cloud shadows** drift over the whole valley.
- **Grass:** instanced blades (about 60-120k around the player, density fading with distance), dark roots to bright tips, wind sway in the vertex shader, the breathing offset, the snore wave and the player push. Grass catches light: tilt its lighting normal toward the sun so it stays bright at low sun.
- **Materials:** physical, softly stylized: glossy clearcoat on the buttons, sheen on the shirt and sock, glossy eye with a highlight, transmission or a fresnel rim on the soap bubbles. Subtle procedural colour variation everywhere.
- **Post:** one subtle bloom (strength about 0.35, threshold above 1: lanterns, fireflies, sun glints, the stitching sparkle), a light vignette. No grain or chromatic aberration.
- **Backdrop:** a gradient sky dome with soft clouds, never pure white or pure black (deep blue at night).
- **Framing:** the play camera looks down at the button from a high three-quarter angle (about 50 degrees, 13 m away), follows smoothly with a little lag and looks slightly ahead. **Anything between the camera and the button** (trees, the cottage roof, his nose) **dissolves** (dithered) so the button is never hidden. The cut only applies while the button is in front of the camera and only to what lies between them; it is off whenever the camera looks at something else (Giant view, the eye close-up, Photo).
- **Motion:** everything eases, overshoots a little and settles; nothing pops, snaps or teleports. Draw the button between its last two fixed-step simulation states (interpolate by the leftover time), and make the camera, the guide arrow and the grass push use that smoothed position, so rolling at speed never stutters.
- **Quality:** antialias the post-processing pass (multisampled render target), smooth normals on every rounded shape (merge vertices before computing normals: no faceted foliage), a baked cavity occlusion from the height field (darker creases where the body meets the meadow, between fingers, at the neck), per-blade colour variation and a warm glow through the grass tips when looking toward the sun, a sparse far ring of grass so the meadow never ends in a visible square, and a gentle colour grade.
## Interface
A light, warm UI that never covers the button. Cream cards (#fbf6ea), 18 px corners, soft shadows, dark brown ink (#3b2a1e), Fredoka. Make it your own: no hotbar of numbered item slots and no copied game HUDs.
- Top left: small caps "POKEABLE · WORLD", the big title "The Sleeping Giant" and the caption "You're his lost button. Find your way home. Shh.". After the first move the title shrinks and the caption hides, so a toast never sits on top of it.
- Top right: the time of day (a small sun or moon on an arc with the name under it), a status pill `WEBGPU · LIVE` or `WEBGL2 · LIVE`, a speaker pill, a **full screen** pill (`F`; `document.documentElement.requestFullscreen()`, hidden where unsupported) and a **pause** pill.
- **Pause menu** (`Esc` or the pause pill; the world stops and the sound suspends):
- the way home as a checklist (notes x/3, the ear, the climb), little secrets found (x/3) and the night run time;
- Resume, Full screen, Sound, Giant view, Photo mode, Back to the sock, Start over;
- Time of day and Wind sliders, Rain, Cinema camera and Guide arrow switches;
- the controls.
- **Hints:**
- a "Next" line under the title always says the current step ("Find the lullaby notes (1/3): next, the frogs", "Go to his ear and press E", "Climb his shirt...");
- a small **guide arrow** circles the button on the ground plane, pointing toward the next goal with its distance in metres;
- pulsing markers on the map card;
- `H` (or clicking the Next line) gives a fuller hint as a toast; the same hint appears by itself after about 75 s without progress;
- a few one-time tips at the right moment (rolling is loud, freeze when the eye opens, hop out after Home).
- Hints never give away the secrets (the sneeze, the tickle).
- Bottom left: a **map card** drawn from the giant's own outline (head, shirt, blanket, hands, the lake, the cottage, the windmill, home marked with a dashed ring). It shows the button's position and facing, three note slots that fill as you learn them, and a "z z Z" stir meter beside his head that turns orange and shakes as he stirs. Click it for Giant view.
- Near something you can use, a small speech bubble floats **over that thing in the world**, with a fill ring while `E` is held.
- Toasts at the top centre, at most about 420 px wide (long ones wrap).
- A one-line hint at the start that fades after the first move: "WASD to walk · Shift to roll · Space to hop · V to see him whole".
- Phones: the title shrinks, the map moves top right under the time, joystick and buttons as above.
- If neither WebGPU nor WebGL2 works, a clear, designed message.
## Camera and keys
- Mouse wheel / pinch zooms 6-30 m; right-drag or two-finger drag rotates the view around the button (pitch 30-70 degrees).
- **Keys:**
- `WASD` / arrows move, `Shift` roll, `Space` hop, `E` hum at his ear, `V` Giant view, `H` hint, `F` full screen, `Esc` pause;
- `C` Cinema, `P` Photo, `M` mute, `T` time of day +1/4, `R` rain, `0` reset the camera.
- **Loading:** a soft "Tucking him in…" screen (a sleeping button and drifting z's) until the first frame is drawn.
- **Intro (not in demo):** the page opens in Giant view at golden hour; a snore rolls down the valley as a soft light band over the grass; after about 5 s (or the first input) the camera glides down to the button lying by the sock.
- **Giant view (`V` or click the map):** the camera rises high above the valley so the whole giant fits the screen, head at the top; `V` again (or any move) returns.
- **Cinema (`C`):** hides all UI; the camera cranes up and drifts slowly beside the button while you keep walking.
- **Photo mode (`P`):** pauses the world (the breath holds mid-rise), hides all UI, free camera (WASD flies, drag looks, wheel moves), `Esc` returns.
## Test hook
If the URL has `?test=1`, expose `window.__toy` with no visible change:
- `teleport(place)`, where `place` is one of `"sock" | "belly" | "chest" | "nose" | "ear" | "palm" | "cottage" | "knee"`;
- `setTime(0..1)`, `setWind(0..1)`, `setRain(bool)`;
- `learn(note)` and `learnAll()`;
- `stir(amount)`, `sneeze()`, `deepSleep()`, `goHome()`;
- `getState()` returning `{ renderer, fps, place, time, breath, stir, deep, notes: [ids], home, eyeOpen, interacting }`.
## Demo mode (required)
If the URL has `?demo=1`, auto-play a 4-second loop with no user input: the giant breathes in, one eye opens and looks at the button, closes, and he snores.
For this world that means:
- Hide all UI and the cursor. Never create an `AudioContext`.
- One fixed quality preset, fixed seed, golden hour, medium wind, no rain.
- A fixed camera above his chest looking up at his face, so the face (eyes, nose, moustache, brows, ears) fills about 80% of a **square** frame. The button stands on the bridge of his nose.
- One breath per loop, restarting from the identical state every 4.0 s of real time:
- **0.0 to 1.4 s:** he breathes in (the chest in the foreground rises); the button waddles on his nose.
- **1.4 to 2.6 s:** his left eye slides open, the amber iris turns to look at the button, his brow lifts.
- **2.6 to 3.3 s:** a sleepy blink and the eye closes.
- **3.3 to 4.0 s:** he snores: seeds puff from under the moustache, the moustache flutters, a gust ripples away through the grass, back to the state at 0.0 s.
- Throughout: three "Z" letters rise from his mouth on a seamless 4 s cycle.
- 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:
- From Giant view he reads at once as a sleeping person (head, shirt, blanket, hands, knees, sock).
- The chest and belly breathe and everything on them rides along; the button never sinks into the ground or floats on a breathing slope.
- The snore wave rolls from the mouth through the grass on every breath out.
- Walk and roll everywhere without getting stuck or leaving the valley; the camera never goes underground; occluders dissolve around the button.
- The whole goal works end to end: three notes, the ear, deep sleep and the dream, the climb, Home, hop out; the shirt pushes you back before deep sleep.
- The eye opens at full stir and follows the button; the sneeze launches it; the palm tickle works.
- Every key (also with a non-Latin keyboard layout), slider, switch and the map card; the pause menu, full screen, the hints and the guide arrow; the timer, Freeze!, snore surfing, the sleep talk and the end card; day, golden hour, sunset and night; rain and the rainbow; Cinema; Photo; Giant view; resizing to phone width with the joystick and touch buttons.
- Sound: every action has its effect, nothing plays before the first gesture, mute works.
- It works inside `<iframe sandbox="allow-scripts allow-pointer-lock">` with storage blocked, and takes keyboard focus on click.
- `?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 breathing landscape first. The moment you realize the hills are a sleeping giant, and later the moment his eye opens and looks at you, should be the best parts.