Laurent Le Brun wanted to make a game in seven days. So he started by writing a programming language.
That is a terrible idea in most schedules and an excellent one for the Langjam Gamejam, whose rule was precisely to create a language and then use it to build a game.1
The result, shmup8, is a Windows shoot ’em up whose final executable is roughly 3 kB.1 The code is public and a playable build is distributed on itch.io.2 3
The interesting part is not only the number. The size constraint ended up shaping the language, engine, workflow and even what enemies are allowed to do.
A VM can save more than it costs
Le Brun builds a compiler in F#, an interpreter in C++, then writes the game logic in his custom language. Rendering happens through a single fullscreen GLSL shader.1
You might expect the interpreter to be an absurd luxury when every byte matters.
At the end of the project, he ports the game logic to C++ to check. In his measurement, the version without the VM ends up 90 bytes larger than the bytecode version.1
He explicitly asks readers to take that result with a grain of salt: neither the C++ port nor the interpreter was pushed through exhaustive optimisation.1
The sensible conclusion is not “VMs are smaller than C++.”
It is that a tiny intermediate language can offset the cost of its interpreter when it encodes one narrow game domain very efficiently.
One type and almost no manners
The bytecode essentially uses one type: float32.1
Values live in arrays. A local variable takes a slot. An index is also a float and gets converted to an integer when needed. A condition becomes true above 0.5.
The bytecode boils down to two broad kinds of operation: update a cell or jump to another address, optionally under a condition.1
The language visible to the author stays slightly more civilised through syntactic sugar: assignments, if, while, and for loops transformed by the compiler.1
The separation is conventional, but the constraint makes it unusually visible: the syntax can stay pleasant as long as the executed format remains brutally simple.
Live reload protects the creative loop
The most useful part of the write-up may not be the compression.
Le Brun wanted to change logic and visuals without rebuilding the C++ project. On each source edit, his custom compiler produces new bytecode, and the already-running executable reloads that file every frame. The GLSL shader reloads in the same way.1
Two live-coding loops sit next to each other.
That preserves something technical constraints easily destroy: fast visual iteration.
Le Brun makes the point directly. In creative work, you cannot reliably predict what will feel good before trying it.1
Even the enemies are designed by the constraint
The game starts with three enemies and adds another every seven seconds.1
When a missile hits one, the enemy does not die. It gets teleported outside the screen and can return later.1
Why the unexpected immortality? A list of waves, destruction and more state would have required more logic. Le Brun chooses a simpler rule that still increases difficulty.
Runs are designed to last roughly 30 to 60 seconds, with fast restarts.1
The size limit therefore did not merely compress the finished program. It produced game-design decisions.
Constraints become useful when they arrive early
shmup8 is obviously not a sensible architecture for the next 80-hour RPG.
But it demonstrates something transferable: a constraint becomes interesting when it influences the system from the beginning.
If you decide at the end that a game must be small, you compress assets. If you decide at the start that it must be tiny, you invent a bytecode, draw everything through one shader and ask whether enemies really need to die.
At 3 kB, even a game mechanic starts looking like a storage decision.
