Onionskinning sprite sheets
Every frame of a clip drawn over every other, so a frame the pack moved shows.
A rip crops each frame to its ink, and a packer that centres each frame in its cell moves the body whenever a frame's ink is wider. Drawing every frame of a clip over every other shows that move, and one number says whether two frames are one drawing.
Measuring two frames
- Put two frames on one canvas and, for every whole-pixel shift in a window, score how much of the two inked areas fails to overlap:
miss(dx, dy) = |A xor shift(B, dx, dy)| / (|A| + |B|). - The best shift is the packer's offset, and the miss there says how far to trust it:
| Miss at the best shift | The two frames are | What to do |
|---|---|---|
| ≤ 0.15 | one drawing in two crops | Take the shift out. |
| 0.2 to 0.6 | two drawings: a pump, a stride, a death | Leave it. |
| ≥ 0.6 | unrelated | The frame list is wrong. |
Measure what lands on screen: where a frame is drawn at an offset, measure after that offset is applied.
What must not move
- A sprite drawn at a fixed place on the screen, such as a held weapon, a HUD part or a cursor: two frames that are one drawing are on one anchor, with no drift.
- A sprite drawn at its own place in the world, such as a monster, a pickup or a projectile: it is anchored bottom-centre, and a walk may sway a pixel on purpose. Look at the picture and the number, and do not force the frames to zero drift.
Pinning an overlay
- A muzzle flash, glow or shadow drawn over a body usually carries a few of the body's own pixels at its base. Score each shift by how many opaque overlay pixels land on a body pixel of nearly the same colour; a few dozen matches pins it.
- Pin the group by the frame that matches best, and let every other frame of the same drawing follow it by the overlap measure. Frames pinned one by one on weak matches end up far apart.
- A frame that carries no body pixels, such as a flame drawn clear of the barrel, puts its own middle over the topmost inked row of the body.
The picture
Make one PNG per clip: every frame's silhouette tinted along a hue ramp and added over a dark ground, with the frames in a strip at 1:1 underneath. Agreement is white, and drift is a coloured fringe on one side. Keep them at docs/onionskin/<sheet>.<clip>.png.
Checking it
| What you see | The cause |
|---|---|
| The body slides side to side as the clip plays | Each frame was centred in its cell. |
| The body jumps up or down between frames | The frames were not bottom-aligned on one baseline before packing. |
| An overlay is offset the same way every frame | It was placed by its cell, not by the body it belongs to. |
| Two overlay frames far apart | Each was pinned on its own weak match. |
| The check passes and it still looks wrong | The frames are different drawings; the frame list or timing is wrong. |
A clip whose stack is white with thin coloured edges where a part moved is on one anchor. Two whole silhouettes in two colours is a frame the pack moved. Make the test of a sheet whose sprites must not move fail when any held frame that is one drawing with its neighbour is off its anchor.