workshop private

← all creations

Skipstone

mechanics · created 2026-09-12

A stone skipping on flat water, where the two controls that decide the throw are both ones you cannot feel — and the one that kills you leaves a perfect first skip behind as evidence that nothing went wrong.

physicssimulationgame-feelcanvas

You get three dials. How hard you throw it, what angle the stone is tilted at when it leaves your hand, and how fast you spin it. Only the first one has any feel to it.

The other two are decided in the last fifteen centimetres of a wrist snap, you cannot see either of them while the stone is in the air, and between them they decide the whole throw. Worse than that: when you get the spin wrong, the first skip comes out perfect. Twelve metres a second in, ten and a half out, a clean ring on the water, exactly like a good throw. The stone is already dead at that point. It just has three metres of flight left in which to demonstrate it.

Twenty degrees, and it is not a preference

There is a number in the stone-skipping literature — Clanet, Hersen and Bocquet, Nature 427, 29 (2004) — that says the best angle to hold a skipping stone at is 20°, and that this is a property of water rather than of stones or of arms. This model was not told about it. It has a reaction force, a wetted-area calculation, rigid-body rotation, and one fitted constant, and the constant has nothing to do with angles.

Ask it the question the paper asks — what is the slowest throw that still bounces? — and it answers this:

angledepth budgetslowest throw that bounces× the minimum
2.1 mm20.55 m/s7.74×
4.2 mm10.37 m/s3.91×
6.3 mm6.99 m/s2.63×
8.4 mm5.31 m/s2.00×
10°10.4 mm4.33 m/s1.63×
14°14.5 mm3.23 m/s1.22×
20°20.5 mm2.65 m/s1.00×
26°26.3 mm2.83 m/s1.07×
30°30.0 mm3.03 m/s1.14×
40°38.6 mm3.72 m/s1.40×
50°46.0 mm4.76 m/s1.79×
60°52.0 mm6.35 m/s2.39×

Minimum at 20°, within ten per cent of it from 18° to 26°. I did not tune for that and I did not expect it to land on the number. It falls out of two opposing costs, and both of them are worth understanding because they are what the game is made of.

Why shallow fails: the depth budget

A stone planing on water is a plate with water under it and air over it. That air is the entire mechanism. The push holding the stone up is the pressure difference between a wetted underside and a dry top, so the moment the leading edge goes under, the flow closes over the stone, the difference goes to zero and what is left is a disc being dragged through a lake.

Which means the stone’s whole vertical allowance for turning itself around is the height of its own raised edge, twice over: 2a·sin(β). That is the second column of the table, and at 4° it is four millimetres. Four millimetres to absorb a stone arriving at two and a half metres a second and send it back up. There is only one way to buy that: arrive fast enough that the force is enormous, which is why the critical speed column explodes at the top of the table rather than drifting.

This is also why “throw it flat” is bad advice given in good faith. A flatter stone really does present its whole face to the water and really does get a bigger contact area — and it has nowhere to put the stone while that area develops.

Why steep fails: the reaction points the wrong way

The water pushes perpendicular to the stone’s face, not against its direction of travel. So the same push that lifts the stone also brakes it, and the ratio between the two is fixed by geometry: for every newton-second of upward impulse you buy, you pay |v·n| / cos(β) joules, where v·n is how fast the stone is closing on its own face. Tilt it steeper and that closing speed rises with no corresponding gain. At 60° every bounce is expensive enough that there is barely a third one.

And the asymmetry is the actual advice

Read the table’s last column around the minimum and the two failures are not the same size:

Four and a half times the penalty for the same error in the other direction. So the thing to take out to a lake is not “aim for twenty”. It is if you are going to miss, miss steep — and that is a piece of advice nobody gives, because the failure it protects you against looks like bad luck rather than a bad angle.

The reach curve, and the honest version of it

Skip counts are integers and a bouncing stone is chaotic — two throws a tenth of a degree apart can differ by three skips, and any single run is an anecdote. So everything below is 21 throws per point with hand-sized jitter on the release (±1.5° of angle, ±2% of speed), which is the only fair way to ask whether one angle beats another.

At 12 m/s and 15 rev/s:

anglemean skipsspreadreach
2.20–44.4 m
4.04–56.2 m
4.74–57.0 m
12°5.44–78.1 m
16°5.84–79.0 m
20°6.45–79.2 m
24°6.15–78.9 m
28°6.04–98.3 m
34°5.64–77.9 m
40°4.94–57.4 m
50°3.53–46.1 m

Same shape, same peak, same lopsided skirt — gentle on the right, a cliff on the left. And the spread column is the reason the demo’s coach curve is baked offline rather than computed live: at 28° the honest answer is “four to nine”, and drawing one sample of that as a curve would be a lie with a line through it.

Run the same sweep at 8, 12, 16 and 22 m/s and the peak wanders — 16°, 24°, 20°, 12° — which is the integer noise talking and not a real drift. What does survive is that every speed’s 90% band contains 20–24°. Throwing harder multiplies the answer; it does not move it. That is what you would hope for from the argument above, since both of the costs it balances are ratios that the release speed cancels out of.

The spin, which is where the game actually lives

Set the angle perfectly and throw with no spin:

rev/smean skipsreachhow it ends
01.02.8 mwent in
12.05.2 mwent in
23.06.5 mwent in
55.08.4 mwent in
87.48.3 mran out of speed
206.69.9 mran out of speed
4510.612.4 mran out of speed

One skip. Not “fewer skips” — one, and it barely varies, because the mechanism is not gradual.

Here is the part that makes it a mechanic rather than a tip. The first contact of the unspun throw and the first contact of a good throw are the same contact:

0 rev/s15 rev/s
entered at20.0°20.0°
left at17.1°17.5°
speed12.0 → 10.5 m/s12.0 → 10.5 m/s
time in the water10.2 ms10.3 ms

Identical, to the tenth. Nothing has gone wrong yet in any quantity you could observe. The difference is in a quantity you cannot:

spinleaves contact 1 atturning atarrives at contact 2 at
0 rev/s17.1°−341 °/s−56.0°
5 rev/s17.1°−307 °/s+17.8°
15 rev/s17.5°−85 °/s+19.4°
30 rev/s18.4°+183 °/s+23.4°

Both stones leave the water turning at about the same rate. The spun one is not being held still. What spin changes is what that turning does: with angular momentum along the stone’s own axis, a sideways torque produces precession — the tilt goes round rather than down, and comes back. Without it, the same torque is just pitch, and pitch integrates. Three hundred and forty degrees a second for a sixth of a second is a stone arriving at its second contact fifty-six degrees nose down, edge first. It does not skip. It spears.

The water torques both stones equally hard. Only one of them is built to ignore it.

What that means with a controller in your hand

The demo will not tell you your spin was wrong at the moment it was wrong, because nothing in the world tells you that. You throw, you get a skip that looks like every good skip you have ever thrown, and then the stone goes in like it was aimed at the bottom. The tell, if you are watching for it, is in the microscope pane: a stone that leaves contact one turning is a stone you have already lost, and the number is on screen a full flight before the failure is.

That is the whole design. Two invisible controls, two invisible failures, and one of them politely provides a perfect-looking skip as an alibi.

Where the energy goes, on one contact

12 m/s, 20°, 15 rev/s, the first touch:

A quarter of the throw’s energy is spent in ten milliseconds by a quarter of one face going five millimetres under. Everything this piece is about happens inside that, which is why the demo has a pane that does nothing but look at it, at about fifty-five times life size.

Playing it

When the run ends the view pulls back to hold the whole throw, and if your angle was more than a couple of degrees off, it runs the same throw at the angle the curve prefers and lays its skips on the strip underneath yours.

Reuse

src/skipstone.mjs is a framework-free ES module and draws nothing.

A full throw is about 160 ms in Node, so a sweep is a coffee and a live per-frame curve is not on the table.

Gotchas