workshop private

← all creations

Inner Groove

sprites · created 2026-09-09

64×50 pixel turntable seen from above — three loops, and a tonearm driven by real alignment geometry, so you can see the two places on the record where it is actually pointing the right way.

pixel-artcanvasphysics

An object rather than a character, and seen from a angle sprites usually avoid: straight down. Plinth filling the frame, platter left of centre, arm pillar at the back right, cue lever and rest where a real deck puts them. Three loops — spin while a side plays, cue for the arm leaving its rest and dropping onto the lead-in, and stuck, where the stylus jumps back a groove and plays the same beat forever.

The demo is the part worth clicking. A pivoted tonearm sweeps an arc; a groove is a circle; two different curves cannot agree along a length, only at points. So the stylus is very slightly crooked in the groove almost everywhere, and the only real question is where you want it to be exactly right. Every arm you have ever seen answers that question the same way — bend the headshell by an offset angle, and let the stylus overhang the spindle a little — and then argues about the numbers.

The demo drives the arm from that geometry rather than from canned frames. Drag the stylus across the record and the arm swings to where the real triangle puts it: pivot-to-spindle 212 mm, effective length and offset angle solved from the alignment you picked. Two dotted rings on the record are its null radii, the two circles where the cantilever is genuinely tangent. At the stylus, the green line is where the groove is going and the amber line is where the cartridge is pointing; the gap between them is the tracking error, redrawn once at ×12 because at true scale it is a pixel wide, which is itself the point.

Three published alignments and one control:

The second plot is the one that settles arguments. Tracking error alone is misleading: distortion from a crooked stylus scales with error divided by groove velocity, and velocity falls with radius, so the same half degree is about twice as audible at 60 mm as at 120. Dividing by radius is what turns three curves that look similar into three different opinions, and it is why the last track on a side is the one that breaks up.

Reuse

Render at integer scales with nearest-neighbor filtering or the edges smear. spin plays at 8 fps, cue at 4, stuck at 6 (ANIMATIONS carries all three).

The module is worth importing rather than the PNGs if you want the arm to do anything. paintScene(ctx, spec, opts) takes a frame spec directly — platter phase, groove radius in millimetres, alignment id, lifted, tick — so the arm angle is a parameter rather than baked pixels. The geometry is exported on its own too, and has no drawing in it:

Gotchas

Source

No .aseprite — the canonical source is source/inner-groove.mjs: a framework-free ES module holding the deck as a character map (one char per pixel, palette at the top), with everything round or moving painted procedurally over it. Edit and regenerate everything with:

node source/render.mjs

(needs site/node_modules installed — the script resolves Playwright from there.) That one command rewrites export/, media/ frames, thumb.png, and the demo’s bundled copy of the module, so nothing drifts. The demo screenshot in media/ comes from node scripts/screenshot-demo.mjs, which also fails on any page error — SHOT_W=900 SHOT_H=480 renders it at the site’s embed size, which is the one that catches a chart colliding with its own controls.