069 - Bliss

May 31, 2020


It was only three months ago that I wrote about the struggles of going a few weeks without deploying while working through a major refactor.

I'm in a much different boat today.

I'm making visual progress every week and will sometimes just sit at my desk smiling with joy for a few moments as I appreciate the fun journey that is working on a large project alone.

I'm feeling happy about the foundation that I'm building on.

It feels great whenever I get to add another layer on top of groundwork that might have been put in place months or years ago.

I feel like the pieces of the puzzle are coming together slowly but surely.

Of course nothing gold can stay and there will be more times in the months and years to come when we have to sift through the weeds for a while.

For now, though, I'm enjoying this feeling of bliss while it's here to be appreciated.

User Interface Iteration

Coming into the week I knew that I needed to do some user interface work - which has historically been a less streamlined part of the engine.

The approach to writing tests and implementation code for interfaces has generally stabalized, but prior to this week crossing the last mile of trying to make things look decent was tedious.

So I kicked off the week by using the first three days to write some tooling to make it easier to more rapidly iterate on the game's look and feel.

Back in early April I started learning Apple's Metal Graphics API and making light touches on Akigi's renderer-metal crate, the renderer backend that will one day power an Akigi MacOS application.

This week I dove in and added just enough to the Metal renderer in order to support displaying textured quads.

I then made a single function that renders the game to a PNG file using that renderer-metal behind our generic Renderer trait.

This gave me the power to visualize the game world using a single function call after initializing the world with whatever data I wanted to see.

/// Verify that the first response is rendered above the second response
fn response_1_above_response_2() {
    let mut world = create_test_world();
    set_main_action_conversing(&mut world);

    let responses = unsafe_text_sections_containing_text(&world, "Response");

    assert!(responses[0].screen_position.1 < responses[1].screen_position.1);

    // Add this line to the bottom of any test case

The output of that call looks like this:

Intentionally panicking to ensure that we never accidentally leave this in a test function.

View rendered game world:
open /Users/chinedufn/Development/akigi/game-client/game-app/test-world-renders/scratchpad.png

thread 'systems::user_interface_system::dialogue_overlay::tests::pushes_dialogue_overlay_when_in_dialogue' panicked at '
Intentionally panicking to ensure that we never accidentally leave this in a test function.

I then added a test utility that can deserialize any value that implements DeserializeOwned from a file, allowing me to tweak user interface margins and paddings and sizes without needing to recompile.

At the end I had a system that, while not perfect, was a big step up from my previous process of needing to refresh the web browser and click until I got to the desired game state.

Now whenever I have the values-from-file feature enabled and I edit the values.yml file a watcher process regenerates a PNG file with the new values.

I have to click on the MacOS Preview app for it to refresh to the new image. In the future I might just programatically open a window and copy the bytes over or something. My Metal graphics API renderer only supports the user interface right now - but in the future I'll render meshes which should be useful for easily creating and visualizing any scene.

The ability to read values from disk is behind a feature flag so that I don't accidentally deploy that to production. In production we seek to distribute each of our applications (game-server, web-client, etc) as single binaries in order to keep our distribution process as simple as we can.

In the future I may experiment with rendering a few times at different screen sizes and then compositing that together into a final image (or perhaps a window if I ever need to be able to animate through some world states)


Got a first pass of the inventory into the game. Needs polish, as with many things, but it generally works.

Got to test drive the new tooling around visualizing user interfaces while working on this so that was enjoyable.

We'll need to circle back and add polish, but an inventory interface is now in the game.


Rigify cat rig On tuesday I finished modeling the cat and got the rigify rig in place. Loving rigify so far. In the back of my mind is at some point using some morning practice sessions to try to re-create a rigify rig on my own from scratch in order to learn more about how to create good rigs controls.

Other Progress

  • Some refactoring of the distributed-npc-client as a foundation for better testing now that I better understand the direction of the crate.

  • Fixed some issues with exporting data from Blender files that had linked to data in other files. This took me a few hours to figure out but it's working now.

Next Week

Right now there isn't that much to do in the game - but I'm feeling good about flipping that equation over this next month.

I want June to be the month that people start to play the game for fun, not just to try it out.

This means that I'll need to spend a fair bit of time adding in more gameplay.

By the end of June I'd like to have a first paying subscriber for the game.

The gap between that and where we're at now is enormous. So we'll take it one week at a time.

Cya next time!