Track 2 — Motion
Every knob in this track answers the same question: where does the previous frame get redrawn? You already know zoom. Here are the rest, one at a time on the bench, then combined, then read in the wild.
Lesson 1 · zoom, pushed harder
zoom=1.04
At 4% per frame the compounding stops being subtle: this is the classic flying-through-a-tunnel move. Above 1 flies outward, below 1 falls inward, and the distance from 1 is speed. Almost every preset keeps it within 0.9–1.1; the drama comes from changing it (as in Lesson 4 of Track 1), not from large constants.
Lesson 2 · rot and the pivot
zoom=1.01
rot=0.02
rot rotates the previous frame by a fixed angle (in radians) each frame. On its own it smears history into rings. Combined with outward zoom it makes the signature MilkDrop move: the spiral — every trail is simultaneously growing and turning.
Rotation happens around the pivot cx, cy (screen fractions; 0.5,0.5 is dead center):
cx=0.3
cy=0.35
Moving the pivot breaks the symmetry — the vortex leans, and trails on the far side travel farther per frame than trails near the pivot. Run both and watch how different the same rot feels.
Lesson 3 · dx, dy — the push
dx=0.003
dy=-0.002
dx/dy slide the whole previous frame sideways each frame, in screen fractions. Run it and note which way the image travels versus the signs — the vertical axis in particular will surprise you once here so it never surprises you again. Constant small values give wind; audio-driven values (Track 3) give shoves on the beat.
Lesson 4 · sx, sy — the stretch
sx=1.02
sy=0.98
Per-axis scaling: this pair widens history 2% per frame while squashing it vertically. It's zoom with an opinion about direction — good for flames (stretch up), water (stretch sideways), and funhouse smears.
Lesson 5 · warp — the wobble
warp=0.2
fWarpAnimSpeed=1
fWarpScale=1.5
warp displaces the previous frame through a built-in animated noise field — instant liquid. fWarpAnimSpeed sets how fast the field churns, and fWarpScale how large its blobs are.
The classic beginner trap:
warp=1plus highdecayturns everything into brown smudge within seconds — the noise field stirs the paint and nothing erases it. Experienced authors keepwarplow or zero and build distortion with per-pixel equations instead, where they control the field. The anti-pattern table has the full list.
Lesson 6 · Combining knobs
One knob is a demo; a preset is a negotiation between several. This one uses everything from this track plus a per_frame block:
fDecay=0.97
zoom=1.008
per_frame_1=rot = 0.008 + 0.004*sin(time*0.13);
per_frame_2=wave_r = wave_r + 0.25*(0.6*sin(0.98*time) + 0.4*sin(1.047*time));
per_frame_3=wave_g = wave_g + 0.25*(0.6*sin(0.835*time) + 0.4*sin(1.081*time));
per_frame_4=wave_b = wave_b + 0.25*(0.6*sin(0.814*time) + 0.4*sin(1.011*time));
Line by line:
per_frame_1— the spiral's twist is not constant: it drifts between0.004and0.012on a slow sine (time*0.13≈ one swing per 48 s). The motion never settles, so the eye never files it away.per_frame_2–4— each color channel wanders on a sum of two sines at unrelated frequencies (0.98vs1.047, …). Irrational-ratio frequencies never realign, so the palette never repeats. This is color cycling with irrational frequencies — Pattern 5 in the coding guide, and a Geiss signature you'll see next.
Turn one knob. Make the vortex violent: shorten decay, raise the rot swing, and speed up the color sines. Then make it glacial. The same six lines cover the whole mood spectrum.
Lesson 7 · Dissection: Geiss — Happy Drops (Ryan Geiss)
Time to read a real one. This ships in the Stims catalog and is old enough to drink. Its six per_frame lines are pure Track 2 material; its three per_pixel lines are a preview of Tracks 3 and 4.
▶ Open Happy Drops in the editor · Watch it in the app
The lines that matter (the rest of the file is default housekeeping):
fDecay=0.98
warp=0.298816
rot=0
wave_r=0.65
wave_g=0.65
wave_b=0.65
per_frame_1=wave_r = wave_r + 0.350*( 0.60*sin(0.742*time) + 0.40*sin(1.021*time) );
per_frame_2=wave_g = wave_g + 0.350*( 0.60*sin(0.703*time) + 0.40*sin(0.969*time) );
per_frame_3=wave_b = wave_b + 0.350*( 0.60*sin(1.090*time) + 0.40*sin(0.963*time) );
per_frame_4=rot = rot + 0.040*( 0.60*sin(0.381*time) + 0.40*sin(0.279*time) );
per_frame_5=cx = cx + 0.110*( 0.60*sin(0.374*time) + 0.40*sin(0.294*time) );
per_frame_6=cy = cy + 0.110*( 0.60*sin(0.393*time) + 0.40*sin(0.223*time) );
per_pixel_1=dr = 0.01 + 0.03*min(max(bass_att-1,0.0), 0.5)*sin(rad*15);
per_pixel_2=dx = dx + dr*cos(ang)*0.75;
per_pixel_3=dy = dy + dr*sin(-ang);
per_frame_1–per_frame_3— Lesson 6's irrational-frequency color drift at full strength. Each channel swings0.35either side of a neutral0.65, so red, green, and blue each wander between0.3and1.0on their own unrelated sines, and the palette never repeats.per_frame_4— the same two-sine trick applied to motion. The file's baserotis0, so the twist wanders between-0.04and0.04: at its peak twice your spiral's0.02, but it keeps reversing (each sine takes 16–23 seconds per cycle), so it never settles into a plain spiral.per_frame_5/per_frame_6— the pivot from Lesson 2, set wandering.cxandcyeach drift up to0.11from center, so the point the rotation turns around slides slowly around the middle of the screen.per_pixel_1–per_pixel_3— the preview. These lines run per mesh point, andrad/angare each point's distance and direction from the screen center.drpushes every point about0.01outward along its own radial line each frame — a steady outward stream, like a gentlezoom. On top of that,bass_att-1is how far the bass sits above its average, clamped to0–0.5: in quiet passages it is zero, but on a bass hitsin(rad*15)adds alternating bands of stronger and weaker push across the radius. Those bands, smeared outward by the feedback loop, are the drops. Track 3 coversbass_att; making knobs vary across the screen is all of Track 4.
Exercise. Remix Happy Drops (Remix in the editor's ⋯ menu preserves the credit lineage): cool the palette by lowering the base wave_r to 0.3 and its swing to 0.15, give rot a base of 0.05 so the twist keeps one direction, and turn the stream inward by changing 0.01 to -0.01 in per_pixel_1. Export it, or copy the URL — the link is the preset.
What you can now read
Most of the pre-2007 classics keep their motion in per_frame, and any preset that does is now legible to you: find the knobs, find the sines driving them, find the eraser.
Next: Track 3 — Listening, where sin(time) gives way to the music.