2025-10-09
TL;DR: I finished the game I started in part one. You can play it online here or compile and play locally with the code here. I don’t have a lot of time for writing this week, so I’m going to give a brief brain dump instead of my usual level of detail, which I suppose is better than nothing at all.
I changed up the architecture of the code after just kind of taking a
guess at what might work during the first week. It was important to me
that the rendering and game state logic be separate, and ideally that
would mean they’d live in separate files. My naive first approach was to
try to put an impl
for a struct
in a sibling
file, but this doesn’t work because of Rust’s item privacy rules. After
some reading, it seems this is only possible if an item is defined in a
module and the impl
s are elsewhere in the same module. I
guess this makes sense because otherwise it would be possible to add
functionality to struct
s that are otherwise private. I
still don’t fully understand this behavior, but I was able to create a
game
module that defines all of its structures and other
items in mod.rs
and extends them with more functionality in
files within that module.
Sound was a little challenging to get working on NixOS. On Linux
generally, enabling the audio
feature in
macroquad
causes it to link against
libasound2
, and in a typical distribution it would be
sufficient to install the development package for that library so the
linker can find it. On NixOS, this is normally solvable by adding the
package to the development shell and making sure its path is in
LD_LIBRARY_PATH
. But, as I learned, this is only really
relevant for runtime dylib loading, and Rust’s linker needs
extra help to find certain libraries at link time. (As above, I
don’t understand this fully.) It turns out that you can pass the path in
RUSTFLAGS
, which is easy enough to do in shell.nix
.
I was especially happy to get sound working because I think the sound effects in Pinwheel completely change the character of the game. It’s the first or second thing that people have mentioned when playing the game for the first time, and it adds a silliness that I enjoy. I made all the sounds myself and recorded them into Audacity with my cheap desk microphone. This was mildly embarrassing but also kind of fun. I’ll have to remember the power of sound when I build more games in the future.
macroquad
performed beautifully throughout this project,
and one example is its effortless WASM deployment. Just installing the
appropriate toolchain and running a slightly altered build command is
all that’s required. The option to play in a browser makes it really
easy to show people the game and let them try it out if they want to. I
was able to add some logic to maintain aspect ratio in most situations,
which simplified the canvas CSS a bit, so with three static files I can
deploy the game online. If you’re on macOS or iOS, you may have noticed
that the web version doesn’t fill the viewport or even run at all. This
is a disappointing and confusing issue that I haven’t resolved yet, but
it’s not that important to me at the moment. Maybe I’ll address it in
future game projects. I don’t see any reason why WASM should be a
problem on these platforms with the right configuration. I just have to
figure out what that configuration is.
I built a few functions of general usefulness during this project,
and by chance I watched this video about
building a personal library of components for accelerated game
development. This has led me to the realization that I should be
building a crate that’s essentially an extension of
macroquad
that I can grow over time. Utility functions can
live there, but more than that I can add implementations of various
parts that together approximate a true game engine. Collision, asset
loading and management, rendering and lighting tools, pathfinding,
opponent AI, and so on. As I encounter new problems and solve them, the
solutions can get merged “upstream” so I have them next time. Since
nobody else will use this crate, I can make decisions based solely on my
own whims.
This was a lot of fun, and I’ll definitely try to do some more gamedev over the winter.