So here’s a postmortem of my attempt of participating in the Autumn Lisp Game Jam, 2021. For those who don’t know, the Autumn Lisp Game Jam is a fun little contest to write and release a full video game in some kind of Lisp programming language, in 10 days. I’ve done several other game jams before, with varying levels of success, but they were all of the Ludum Dare format: One weekend spent on it, and they announce a theme that the games are rated on the instant the jam starts. This has some big effects on the experience, obviously. You are basically working nonstop for 48 or 72 hours (it’s wise to pre-make some good substantial sandwiches before hand and make sure you get enough sleep during the jam), and nobody knows what they’re going to be doing before the game jam starts so everyone basically has to design a game from almost nothing first thing.

ALGJ, on the other hand, has no theme and is 10 days long. This means you have to pace yourself, but you can also do more pre-preparation. It’s a very different experience. You can easily come up with at least an idea of a game beforehand, and you have long enough to work on it that your scope can be broader, but you can also burn out faster or (in my case) procrastinate more. The pressure is a lot lower, which is nice, and you can make a slightly more ambitious project at a slightly more measured pace. It’s actually quite difficult to prepare your tools and such without actually “cheating” though, at least for me (nobody is gonna keep track of such “cheating” or care too much, but I care). I also had to juggle both the game jam and work my day job though, which didn’t really make life easier, though I had the week that the jam ended off for vacation. All in all it’s an interesting experience.

The most annoying thing I’ve always had to grapple with when using Lisp is always what tech stack to choose. My experience is also not up to date, since for the last 5 years Rust has basically been everything I’ve ever wanted, but my experience with Lisp gamedev stacks has never been particularly good. Common Lisp is full of interesting, well designed and half-baked tools, including disparate package managers. Scheme is similar, except everything is more minimalist, and you often have to cleave to a particular implementation (Chicken, Gambit, etc) and stick to it. Clojure and Racket both look promising when it comes to modern conveniences, but they haven’t hit any of my needs hard enough that I know much about them and I’m not going to learn right off the bat for this jam. So instead I trod off my usual beaten path and tried Fennel.

I don’t recall how I learned of it, but Fennel is a Lisp that compiles to Lua code, and seems to take a fair amount of inspiration from Clojure. I’d heard of it but never used it before, but it was suggested I try it by other prospective game jammers, and after some looking at it and playing around I decided that Fennel + Love2D was a good way to go. I am passably familiar with Lua and Love2D, and I like them both, so revisiting the ecosystem after a long stint in Rust-land seemed nice. TIC-80 also looked appealing but I don’t know anything really about it and didn’t feel like learning on short notice, so that might be a project for the next game jam but not this one.

All in all, my entry was not particularly successful. I made the skeleton of a game but no actual content, basically, which seems to be where I get with lots of my games. The tech is the most interesting part, and also the easiest to tackle since I have done it a few times. When I ask myself “what do you actually want to do with it” either my reach exceeds my grasp or inspiration for actual specifics ends up eluding me. Still, I was advised to upload what little I had, and I’m glad that I did since making a release is a nontrivial part of the process. I think I’ll keep working on the game for a little longer and make an actual level or two, maybe a boss fight, and call it done later.

So that’s the executive summary, now for the details if you’re still interested. I habitually journal anyway, so for most of the jam I just wrote about it in my journal with the intent of pulling from it later and forming this postmortem. I think instead I’ll keep it in the original format of daily notes, since I feel like it explains the process pretty well, and also has some interesting technical tidbits. Most of it is a running experience of what it’s like trying to do a game jam with low-key bipolar disorder.

Content warning: Depression

15/10/21 Friday

Did some thinking about my Autumn Lisp Game Jam entry. I was thinking of making a RPG fighting system game, kinda like Epic Battle Fantasy or such, and my old project Faequest was the obvious setting and inspiration for it. Then I read through my old design notes for Faequest and was like “…damn, I put a LOT of work into this”. Then I was like “…and I still don’t have an actual story to tell, more just a bunch of disconnected shenanigans.” Then I thought “…Is this even a good idea? Could I do something different? Maybe something simpler with less context to catch up on? What about… what about like, a bullet hell?” And so now I’m going to make a bullet hell. It may or may not end up being Rocket Kiwi 2, we will see. I suppose in the end it’s mainly a matter of style more than anything else.

Was hard not to think or work on game stuff last night before the jam’s official start. Downside of not having a theme like Ludum Dare does: The theme makes it impossible to even plan for the game before it happens, apart from the most basic things like “…well it’s probably going to be 2D”.

…dang, is where a lot of indie game talk and assets and stuff live these days. I should explore that more.

Oh, huh, apparently the JVM has a concurrent GC these days. I traditionally shun GC’ed languages for games after some unpleasant experiences with OCaml way back when, though Unity works well enough. But I actually have no practical experience or knowledge about how concurrent GC’s work in games. If you’re not making something CPU heavy, and it only stops the world for one thread at a time, could you just structure things to be shared across a handful of different threads such that each one has a fairly small working set at any given time?

Of course, the only language I would want use to write something that thread-y is Rust, and in Rust it’s a bit of a moot point ’cause you have no GC, but still. I should probably learn Clojure someday; immutable languages would work well with thread-y stuff too.

Oh, also, TIC-80 actually looks pretty cool. I looked at it once or twice and was like “okay that’s kinda too constrained to do the stuff I want, I wanna do NES style stuff at minimum, not Commodore 64”. But after another look I think it can work, even if the sprite space is a bit limited. Still looks fun, and it’s a whole toolkit so I can play around with art and music without it being miserably complicated. Still! That’s a plan for later.

Okay, well, I got some work done at least, but really didn’t get much progress done on the game jam. I have a very basic skeleton, but I’m too sleepy to really tackle the slight weirdness inherent in gluing an ECS together with input and drawing. I should probably just ditch the ECS, make a fixed game state with fixed sets of entities, and get on with life.

16/10/21 Saturday

Dang, I know a whole lot less about making games in Lua than I thought I did. I also know a moderate amount less about LÖVE than I used to; it’s evolved a bit in the last few years. Version 0.11.3 seeems quite good and universal though. I also have forgotten a lot of what I once knew about Lua, and spending a day or two playing with Fennel hasn’t re-taught me that much.

Well, I don’t think I’ve ever done a game jam that didn’t humble me, so this is probably a good thing.

It’s a pretty wild thing though, how much Lua gets done with strings just being immutable and interned by default. They’re a lot more like Lisp symbols, and Lua uses them as such, and Fennel does more. Fennel has a lot of nice syntactic sugar as well, while still being like, viciously simple in many ways.

Also, Lisp is actually pretty punctuation light compared to most other programming languages. Stop laughing, I’m serious. You really don’t need a lot of the commas, colons, semicolons, and other assorted fru-fru that ALGOL-descended languages tend to collect, mainly because function calls written (foo bar bop) are way easier to parse than foo(bar, bop).

Lua’s stdlib is minimal to the point of anemia. I sympathize, but seriously, there’s no way to concatenate two lists without a for loop. The lume library is pretty necessary.

It’s funny how you get used to things. I should have set up my basic style of game template that I usually use in Rust: whatever math necessary to make coordinates unitless/resolution-independent, timing all in seconds rather than frames, etc. For a game jam that doesn’t really matter I guess, but it irks me. In Rust with ggez and in C# with Unity I basically have all this stuff already, so it didn’t occur to me. It’s easy! Sure! No sweat. But an irritating distraction during a jam. Been a while since I did one of these, can you tell?

Well, after two hours I have a square I can move around, some rockets I can shoot, and they trail particles after them as rocket exhaust. Though upon consideration I probably don’t want to have your actual bullets do that, part of the thing of a bullet hell is that you gotta be able to distinguish enemy bullets from the background and your own shots without effort. So time for a break; next up I need to remove things that go off the screen, add some screen boundaries for the player, maybe make some sprites, make some things to shoot, and do collision. EZPZ. I’m probably going to stick with the monochrome look; I have long been impressed by how much Hero Core does with it.

Current soundtrack: Endless Space 2 OST.

…okay, that Fennel game template is totally worth it ’cause it has some scripts to generate AppImage files for Linux. They’re a little jank, and took some modification, but do work. And apparently Love2D has a webassembly build now, which actually works pretty well, and is awesome. Amazing what happens to a thing when you stop paying attention to it for like four years. And the game template has a build script for that, too. Windows builds are… a bit less working right now, and I don’t care about Mac builds and can’t test them anyway so I’m just gonna take that shit out.

17/10/21 Sunday

Wow, fuck today. I didn’t do jack.

18/10/21 Monday

Well I made some sprites for the game jam, that’s a good start. Bought aseprite to do it. It’s still open source but buying it gets you pre made binaries, you are just not allowed to distribute pre made binaries yourself. I spent half an hour working on compiling it myself and had weird issues getting skia to link properly, so I just shrugged and shelled out the $20. I have the luxury of doing so, unlike in undergrad; I will happily pay someone else to solve all my bullshit C++ linker problems if the opportunity exists. And IMO aseprite is totally worth the $20, so. No regrets.

Today was a bit shit. I’ve been wondering if bumping up my antidepressant prescription last week has been to blame for me being pretty blah and very sleepy. Though I guess I was like that before, too. So, I dunno. Gotta give it time.

19/10/21 Tuesday

Hmm, so there’s like 5 days left in the game jam. Goodness it goes fast. Ten days is too long for a game jam, it’s long enough that I can procrastinate. And I can’t get it all done in one single high-energy swing before inevitably swinging back to the depressed side of things. I have basic collision, motion and stuff, what do I actually need left? Roughly in order of priority:

  • Enemy behaviors – move along interesting paths, fire bullets, do stuff, etc. Includes creating a few different types of interesting enemies.
  • Level behaviors – spawn enemies, bosses, etc
  • Bullet patterns – at least a few simple ones.
  • At least one actual level
  • Background screen
  • Transitions
  • Basic title screen, game over and other game states and such. Win and loss conditions.

I still find it a little weird that Clojure has become a very successful Lisp, and its descendants like Fennel too, by abandoning bits of the Lisp Ideal. I keep having to write Actual Syntax in Fennel and it keeps making things better! Heresy! I keep writing [] and {} and everywhere and it’s like Lisp but not!

Wisdom from technomancy, the developer of Fennel: “seriously though, the Lisp Ideal is about writing code using the same notation as you use for data structures. So for Fennel, using [] and {} is actually more lispy. Focusing on cons cells is short-sighted and misses the forest for the trees.”

And I AM very impressed by Fennel, in general. Lua feels very close to a Lisp in spirit: dynamically typed with orthogonal data structures, first class functions, lots of dynamic metaprogramming and first class symbols (as Lua strings are all interned and immutable). Fennel does a very good job of taking that and adding a lot of the convenience of Lisp-y things, cleaning up a few of Lua’s warts with 21st century conveniences, and still being palpably Lua-ish. It’s really wild how well it works.

Man, I wish I remembered how to use Milkytracker. It’d be cool to make a few simple tracks for this game, even if they sucked. But [REDACTED] laughed at me when I told her I was interested in doing more with music, and I haven’t touched it since. Don’t be like me, kids. And don’t be like her. Since now isn’t a great time to try to put in even more work to try to re-learn how to use it, I guess I’ll just dig through royalty free music instead. The Anttis Instrumental collection should have something good in it, right? Right. Songs I’ve hit in it that I like:

  • “10 19” is actually really good.
  • “5 am in Asia” is also pretty deece, peppy and jazzy
  • “Synthesize Me”, pretty good soothing level music
  • “Superheroes are dead”

20/10/21 Wednesday

Oh right, now I remember why I drink. It’s because I hate everything.

21/10/21 Thursday

…Okay, I think it’s time to step up the priority on self-care a little. Yesterday was Bad. $PARTNER is a sweetie and I don’t deserve him. Exercise really needs to get pushed up the priority list. And food, a little bit. If those get solved then I think sleep will get better. But this alcohol shit is kinda unacceptable. I have considered that feeling so crap is a side effect of stepping up my antidepressants, but it’s been a short enough period that I dunno if I can conclude much about that yet. I was pretty miserable before doing that, after all.

3 days left in game jam. Zuh. Can I actually do it? Maybe. Let’s not worry too hard about that right now. Just survive until beach week, then take that time to recharge and reconfigure a bit and see how it feels. No caffeine, exercise every morning, see what happens.

Okay today was okay. Not sure whether it’s stabilization or just the rebound that often happens after a Rage Spiral, but either way. I need to not work from home; that’s a major contributing factor to feeling like shit.

22/10/21 Friday

Well this morning I felt like shit, but talking to friends online (you know, when I should be working) really helped a lot. Having good people in your life matters.

Oh heck, dto on the #lispgames IRC channel is making really sweet little shmup/bullet-hell game. It’s actually real inspiring ’cause it’s very simple but also looks really good. Makes it feel like the barrier to entry for my own shmup is lower, so I’m a little inspired to work on it again now.

…man, the lume Lua library is so good. It just has everything you need and nothing you don’t. Stuff like “find the angle from this point to that point, then turn that angle into a scaled vector”. You know, which is always what you do when you need to have one thing aim at another. In lume it’s two function calls, when you have a “pure vector math lib” it’s usually the whole tedious (x2 - x1).scale(1/length) * target_length or something.

Current music: Tyrian OST

23/10/21 Saturday

It’s beach week, my d00ds!

Drive was easy. Route was easy. Weather was easy. Fall leaves were beautiful. Good omen maybe? We’ll see.

Ok, so what’s my plan this week? Tomorrow the Lisp Game Jam is over at midnight, so I just wanna try to get as much finished on that as I can first. And the rest of the week I’m just gonna focus on self care.

…And that’s about it! Keep it simple.

24/10/21 Sunday

Okay, so it’s absolutely beautiful, I’m sitting in The Quiet Nerd Room with all my friends, and life is good. Let’s finish Rocket Kiwi 2. (…and I think giving up caffeine will happen tomorrow.)

So, what is the absolute minimum I need to do to finish Rocket Kiwi?

  • Collision detection
  • Enemy paths
  • Make enemies fire
  • Make background scroll
  • Make enemy bullets visible

Okay, I got collision detection and enemy firing and drawing done. But… Eventually I just looked at my editor, then looked at the beach outside, then looked at my editor, then and asked myself “why did I give myself a job for my first day of vacation?” And I couldn’t come up with a good answer. So I went and hung out on the beach, then in the pool, then showered, then napped for two hours, and decided I was pretty convinced.

So, I could get the thing technically complete in time for the game jam, it a) wouldn’t be that good, and b) I should probably try to actually be nice to myself once in a while.

I do intend to continue making the game. It’s pretty fun, but it’s also gotten to the point where it needs some refactoring and that ain’t gonna happen under time pressure. Fennel and LOVE is a good tech stack but I’m definitely starting to Feel It with the lack of static typing, and I need to clean things up and make them more consistent and regular to help with that. Also I really miss having a real ECS and might have to either put the work into bending tiny-ecs to my whim, or give myself a bit more ECS machinery myself. Having to call “update position” on like four different lists of objects is getting old.

So yeah, I think the game could be pretty good while staying small, and if I work on it a couple hours a day this week I’ll be pretty happy with it. Definitely want to do the Spring game jam.