Source lives here. Play it here.
In a joint effort, Aliasing and myself have created a novel top-down action rogue-lite for the 2023 Spring Lisp Game Jam. Aliasing is an experienced game dev so in a way, I was along for the ride. Still, I managed to contribute some game mechanics, features, unit testing, CI/CD that deploys to super-rogue.workinprogress.top on every commit. This was a fun devops exercise for me - Aliasing mentioned to me that I helped keep him on track with the addition of automated testing and per-commit deploys to a website (it makes it easy to play-test pull requests).
§Technologies used
The game runs in Love - a game engine that is programmable using Lua.
The game is written in Fennel - a lisp embedded in Lua. Why Lisp? Structural editing. Everything-is-a-value semantics. Less-varied syntax which is easier to read and type. Macros unlock the capability to parameterize code at compile-time - leading to expressive, concise code.
The CI/CD and local builds used Nix. There is one exception - to save on development time we opted to use an existing GitHub action for the Linux and Windows release builds. macOS builds forthcoming.1 Nix proved to be a helpful choice: we had issues with failures that would occur only in GitHub Actions early on, so we opted to use a flake to specify exact dependencies to use for each build.
§Playing to our strengths
Aliasing is an experienced, very clever game dev and I learned a lot about making a game in Love (in fennel, no less!) as a team. Aliasing built the game engine on top of love while we deliberated on game design ideas. Personally, I have no game dev experience, but I do have a lot of devops and project management experience.
While Aliasing worked on core game mechanics, I used my devops skills to create a runway for success. Here is a brief list of the devops and PM strategies we used:
- We used a PR workflow but reserved the right to merge if the other is AFK for too long.
- We set up the unit test support. Took a lot of research as there’s a lot of testing frameworks, our first couple choices didn’t meet our technical requirements.2 We ended up using luaunit.
- We set up the web, windows, and linux deploys. Each commit would result in a new test game webpage. This allowed us to playtest every change in our pull requests. Because of the sheer convienence it was easier to playtest than to review the code.
- We met to re-prioritize tasks once or twice. Mainly to just make sure we’re aligned on our goals and ideas of done-ness.
§Call to action
Whenever I end up working on something I have this wish-list of things I hope existed. Does anybody else wish these things existed?
- devdocs.io/Zeal/Dash docset for Fennel
- devdocs.io/Zeal/Dash docset for Love
- A contract system for Fennel. Think like Racket contracts or Pycontracts.
- A nix derivation that has a headless flag as to reduce runtime dependencies of Love. This would to speed up GitHub Actions running the Love binary - such as unit tests.
If you’re building any of these things I’d love to help… :)
§That’s it
I had a blast and I’m looking forward to another opportunity to tackle some engineering problems like this again. I’m sold on Fennel. Whenever I need tot rouch a system programmable in Lua, I’m using Fennel from now on. A lot of software uses Lua for its scripting engine.3 Feel free to hack on the source code or open a PR. Or maybe just play the game :).
-
The lack of macOS build isn’t due to a lack of trying; I had tried to re-install macOS on a 2014 Mac Mini, however it seems Apple’s “Internet Recovery” feature errors out during installation. Additionally I tried to obtain a macOS installer USB. Turns out it is not trivial to write a macOS installer USB as Apple does not publish download URLs. I found some mediafire links to the .DMG files, however had no luck using dmg2img then writing it to a USB - dang thing wouldn’t boot. I am not an Apple fan, except for
AAPL
stock performance. ↩︎ -
The tests must run within love2d. This eliminated a few that use an external program to run tests. The other requirement was it had to work with fennel. Some use globals injection at test-time, which breaks fennel’s compiler as it can’t resolve variable references. Also easy to use would be ideal. ↩︎
-
Some programs that I use that are scriptable in Lua:
- Awesome window manager
- Love2d the game engine as seen in this post
- MPV the multimedia player
- Pandoc document processor/converter
- Nmap uses it for scripting. If you ever want to see super basic protocol implementations - check out its service discover scripts.
- Many games including: Factorio, World of Warcraft, BZFlag, Project Zomboid, NetHack, The Battle of Wesnoth, and so on.