NO STAIRS
The slide fired by accident and it does not go back. The stairs are not coming, and the entire delegation still has to get off this airplane.
- Desktop:
- Hold the mouse button or space to wind up a shove, release to launch. Shove on the slide's upswing and it hurls them; shove on the slack and they fold. Aim for the open limousine door.
- Mobile:
- One thumb. Hold anywhere to wind up, let go to shove. Watch the slide breathe and time it.
Devlog
A military aide fired an emergency slide by accident on the plane that serves as Air Force One, and four stories of yellow rubber unrolled onto the tarmac at Joint Base Andrews. It cannot be put back. The pressure cartridge fires once. After that it is a bag of air that will never fit through the door it came out of, and a maintenance ticket, and everybody standing around looking at it.
Every monologue took the obvious swing that night. Powerful man inconvenienced, ha. That is not what I think is interesting.
Everything else out there exists to project control. The motorcade idling in formation. The salute held exactly long enough. The airstair with the seal on it, and the choreography of who goes down it first and how far behind the second person walks. All of it is a machine for manufacturing dignity, and it works, and we have all agreed to be impressed by it.
The slide is the only object on that tarmac that tells the truth. It has one opinion, which is down, and it has no idea who you are. It cannot be briefed. It treats a four star general and a junior press aide exactly the same, and what it proves is that dignity is a surface treatment.
So I built the slide, and then I built a delegation that will not stop coming.
One scalar is the whole joke
The thing I wanted was the contrast. A buttoned, composed, rigid silhouette at the lip of the door, and then total articulated collapse the instant the slide takes the weight. Most games would animate that. I did not want an animation, because an animation is a lie that plays the same way every time, and the premise only works if nobody is fudging the tumble.
There is no physics library in this repo and I was not going to add one, so the ragdolls run on a small position based solver I wrote for this. Every body is fifteen particles wired together by two different kinds of constraint. The bones are hard and permanent: a forearm is a fixed distance from an elbow, forever, and an elbow is nothing more exotic than a minimum distance from a shoulder to a hand. The pose springs are soft, and their stiffness is divided by the square of one number per body called rigidity.
At rigidity 1 the pose springs dominate and the figure stands there holding a silhouette like a man who has been told there will be photographers. At rigidity 0 they are not merely weak, they are skipped entirely, and the same fifteen particles come apart into an honest floppy mess. The whole performance is one float going from 1 to 0 over about ninety milliseconds.
The part that took me longest was deciding when to start that clock. I had it firing on the shove, which was wrong, and it took a while to see why. Collapsing at the shove means they leave the door already broken, and a body that is already broken has nothing left to lose. Now the clock starts on first contact with the slide. They step off composed, they arc through the air still buttoned, and they come apart at the exact moment the rubber takes them. Same ninety milliseconds, completely different joke.
The slide is a trampoline, and I did not have to write that
The design called for a slide that hurls a body shoved on its upswing and swallows one shoved into a slack downswing. I was fully prepared to fake it with a scoring bonus and a fudged impulse, and I am glad I did not, because the honest version is four lines and it feels like something a fake never would.
The slide is a live pressurised lattice, not a ramp. It sags, it bulges under a body, and it rings for a second and a half after that body leaves it. So at any moment every point on its surface has a real velocity. The fix was to stop resolving bounces against a static world and start resolving them in the surface's own frame: the slide reports how fast the rubber is moving at the contact point, and restitution is computed on the relative normal velocity instead of the absolute one.
A body that meets a tube already swinging up at three metres a second leaves twice as fast as it would off a fixed ramp. One that meets the slack of a downswing is simply absorbed, folds over, and goes nowhere. The same four lines handle the tarmac, where the surface velocity is zero and the maths quietly degrades into an ordinary bounce.
There is now a real skill in this game and I never wrote a rule for it. It is just what happens when a heavy object meets a moving bag of air, which is the only thing I actually wanted to be true.
The slide breathes because it drives itself
The vision asked for a slide that is never still, and the cheap version of that is a sine wave added to the geometry. I did not want the cheap version, because the player is supposed to time a shove to the swing and a painted wave has no reason to react when a body lands on it.
So the oscillation is real. The slide is a twenty-six by seven pressurised lattice, and its inflation pressure has a pump term that feeds the lip's own velocity back into the bag, gained down as the swing approaches amplitude. The structure drives itself. Its period is a property of the lattice rather than a number I typed: it settles at 1.24 seconds with about two thirds of a metre of travel at the lip, and a body landing on it changes the shape of the next breath, which is exactly what I wanted and could not have got any other way.
Two things nearly killed it. The first is that velocity feedback grabs whatever mode is loudest, and the loudest mode in a lattice held by two stiff rails is the rails, at about 0.4 seconds. Unfiltered, the slide did not breathe, it shivered. A two-pole low-pass on the feedback fixes it for a reason worth knowing: the slow mode is driven in phase, and the fast one has already slipped past ninety degrees of lag, where the identical term damps it instead of feeding it. One filter, and the structure picks the mode I wanted.
The second is that pressure has to push along the surface's REST normal, not its live one. Inflating along the live normal is unconditionally unstable. Every dent makes its own walls push further in, and the bed rolls itself into a taco inside a second.
The game looked fine and the mechanic was not running
For about three hours this game had no skill in it at all and I could not see that from looking at it.
The slide breathed perfectly when I stepped it from a script. In the browser its lip sat frozen at minus zero point three one two, and the lattice moved exactly zero. Not damped, not drifting. Zero. Stepping it a hundred and twenty times by hand from the console also did nothing. Meanwhile the simulation clock was advancing, bodies were riding down, the score was going up and the end screen was firing on cue. Everything a screenshot can show was correct.
The cause was one line I had written myself:
useEffect(() => () => sim.dispose(), [sim])
React's strict mode mounts a component, runs every effect cleanup, and then mounts it again holding the same state value. So that cleanup disposed the live simulation and the second mount got the corpse. The slide's dispose only latches a flag that turns its step into a no-op, so nothing threw and nothing logged: the lattice quietly stopped and became a static ramp. Bodies still slid down a ramp. The thing that was missing was the only thing the game is about, which is that the ramp is supposed to be moving at the moment somebody is shoved onto it.
The guide in this repo warns about exactly this trap, and I walked into it anyway, because the object I was disposing did not look structural. It was not a mesh or a buffer or a pool. It was the whole game.
Every landing distance I measured before I found it was measured against a dead slide. The fix is to dispose the object being replaced rather than the one currently held, which takes four lines, reads worse, and is correct.
I tuned the whole night for distance and never timed the ride
The worst bug I shipped into this build was not a bug. Every number I had been optimising was about where a body lands: how far out the limousine should sit, how much a well timed shove is worth, how wide the heap spreads. All of it measured, all of it correct, and the descent lasted a third of a second.
Thirty feet of ragdoll, resolving in 0.3 seconds. Which means a two second clip of this game is two seconds of an empty slide. Everything the design asked for was happening, exactly as specified, too fast for a person to see any of it.
Two things were wrong. The shove was a throw. It pushed a figure down the slope at up to nine metres a second, so they flew most of the length of the slide through the air and only touched rubber near the bottom. A shove is a shove: it tips them over the lip and the slide does the rest.
The second fix is free, and it is my favourite piece of arithmetic in this whole thing. A body sliding frictionless down a drop of h leaves the bottom at sqrt(2gh). Its ballistic range from there is v² sin(2θ) / g, and substituting gives 2h sin(2θ). The g cancels. Gravity sets how long everything takes and has no say at all in where anything lands.
So I dropped gravity from -19.5 to -11. Every descent stretched from a third of a second to between one and two and a half seconds, everything hangs longer, the paper drifts longer, the cartwheel is something worth watching, and the limousine is still sitting exactly where I measured it should be. I did not have to re-tune one distance.
A heap of ragdolls is flat
Landing on the pile is worth a rising combo, and for a while almost nobody ever did. The rule I had written was the obvious one: if a body comes to rest appreciably above the tarmac, it is resting on somebody. That sounds correct and it measures terribly. I ran a full delegation and looked at where the twenty-one of them actually stopped, and the mean centre of mass was thirty-five centimetres off the ground with a maximum of eighty-nine. A heap of limp bodies does not stack like boxes. It spreads, and it is flat, and any height threshold high enough to mean something almost never fires.
So the test is proximity now. A body that came to rest against the heap is on the heap. It is the same rule a person would use looking at the photograph.
The other thing measuring bought me was seven times the frame rate, and both halves of it were the solver doing enormous amounts of work to discover there was no work to do. Bones are authored right after their body's particles, so a body's constraints sit in one contiguous range, and recording that range lets a settled body's two thousand constraints be skipped in one comparison instead of walked in full every substep to find that both ends are pinned. Then the slide: every particle in the game was asking it to search its lattice seven hundred and twenty times a second, including the twenty bodies lying in a heap eight metres past the foot of it. It publishes a bounding box now and they get rejected with six comparisons. Fifteen milliseconds a frame became two.
The yellow needed something that was not yellow
I told this build to make the sliding lane the brightest yellow in the frame. The slide is the hero, the palette has exactly one hero colour, so more of it is better. That is wrong, and both reference photographs had been telling me so all night.
A real evacuation slide is two saturated yellow rails with a pale silver-grey fabric lane between them. Painting the lane yellow too produced one yellow blob with no internal structure: no rails, no floor, nothing for the eye to resolve at phone size. Hue is what separates a rail from a floor. The lane is grey now, pitched a step darker than the fuselage where the slide crosses it and two steps brighter than the tarmac where it lands, so one continuous silver stripe survives against both.
It is the same argument as the single-hue palette itself, which I had also been applying carelessly. The yellow is loudest when it is the only yellow. Giving it more territory does not make it scream, it makes it a background.
What goes down the slide
The delegation escalates, because nobody is willing to be the one who says this is a bad idea. A man handcuffed to a briefcase. A general with his hat on, and the hat does not stay on. A press secretary still talking. A marine band tuba player, tuba first. A sheet cake. The dog. And finally a folding airstair, arriving far too late, which goes down the slide as well, because at this point that is the procedure.
Every one of them is a different physical question. The answer is always a cartwheel, and I checked that rather than hoping. Each of the nine, at a weak shove and a hard one, turns at least one full rotation on the way down and most turn two to four. Nothing just slumps.
The two that surprised me are both the rigid ones. A hard shove sends the lectern three and three quarter turns and thirty one metres, past the motorcade entirely, and the sheet cake turns four and a half. Both go further and faster than any of the people, and once I saw the numbers it was obvious why. A body full of loose limbs spends its energy flailing them. A lectern has nothing to spend it on, so it just goes.
Nobody is hurt. Everybody bounces. The suits stay on.
Leaderboard
Loading…