Skip to games
Hadukis

Writing

Why our forts fell down on their own

· 4 min read

A physics-demolition game has one promise that comes before any other: the thing you are about to knock down is standing up. In early builds of ScaleSling, some forts trembled when the level loaded, and a few simply fell over while the player was still lining up the first shot.

It is very easy to blame the physics engine for that, and to start adjusting friction and density until the wobbling stops. We nearly did. None of the causes turned out to be the engine.

Twenty-four pairs of blocks, born inside each other

Every level is a list of blocks with a position and a size, and every one of those numbers was typed by hand. A plank 42 pixels wide placed 32 pixels away from its neighbour overlaps it by ten. On screen, ten pixels of overlap is invisible — the sprites just look like they touch.

Two rigid bodies cannot occupy the same space. On the very first step of the simulation the engine finds them overlapping and pushes them apart, hard. The push is what the player saw as a tremor, and in a tall stack it was enough to bring the whole thing down.

A script that reads every level found 24 overlapping pairs across 16 of the 24 levels, overlapping by 3 to 11 pixels. A second script separates each pair along the axis where they overlap least — which is almost always the axis the level author meant them to meet on — half the distance each, over a few passes so that fixing one pair does not create another. It leaves rotated blocks alone, because the real footprint of a tilted plank is not its width and height.

A fence with a missing post

Five levels shared a fence that had been copied from one to the next: a beam 130 pixels long resting on a single post. Its centre of mass sat 39 pixels beyond the support. It tipped, every time, and dropped 48 pixels before anybody touched it.

The first idea was to slide the beam back over the post. That was tried, and it pushed the beam into a longer beam next to it, which is worse. The beam was not too long; the fence was missing the post at its far end. Adding it fixed all five levels at once.

How we know it's fixed

The answer is not "we played the levels and they looked fine." There is now a stability check that loads each level into the real physics engine, fires nothing, waits four simulated seconds and measures how far every block moved.

Before the fixes, six levels collapsed on their own and the worst block moved 48 pixels. After them, none do, and the largest movement anywhere is 10 pixels — the normal settling of a stack finding its rest. The check runs without a browser, so it runs every time a level changes.

The block that came out half as tall again

One cause was not in the level data at all. A plank asked for at 26 by 88 pixels was arriving in the world at 26 by 131. A troll with a collision radius of 27 had a radius of 20.

The framework the game is built on scales an object's physics body along with its picture. Declaring the body at the right size and then resizing the sprite to fit scaled the body a second time, by the ratio between the image file and the requested size. Nothing printed an error. Towers simply rested twenty pixels above the ground, and shots passed through things that looked solid.

The fix is to size the picture first and then replace the body with an exact one. The only way we found the problem was by measuring the bodies directly rather than reading the code, which looked correct — and that is now how every new object type gets checked.

One more trap: stars

Each level awards three stars at 95% of the total points on the board. That target is written into the level file when the level is generated, not worked out when the game starts.

When the airships were removed from six levels, each lost 900 points of things to destroy — but the three-star target still asked for them. Six levels that could be completed perfectly became levels that could not, and the change looked like a single deleted object. Any edit to what is on a level's board now recalculates its stars in the same change.

The general point

A structure falling over looks like a physics problem, so it invites physics fixes: more friction, heavier blocks, a slower simulation. Every one of those would have hidden the real faults and made the game feel worse to hit. The causes were data — typed coordinates, a copied fence, a stale number — and the thing that found them was measuring, not tuning.

The forts in ScaleSling now stand until you knock them down. Try knocking one down.

Filed under gamedev, physics, level-design.