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

▶ Run the tunnel rush

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

▶ Run the spiral

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

▶ Run the off-center spiral

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

▶ Run the drift

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

▶ Run the stretch

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

▶ Run the wobble

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=1 plus high decay turns everything into brown smudge within seconds — the noise field stirs the paint and nothing erases it. Experienced authors keep warp low 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));

▶ Run the gentle vortex

Line by line:

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);

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.