A top-down city plaza where hundreds of simulated walkers, colored by direction, sidestep each other and sort into lanes nobody planned, a crossing stream cuts through in diagonal stripes, and fading trails draw the structure before the simulation pauses.
Written and rendered by AI CSS Animations Oct 18, 2026
Pedestrian simulations treat each walker as an agent pulled toward a goal and pushed away from other people and walls; the social force model published by Dirk Helbing and Péter Molnár in 1995 is one of the best known. Such models reproduce patterns researchers have filmed in real crowds: people walking in opposite directions sort themselves into lanes without any plan, and crossing streams break into diagonal stripes. Architects, transit planners and event organizers use these simulations to size corridors, stairs and exits, and the top-down view of colored walkers is their signature.
Make a 10-second top-down crowd simulation: hundreds of pedestrians cross a city plaza, sidestep each other and, with no plan, sort themselves into lanes.
<inputs>
If I don't give you something, use the default and don't ask.
- Plaza: Dunmarren Square (fictional).
- Title: "Nobody planned the lanes."
- Line: "Dunmarren Square, 08:40 · simulated walkers at 2.5× speed"
- Flows: eastbound and westbound along the promenade, southbound across it.
- Length: 10 seconds.
</inputs>
<direction>
- Palette: paving #E4D8C4 with joints #CBBBA2 and a darker granite band #B9A88F; planters #7D9A64 with stone curbs #CFC3AE; tree canopies #4E7B46 and #6E9C55; benches #8A6A4B; eastbound walkers coral #EE5A3A, westbound teal #12827F, southbound mustard #E1A21B; hair tones #3A2E28, #6B4B36, #C9A27E and #2B2B2B; feet #3A332C; shadows #4A3B2A at 22%; type #2A2420, secondary #6E6458.
- The plaza, seen straight down with north up, 1 m = 36px: an east–west promenade fills y 400–700 across the whole frame between two long planters (north y 330–400, south y 700–770) that run in from both frame edges and stop at a 220px gap, x 850–1070, where a north–south path crosses from the top edge to the bottom. The open paving above and below the planters has no walkers: the title sits at the upper left, counters at the lower left, a round fountain (radius 80, two rings of water and a soft central jet) at (1560, 170) and a row of benches at the lower right. Paving: 40 × 20px granite setts in running bond on the promenade and path, 120px slabs elsewhere with fine speckle, a few drain covers. Trees in the planters are top-down canopies of overlapping lobes, lit from the upper left, casting soft shadows 18px down-right.
- Walkers, simulated once at load with the social force model, in metres and seconds of plaza time at a fixed 1/50 s step: each person has a radius of 0.24–0.3 m and a desired speed of 1.2–1.5 m/s toward its exit. Acceleration = (v0·ê − v)/0.5 s, plus for every neighbor within 3 m a push 25·e^((rᵢ + rⱼ − dᵢⱼ)/0.08)·n̂ᵢⱼ m/s², weighted by 0.35 + 0.65·(1 + cos φᵢⱼ)/2 so people react most to whoever is ahead, the same push from planter curbs, and a small seeded noise (0.15 m/s²); speed is capped at 1.3·v0, and after each step any overlapping pair is moved apart to just touching. East- and westbound walkers also feel a weak pull back into the promenade's band where they pass the gap. Find neighbors with a uniform grid. At t = 0 the promenade already holds 170 walkers at random positions, each heading east or west, and the path holds 40 heading south; new walkers enter at the frame edges at seeded Poisson rates (east 1.1/s, west 1.0/s, south 0.7/s of plaza time) and are removed as they leave. Plaza time runs at 2.5× (T = 2.5·t) and pauses at t = 8.8 s; simulate 22 s of it and store every step.
- Drawing a person, from above: shoulders a rounded capsule 0.46 × 0.26 m across the walking direction in the flow color; a 0.2 m head in a hair tone, a little forward of center; two small arm capsules at the shoulder ends swinging opposite the legs; two dark feet (0.1 × 0.18 m ovals) stepping out from under the body, stride and cadence from speed; shoulders swaying ±5° with each step; a soft shadow ellipse 5px down-right. Bodies face their velocity, smoothed over 0.3 s.
- Trails: from 5.6 s, each walker trails its path over the last 2 s of screen time as a 2px line in its flow color at 20%, fading toward the tail, so lanes and crossing stripes show as colored bands.
- Camera: locked overhead, with a 4% push toward the crossing over the piece.
- Type: title in Space Grotesk 600, 60px, #2A2420, at (120, 120); line in Space Grotesk 400, 24px, #6E6458, beneath. Counters at the lower left from (120, 880), three rows 42px apart: a 14px dot in the flow color, the direction ("Eastbound", "Westbound", "Southbound") in Space Grotesk 500, 24px, and the number of walkers who have left the frame that way in Space Mono 400, 24px, tabular, counted from the simulation as each one exits. A note right-aligned at (1800, 1000) in Space Mono 400, 20px: "Trails: last 2 s of each walk"; at the pause, a tag above it in Space Mono 400, 22px: "Paused · 08:40:22".
- Easing: text rises 12px as it fades in over 0.6 s on cubic-bezier(0.22, 1, 0.36, 1).
- Premium: people who read as people from above (shoulders, heads, stepping feet), avoidance you can watch, lanes that no one drew, a calm planning-diagram finish. Cheap: dots sliding on straight rails, people overlapping or passing through each other.
Banned: overlapping people, walking through planters, teleporting, jitter, cars or bikes, faces, glow, anything flashing more than 3 times per second.
</direction>
<structure>
- 0.0–1.2s: the busy plaza from above, both promenade flows mixed at random and bumping; the title and line rise in.
- 1.2–4.0s: eastbound and westbound walkers sidestep and fall in behind people going their way: alternating lanes form along both arms of the promenade.
- 4.0–5.6s: the southbound stream thickens through the gap and cuts across; where the flows cross, walkers break into diagonal stripes; the counters rise in.
- 5.6–7.4s: trails fade in behind everyone, drawing the lanes and stripes as colored bands; the push continues.
- 7.4–8.8s: the note appears; the crowd keeps walking.
- 8.8–10.0s: the simulation pauses: everyone stops mid-step, the trails hold, the "Paused" tag appears; hold.
For other lengths, run more plaza time before the pause; keep at least 1 s of hold.
</structure>
<build>
- One self-contained index.html (inline CSS and JS), a 1920×1080 (16:9) stage scaled to fit the window, designed for 60fps. No image, video, texture or model files: every shape and texture is generated in code.
- window.seek(t), t in seconds, computes every visual from t alone: no CSS transitions or CSS animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. Anything cumulative is solved analytically from t or precomputed once at load at a fixed step. Past the end, seek clamps to the last frame.
- Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop.
- Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek.
- Engine: Canvas 2D, repainting every frame from scratch, the backing store sized from CSS size × devicePixelRatio. Canvas won't fetch fonts itself, so the awaited loads matter.
- The crowd is simulated once at load into Float32Arrays (positions, headings and step phases per stored step, plus each walker's entry and exit steps; keep load under 10 s); seek(t) maps t to plaza time, interpolates and never steps the simulation; counters and trails are read from the stored steps. Paving, planters, trees and the fountain basin are drawn once at load into an offscreen canvas.
</build>
<check>
Before showing me, step through one frame per second (t = 0…10): screenshot each and look at it. Fix overlaps, clipped or cramped text, and anything off-style or Banned. Check no two people overlap and nobody crosses a planter, lanes are visible in both arms by 4 s and crossing stripes by 5.6 s, trails line up behind the walkers, each counter equals the walkers who have left that way, the type sits on empty paving, and the 6 s frame and the final frame are both complete compositions. Confirm seek(10) and seek(11) match, so the final frame holds.
</check> Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.
Thousands of fine particles ride a curl-noise current, gather into a word or logo like a living engraving, dissolve bac…
A deep starfield stretches into blue-white streaks around one vanishing point, merges into a rolling tunnel of light, t…
Shells climb from harbor barges and burst into peonies, chrysanthemums, rings, palms and a finale of drooping gold will…
Thousands of starlings flow across a peach and mauve dusk sky as one mass, darkening into bands as the flock turns, par…
More like this on the motion design inspiration board: Particle animation inspiration