4,500 brick breaker levels from pictures: an image-to-bricks pipeline
I wanted Wrecking Ball's boards to be designed, not random rows of bricks. Designed means thousands of them, because a roguelite run can go a hundred levels deep and nobody wants to see the same board twice. Drawing thousands of brick layouts by hand was never going to happen.
The answer was pictures. Every board is an image turned into bricks: a fox, a lighthouse, a slice of pizza, the Eiffel Tower, a famous painting. The library now has about 4,500.
Where the pictures come from
Open-licensed emoji, first. Twemoji is a complete, consistent set of emoji artwork under CC BY 4.0. A script renders it into 1,188 pictures in 12 themes, mapped from the Unicode emoji groups: animals, sea life, nature, food, travel, landmarks, faces, home, sports, music, holidays and more than 250 country flags. The licence is credited in the game's settings.
Generated pixel art, for the gaps. Emoji can't do famous paintings, castles or real landmarks, so those themes are generated pixel art: about 150 pictures with several variants each, including public-domain famous art reduced to a brick palette.
Shape boards, generated from motifs, fill in about one level in six.
The lesson from the first batch: for content at scale, look for an open-licensed set before generating anything. I'd started generating hundreds of pictures before realising emoji covered most of them better, faster and more consistently. That batch was stopped part-way. Generation is for the gaps and the hero art.
From image to board
Each picture is reduced to the board grid and a small palette, and every cell becomes a brick of that colour. Then:
- Steel. About 3% of each picture's side and top edge bricks become steel, never the underside and never two side by side, so skills that work on steel always have something to do.
- Gold bricks mark special parts of some pictures, such as eyes, which a few skills target.
- A shot budget for every board. Each of the 4,500 boards was played by a bot to find how many shots it reasonably needs. That's what makes a board hard or easy, not its picture.
Difficulty comes from brick health, not board type, so every picture can appear at every depth. A fox at level 3 and a fox at level 90 look the same and play very differently.
The whole library stores compactly as a palette plus one character per cell: 1.8 MB, or 312 KB compressed. The home screen still shows in about 200 ms.
Keeping it varied
My first variety rule said no board could repeat within 40 levels. It worked by board id, and deep runs kept showing the same family of shape boards, "Pocket II" through "Pocket VII": at the hardest difficulty, 21 of 23 shape boards were Pockets. Each counted as a different board.
The rule now works by subject: no fox, no flag of the same country and no shape motif repeats within 40 levels. Each theme also mixes styles: about a third full width, a third inset with side lanes, and a third hollow or carved with pockets and steel channels. The same style never comes twice in a row.
A family-friendly filter
With 1,188 emoji, some aren't right for a family game. A blocklist removes smoking, alcohol, drugs, weapons, death and money. The first version matched any name containing a blocked word, so "pill" also removed the caterpillar. It matches whole words now. Every theme also got a contact sheet, reviewed by eye.
Names in 12 languages
Every board shows its picture's name: Fox, Lighthouse, Mona Lisa. For a while those names were English in every language, because they lived in a data file rather than the game's translation tables. Nobody noticed until the German store screenshots showed English captions under the boards. There are now 1,314 picture names in each of the 12 languages.
The general lesson: any player-visible text in a data file needs translating too, not just the strings in your UI code.