You are in the basket at dawn. There are two controls. The burner puts heat into the envelope; the vent line opens the crown and dumps it. That is the entire input surface. There is no left, there is no right, and there never will be — a balloon has nothing to push against, so horizontally it does not travel through the air, it is the air.
Which would make the whole thing a lift, except for one fact the game is built on: the wind is not one wind. It is a stack of layers, and they disagree. Down low the air is running right at nine or ten metres a second. Up at three hundred it is running left, harder. Between them is a lazy shear layer that barely moves at all.
So the steering wheel is the altimeter. You go right by being low. You go left by being high. You stop by finding the calm. Every horizontal decision in the game is really a vertical one, and the job is three markers in order and then back down onto the X you took off from.
Why it is hard
Nothing you press happens when you press it. There are three lags stacked on top of each other, and they are all real:
- Heat → lift. The burner adds about 12 K/s to an envelope that is always leaking heat back out. Going from hover temperature to a solid climb takes five or six seconds of flame.
- Lift → rate. Buoyancy fights quadratic drag on a very large bag. Even once you are light, the climb rate takes another several seconds to build, and — this is the part that lands people in hedges — it takes just as long to stop.
- Rate → drift. Crossing into a new layer, the balloon needs a couple of seconds to give up the speed of the layer it left.
Add them up and you are steering on a ten-second pipeline. The correct time to start a descent is well before you want to be descending, and the correct time to stop one is embarrassingly far above the ground.
The technique: fly the box
This is not a game contrivance, it is the thing balloonists go looking for every morning, and it is why a sport with no steering can land back where it started.
- Out on the low flow. Climb to about 95 m, where the right-hand wind is strongest, and let it carry you to marker 1.
- Up through the calm. Around 185 m the air is nearly still. Climbing through it costs you almost no sideways distance, which is exactly what marker 2 is placed to reward.
- Back on the high flow. Above 250 m the air runs left at twelve. Marker 3 sits in it, and so does the return leg.
- Down through the shear, aiming short. The descent is the whole trick. Dropping back through the low layer pushes you right again, so the field is not something you descend onto — it is something you descend upwind of and let the surface flow deliver you to. Come down over the X and you will land a hundred metres past it.
The pennants on the pad edges stream with the surface wind, and every cloud in the sky drifts at the speed of the layer it is sitting in. The wind ladder up the right-hand edge is the same information written down: it shares the world’s vertical axis, so the arrow level with your basket is the air you are actually in. The tick on the heat gauge is hover — the temperature at which the envelope exactly carries the weight. Above it you rise, below it you sink, and the envelope drifts down toward the tick on its own the moment you stop burning.
Fuel
85 seconds of flame for a flight that takes around three minutes. Holding level costs roughly a fifth of a second per second, all by itself, because the envelope is always cooling. Climbs cost real money. Venting costs nothing at the time and everything later — it throws away heat you already paid for, and you will want it back on the approach.
Running dry is not a fail state. It makes you a glider with one direction left, and where you end up is decided entirely by which layer you happen to be in when the flame goes out. That is a more interesting punishment than a crash.
Reuse
src/burner.js is framework-free and DOM-free: createGame() returns a state
object, step(dt, {burn, vent}) advances it, and windAt(y) is the whole
atmosphere in one pure function. Swap the PROFILE knots and you have a
different sky; the course, the scoring and the renderer all read from it rather
than assuming anything. src/render.js owns the camera, the clouds and the
scenery, and touches no game state.
The envelope is drawn as ten real gores — each one a strip walked crown to mouth along the same girth function that defines the silhouette — rather than a circle, which is why it reads as a bag and not a balloon emoji at 30 pixels across.

