Lua is not my favorite for game dev January 20, 2024 on Kenneth Dodrill's blog

This is mostly a postmortem for my previous two games that I made, politician simulator and ghost simulator.

For both of these, I chose love2d for my game library. politician simulator was done very quickly (in 3 days or so), and I wrote the code quite poorly. I mostly just wanted to make a funny game, and didn’t feel the need to write the code well. It quickly became very messy and towards the end I really didn’t like coding the game. Lua got in the way.

Basic problems like dynamic typing aside, for programmers used to writing OOP you will sorely miss pretty much everything. There are no classes in lua, which can be a good thing, but there are also no other ways to make a similar structured object. Sure, you can use a table and type-hint with comments. This is mostly what you would do in something like older PHP versions. Easy, right? Well…it’s not so simple. It is basically the equivalent to using an array in PHP, typing hinting with comments, and hoping for the best. PHP has classes and is OOP. C (not C++) has structs and no classes (which is arguably cleaner).

To make a “class” in lua would mean either one of two things: download a library to use that has hacked in some kind of pseudo-class, or make a new file with a global table. Uh-oh. This is kind of where my problems start. Globals are default in lua. I would normally consider this a mistake, but lua is a dynamically typed scripting language. I don’t believe it should be used for game development or similar things. Lua also has no continue statement. How are you not going to have a continue statement? No, really. This may seem simple, and…I suppose it is. But come on.

Lua also doesn’t have many helper functions for tables. Want to see if a table is empty? Use the globally-defined next function to see if it will return a value. Oh, but that’s not good enough. Assign next to a variable in order for things to run faster. For a language that is so focused on tables and functions, there should be some more helper functions for them. I would often look up “how to do X in lua” just to find an answer that was basically “make 2-3 functions and combine them”. I understand that they are attempting to be the C of dynamically typed scripting languages. In C, you often make your own functions for many simple things. However, when I want to use a language that makes it fast to program and do things easily… I kind of want a bigger standard library.

Interestingly, love2d also lacks some quality-of-life functions, mostly for input. The library is mostly solid, but I found input handling to be a pain. I wanted to be able to check input in different files to separate my code out. For example, if someone is typing on their keyboard I want to know. There isn’t a function in love2d for this, except to check if specific keys are pressed. I suppose I could check if any key is pressed by building a table of all keys I could think of… but this seems illogical and prone to errors. Instead, I ended up making a timer that is reset each time the user types anything, along with a (global) boolean to see if my scene had just loaded (don’t want them to fail the scene right away).

My last story is one of global variables. I had a file called work.lua, which is a scene in ghost simulator. In this file I had a “class” defined Work = {}. I have a state manager set up in there with Work.setState(state). I copied this code to a new scene file, drink.lua. I was not requireing the work.lua file in drink.lua, but was requiring both in sceneManager.lua which handles switching scenes. My code editor, neovim, uses LSP and the typical lua LSP in order to tell me if something is weird/wrong. Because Work = {} is global, because Drink = {} is global, and because my Drink.setState(state) function had some Work.setState(...) code in it (remember I copied the code), I spent a good 30 minutes trying to figure out why a particular sprite was not changing frames but the state was still getting set.

Overall, I found lua frustrating to use for game development. I do like love2d. Perhaps I will try and use it again at some point, or maybe I’m missing some key feature of lua. Or, perhaps I am doing this all wrong (feel free to let me know by email). But, for now, I’m looking into sokol because I can use C (not C++) and still write a game that runs in the browser (and likely will be smaller than using love.js. plus, that’s one less npm package installed on my computer).