Talks

How I’m improving performance with 10,000 characters

This devlog is about two days of work on Pilgrimage, and mostly it's performance, performance, performance (0:23). It's a long one.

The new loading page has three monks parading around, and it's there partly because it buys a second or two while all the assets download, so starting a new game only has to generate the map (1:32). I spent about six hours with Astra and four with Fable trying to get the frame rate up, and the bar was that scrolling at 3x speed never drops below 30 FPS (5:56).

Doing less

When the game sees a sustained frame drop, it starts taking out things that don't matter to the gameplay. Every other tree goes first. Does it look as good? Not quite. But it works a lot better (4:00). Zoomed out, the characters drop their edges and most of their walk frames, the trees go and building interiors aren't rendered at all (4:25). Characters off screen aren't drawn (5:33), and a lot of what was Three.js is now sprites, so one tree is drawn a thousand times instead of a thousand trees (6:23).

Pathfinding was the biggest bottleneck. Every character is deciding where to go, whether they need water or should turn down the path to the relic, and with 10,000 of them it was 10,000 routes, all in the browser (9:47). Then I realized from the history that people in the Middle Ages didn't travel alone. It was dangerous, and kind of weird. So I added groups, and by a happy accident the pathfinding only has to work out a route for each group, which took those 10,000 routes down to about 500 (10:32).

The town

People used to sleep on the side of the road, which was a hard problem for a group, so I removed it and added taverns along the road instead (13:10). There are wells and springs, beggars when people run out of money, and shallows people wade across (14:43). Everyone ends up stooped over and too hungry way too quickly, which is fairly depressing, so that needs work (15:30).

Buildings change when you put them next to each other, which I loved in Townscaper, so a house and a tavern can share a chimney, and every building has its own layout (17:01). An inn can stand on its own or go on top of a tavern, because that's how a lot of buildings were built, one generation on top of the last (18:37). And because I can add anything I think of, there's a cheat code where one in every hundred trees stands up and walks around, the last march of the Ents (19:56).

The sprite pipeline

The characters don't use image generation. Getting consistent isometric sprites from it is unbelievably expensive, so with Astra I worked out a pipeline instead (21:31): 3D shapes, bones so a staff stays in a hand, a pass for depth, and a mask so characters get an edge when they walk in front of each other (22:15). It had made 311,000 sprites in four days, and when I wanted nuns, it reused the existing rigs and added them (24:49).

Maps that look real

I rebuilt how maps are seeded (27:15). Forests have wind direction now, because that's how seeds get carried, so the longer lines of trees look like they grew there (28:20). I wanted it to look real when you zoom all the way out, and I'm really happy with it, though the cliffs still look a bit Minecrafty (29:52). It also works well on an iPad now, with gestures, and it might be a better mobile game than desktop (26:07).

It's not a game yet, but it's getting close. The game is revealing itself to me, and now the hard part is making it fun (31:47). That's where the next devlog picks up.