LangJam GameJam
For this year’s LangJam GameJam, my friend Eymbr and I built a narrative platformer. You jump around, avoiding spikes and cliffs, and you can speak to NPCs to understand the story. Eymbr wrote about 5 pages of lore for the game, including a few conversations. The game’s music consists of two of Eymbr’s songs. We encoded the dialogue system using the Yarn programming language, which is a writer friendly way to describe interactive narratives.
I created a running animation for the main character; this was my first time animating. Motion is a key part in building engaging videogames. I used the Phaser3 game engine in TypeScript to implement the rest of the videogame. I implemented a way to run Yarn scripts using Gleam, a new programming language that makes it easy to write correct (less bugs!) yet fast programs. Other programming languages like Rust, Haskell, OCaml, and Elm use similar strict type systems that help prevent bugs and save time. Gleam compiles to TypeScript/JavaScript and it was straightforward to use the Gleam code from within TypeScript.
I implemented a parser and an interpreter for Yarn using Gleam. I used the Atto parser combinator library to read Yarn files. Then, I generated a list of instructions, which are run by a interpreter working on immutable data. All of this code runs from within the videogame to power its dialogue system, and I also wrote a development environment with Gleam’s Lustre library (similar to React).
While the interpreter was perfect for development speed, it’d make more sense to write a dedicate interpreter for the instructions in JavaScript. The Gleam parser and interpreter are over 11 megabytes of compiled JavaScript, while the game needed less than 1 megabyte excluding music and images. With a compiler, I could embed the list of instructions and a more efficient interpreter using less space. Another alternative is compiling the program into official Yarn bytecode, and then this code could run on any Yarn VM. I also want to write test programs in Yarn to see how well the implementation performs compared to other languages. Yarn is an unusual programming language, but it is Turing complete so it can run any type of program.
What took me the longest was thinking of a programming language to implement. This is also the second interpreter I’ve implemented this year, the last one was based on the 2nd part of Crafting Interpreters. It is an extended implementation of Lox written in C with a Pratt parser and enough language extensions to run complicated programs like big-integer algorithms and the FFT algorithm. I wanted to achieve something similar with the language I chose for this gamejam, but I didn’t have enough time to fully test my new language with the same rigor.
This week was my first time working with Gleam. The minimal syntax and the “one-way-to-do-things” in Gleam helps a lot with productivity. The compiler caught most of my bugs ahead of time, but I found a couple runtime crashes that I’ll post about on Gleam’s Github issues if needed.
This year’s Langjam Gamejam was AWESOME and I look forward to next year’s.
The game is published on itch.io, an open game publishing platform.
Check out all this year’s 35 entries.
All source code, including the unused Haskell and Scheme practice code, is openly available on GitHub
The Gleam Yarn parser and VM will be published as Gleam packages after I clean up the code. See this new Github repo later.