Thinking About (Programming) Languages for a Side Project
It has been about 10 years since I stopped working on my procedural landscape generation side project. I’ve wanted to pick some of the the ideas from that project for a while now, but never really had anything which felt that concrete starting point. That is, until I watched at talk called “How to make a Roguelike”, and read the accompanying article. It got me kind of fired up. I don’t think I ultimately want to build is a roguelike, per se. But I would like to play with procedural generation again. To start with I’d like to build a few toys, portions of which will hopefully be useful later.
So: I started thinking about programming language choices. I landed on Java last time around, largely because it was what I knew (if I’m being honest). These days I find Java extremely clunky to work with. The JVM is also a fairly heavy chunk of of tech with a highly suboptimal garbage collector (for the purposes of game programming). I really felt like there were probably better options out there. In the first instance: languages more suitable for the problem. In the second: languages I’m less familiar with which give me the chance to learn new things.
I’m interested in three deployment targets, in this order of importance:
- Desktop computer (specifically macOS), because that’s where I’ll be building it;
- Tablet (specifically iPad), because I find the form factor and mobility appealing for games;
- Web, because it makes for a simple and fast deployment target for feedback and discussion. Previously I used inline screenshots for demonstration, but inline interactive graphics would be way cooler.
At a higher level, I’d also like the language to have these features (in no particular order):
- Language level immutability (bonus points for value types);
- Strong, static typing;
- Non-nullability by default;
- Memory safety;
- Algebraic datatypes, specifically discriminated unions, and pattern matching;
- Composition over inheritance as a design goal.
Again in no particular order, here are the options I rejected:
- Java: Clunky. Verbose. Slow garbage collector;
- Python: Slow. Very much not statically typed. Doesn’t even have
switch
, let alone pattern matching. Anything but anything can beNone
; - C++: Very painful to work with. Static, but not strong, typing. Safer modern constructs have to work around all of the old cruft;
- C#: A little too close to Java. Unity is the reason to use it, but Unity seems to bring pain as much as anything else;
- JavaScript: The obvious answer to the web deployment target, essentially all of the same problems as C++. The better modern stuff need to deal with underlying problems of the previous horrible decisions. Plus: even the modern versions lack most of the features I’m looking for;
- TypeScript: A genuinely solid type system slapped on top of JavaScript. Adds many of the features I want but it’s still JavaScript;
- Dart: A sort of replacement for JavaScript which adds some (but not all) of the features I’m looking for (and has some form for building procedural games). But: lacks the algebraic types and non-nullability. Plus: might die if Google gets bored of it;
- GameMaker Language (GML): I’d be remiss if I didn’t mention this, given that GameMaker Studio seems to be a great tool which many people love. But the language looks horrible. It doesn’t even have structs!
So. What does that leave me with?
Swift is one which I think could be a great fit for game programming. It uses automatic reference counting rather than traditional garbage collection, which has some performance benefits. It’s expressive and has basically all of the features I’m looking for. I’ve used it a little, and generally liked it. It doesn’t have a good story for web deployment, though. It also doesn’t have a working Windows toolchain, which means people mostly aren’t looking at it as game development option. The upshot of that is that existing game programming tools are think on the ground.
Rust might actually be an ideal language for high performance game programming. There’s a very comprehensive website dedicated to making this argument, in fact. It has all of the modern features I’m looking for right on the ground floor and can be compiled to WebAssembly. It has all of the speed advantages of C++ and (basically) none of the potential for memory related bugs. The down side is that the way it avoids those memory related bugs might make it really painful to work with.
Nim is (like Rust) a modern systems programming language with high level features. It’s garbage collected, but the garbage collector is fast. Its algebraic datatypes and pattern matching are not as strong as the other options here, but it does have them. By default everything is a value type in Nim. As a bonus it can be compiled natively or to JavaScript for web deployment. On the downside it’s structured using significant whitespace, one of my least favourite aspects of python.
ReasonML is an alternative syntax for OCaml. Like Nim it can be compiled either to a native binary or to JavaScript. The older I get the more static typing, immutability and lack of side effects seem like good ideas. If you’re thinking “that sounds like functional programming” you might be right. I’ve always found functional languages really hard to follow. I don’t seem to have the problem with ReasonML, though, which suggests my problem was actually the syntax, not the semantics.
If I was to try using Swift I’d be basically on my own. For the other three options there are some interesting tools I could make use of:
- Amethyst: A “data driven” game engine written in Rust. This looks really interesting. It’s an architectural approach I’m a big fan of. The downside is that it’s not even at v1, and I haven’t seen any inspiring example games made with it;
- Piston: A more mature, more traditional engine also written in Rust. Also not a v1, but seems to be further along;
- Godot: A game engine people are saying really nice things about. Plus it’s already at version 3. Implemented in C++, but with clean bindings for Nim and Rust. The binding API is pure C, so creating Swift or even ReasonML bindings would be possible;
- Reprocessing: Not a full engine, just a drawing API. A ReasonML implementation of the Processing 2D graphics methodology. Very clean and functional, plus has both native and JavaScript bindings ready to go.
The language I’m most drawn to is ReasonML, but it’s definitely the least practical. The idea of trying to write my own game engine and entity component system based on functional principles is very appealing. It’s also a big idea, and big ideas are rarely a good place to start.
The second biggest draw for me here is Amethyst and Rust, so the next step feels like going through through the Amethyst tutorials and getting a feel for the engine. I found this excellent YouTube series on building procedurally generated planets and I think a good toy project would be converting this to the technologies I’m interesting in working with. After trying this with Amethyst I’ll move on Godot and Piston (assuming I don’t either get bored of repeating myself or fall in love with one of the options along the way).