Better Logging in GameMaker Studio 2

Author: Brent Taylor, Date: 30 Nov 2021, Tags: #Game-Maker-Studio

Logging is fundamental to development in every industry I can personally think of. It’s also something we spend so very little effort to keep clean and easy to use. How often have we written code like this?

function log(msg) {
    show_debug_message(string(current_hour) + ":" + string(current_minute) + ":"
      + string(current_second) + " - " + string(msg));
}

When called to give information on a variable, it looks something like this:

log("Var with error equals: " + some_var)

A line is printed to the console like this: “20:51:52 - Var with error equals: 298”

This isn’t too bad as these are small examples, but anyone who’s been doing development for at least a year or two will have horror stories of huge blocks of completely unreadable and unmaintainable string concatenation. You’ll especially see newer developers do this, but developers of all skill levels are susceptible to being lazy, especially me.

Other languages, such as Python, have much better ways of handling situations like this in a much more readable way. With the introduction of structs in GameMaker Studio 2.3, we can absolutely replicate that.

Let’s look at how we might want string concatenation or substitution to look like in GameMaker Studio.

var my_text = f("Hello {subject}!", {subject: "world"});

This should produce: “Hello world!”

In my opinion, this is much better. It’s a sort of an in-between of Python’s string.fmt method and Python’s f strings. Let’s see what our logging function might look like with this new approach.

function log(msg) {
    var log_text = f("{hour}:{minute}:{second} - {log_message}",
        {
            hour: current_hour,
            minute: current_minute,
            second: current_second,
            log_message: msg
        }
    );

    show_debug_message(log_text);
}

This is much longer, but it’s also significantly easier to read and maintain.

So what does our f function look like?

function f(msg, data_pairs = noone) { // concatenation isn't always desired
                                      // so set `data_pairs` to `noone` by default
    // If `data_pairs` isn't provided, it's just a string so we can just return it
    if (data_pairs == noone) return string(msg);
    // If `data_pairs` isn't a struct, then we need to error out
    if (!is_struct(data_pairs)) throw "ValueError";

    // We don't want to modify the original string we passed in, so let's copy it
    var build_string = string_copy(msg, 1, string_length(msg));
    var keys = variable_struct_get_names(data_pairs); // Grab all the keys in data_pairs

    // Now we loop over each key to build our substitution tokens
    for (var index=0; index < array_length(keys); index++) {
        var key = keys[index]; // Grab the key
        var token = "{" + string(key) + "}"; // Build our substitution token

        // And lastly, we want to replace every instance of our token with the data
        // provided in the struct
        build_string = string_replace_all(build_string, token,
            string(variable_struct_get(data_pairs, key)) // Don't forget to cast the data
                                                         // to a string
        );
    }

    return build_string; // And return it!
}

I chose to call this function f simply to leverage the habits I’ve already formed while working with Python. If the single letter function name bothers you, I would suggest renaming it string_create to stay in line with current naming conventions in GMS.

This approach is slower, but it’s easier to use, easier to read and significantly easier to maintain. Consider that in most cases in which you’re piping text out to your console or to a file stream, speed isn’t a major concern. I think the tradeoff is worth it.

If you find this useful, consider the code to be under the public domain. Use it in your own projects as you see fit. Enjoy!


Unity State Machines and Movement?

Author: , Date: 03 Apr 2021, Tags: #Unity #Bolt

We’ve all seen that first tutorial that gets you started with a character moving across the screen. For a lot of people, it’s the first tutorial they follow and it’s what gets them hooked on game development. That thrill of creating something and being able to interact with it. It can be intoxicating. I believe the first tutorial of that type I followed was in an old book called, “Beginning DirectX 9” by Wendy Jones. I think it had me moving an animated lion across the screen, wrapping around at the edges. I was in my first year of college at the time and it blew my mind. I’d only been programming for a couple of weeks and this felt like magic.

However, even at the time, I realized I had a problem. If I held down both the left and right movement buttons at the same time, that little character would simply stop in place. I knew it was an issue, but I had no idea how to solve it. I figured I’d eventually figure out how to solve it, surely the book would teach me? It didn’t. In 2004, there weren’t nearly as many resources on game development that were freely available. It wasn’t for another year, while studying game AI, that I first ran into the topic known as “Finite State Machines.” I eventually stumbled into the idea that FSM’s might be useful outside of game AI. That was a big epiphany moment for me. I quickly realized I was using FSM’s all over the place, they just weren’t formal and obvious state machines. It’s one of those, “Aha!”, moments we all get when really trying to learn and master a discipline. Plenty more followed.

Of course, character movement is a series of states. Different input, such as pressing the left or right button, triggers transitions between those states. I had my solution! Finally!

It’s been almost two decades since I’ve followed that tutorial. When transitioning into education, teaching game development, I have been watching all sorts of tutorials from oh so many amazing creators, to see just how people are learning game development these days. There are so many tutorials for beginners, but there’s not a lot out there teaching the intermediate stuff. There’s very few tutorials out there teaching concepts like state machines, and even fewer teaching how to apply them in practice.

You have no idea how much I’m looking forward to contributing to the learning ecosystem! I hope this tutorial helps those who are just now walking the path I did, twenty years ago.

  • Project Files - You can find the Unity project to follow along with the video here.