workshop private

← all creations

Sway

games · created 2026-09-05

A ship-to-shore crane with two controls and no brakes on the part that matters. Six boxes off the quay and into the cells, against a clock that only counts the seconds you spend chasing a pendulum you started.

physicsgame-feelcanvassimulation

You are up in the cab of a container crane. Two controls: the trolley runs left and right along the boom, the hoist pays rope out and takes it back in. That is the whole input surface. There is no “stop the load” button, because there is no such thing.

The load hanging forty feet under the trolley is a pendulum, and it is the only opponent in the game. Every metre per second you put into the trolley goes somewhere, and where it goes is into the swing. Start moving and the box lags behind you; stop moving and it comes past you. Do that twice in a row without thinking about the timing and you are standing over the cell you want with a nine-metre box scything through it at walking pace, unable to put it down.

Six boxes, bottom tier left to right and then the tier above it. The clock runs from your first input. A box only seats when it touches down slow and square; land it hard or crooked and it seats scuffed, +3s. Drag it through a stack you already built and that is a strike, +4s. Nothing is scripted — a landing is clean because the load was actually slow when it touched.

The technique

Everything in the game falls out of one fact: a pendulum’s period depends only on its length. At the rope lengths you work at, a full swing is about four seconds, and four seconds is long enough to plan inside.

The two instruments

The game has almost no HUD, but it has two drawings that are doing real work:

The envelope. The dashed outlines ahead of and behind the load are where the load will be at the ends of its arc, computed from the linearised amplitude √(θ² + ω²L/g). It shifts from teal to red as the arc grows. An operator in a real cab can see this by looking; a player at a screen cannot, so it is drawn. The dotted line hanging from the trolley is the rest position — plumb in still air, leaning downwind when there is any.

The phase dial, bottom left: swing angle across, angular rate up, both normalised. A still load is a dot in the middle. A swinging one orbits, once per period, and the radius of the orbit is the amplitude. What makes it an instrument rather than a readout is that trolley acceleration drags the orbit’s centre sideways — so the entire technique of the game is visible as one rule: push when the dot is on the far side of centre and the orbit shrinks; push when it is on the near side and you have made your problem bigger. The small teal ring in the middle is the size the orbit has to be before a landing will seat.

Wind arrives after the second box. It does not make the load swing — it makes it hang somewhere other than plumb, which is a different problem and one you solve by aiming the trolley off the cell rather than by fighting it. Both instruments account for it: the dial’s centre and the envelope both move with the wind.

What’s under it

src/sway.js is the engine — framework-free, headless, no canvas anywhere in it. The pendulum is integrated at 240 Hz in a substep loop:

θ'' = ( −g·sinθ − a_trolley·cosθ + a_wind·cosθ − 2·L̇·ω ) / L − c·ω

The 2·L̇·ω term is the one that earns its keep. It is the Coriolis coupling between hoisting and swinging, and it is why hoisting a swinging load makes it worse — without it the rope length would just be a number and the hoist would be a second, boring axis.

Collision is one function. surfaceUnder(x0, x1) returns the height of the tallest thing under a footprint — quay, deck, deckhouse, the box waiting on the apron, every box already stacked — and that single query answers landing, stacking, and “did I just drag this through the tier I built”. If the box’s bottom is under that height, it is either a seat (aligned, slow, over the live cell) or it is a strike, and the resolution is the same either way: take the rope back up to where the box actually rests.

Gravity is 30, not 9.81. At true crane proportions a thirty-metre rope swings with an eleven second period; you would spend the entire game waiting for the load to come back. Scaling g puts the working range at 3.5-5 seconds per swing, which is slow enough to plan inside and fast enough that a mistake costs a beat instead of a minute. Everything else — the coupling, the amplitude law, the input shaping, landing on the arc’s end — is the real physics, and it all still works, because none of it cares what g is.

Reuse

Gotchas