Categories
guides

How To: Debug Info Overlay in GMS

During the course of creating your game, you will inevitably run into situations where you would like to know the status of some objects or variables while the game is running. Is your frog jumping but behaving like it’s crouching? Or maybe you need to fine-tune your controls, watching your variables containing speed/velocity in action.

Displaying data on the game screen can be an invaluable tool. So let’s build something that’s simple to use. It should be able to be used by any object running in your game, and be reusable in other projects. Let’s get started

Start by creating a new object. obj_debugdisplay


Object: obj_debugdisplay

This is going to be the object that holds all the debug string data, and displays it to the GUI layer. If you’re using this across multiple rooms, don’t forget to hit the Persistent button!

Create

Let’s set our variables for the debug tool. First initialize an array that’ll hold the text. then pick your font, and let’s set some pixel offsets for the display.

debugtext[0] = "";
debug_font = fnt_debug;
y_offset = 5;
x_offset = 5;

Step

Each step of the game we need to clear out the text array. All our objects will write to this array, it will display the data, and then clear again. Otherwise we’d have data scrolling all over the screen.

debugtext = 0;

Draw GUI

This is going to do the bulk of work. First let’s set the font and get length of the array. (how many lines of text there will be)

draw_set_font(debug_font);
var a = array_length_1d(debugtext) //get length of array

Now that we’ve got our data set, we need to figure out how big everything is going to be. The easy bit will be the height of each line, we can just use the GML function string_height and store it into the local variable hh.

var hh = string_height("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

To get the width we can use the function string_width, but we need the longest value from each line in the array. For loops to the rescue! Let’s store this in local variable ww.

var ww = 0
for (var e=0; e<a; e++) {
     if (ww < string_width(debugtext[e])) ww = string_width(debugtext[e]);
}

Now let’s get a little fancy and put a block of color behind or text to make it easier to read.

draw_set_color(c_red);
draw_set_alpha(0.6);
draw_rectangle(0,0,(x_offset*2)+ww,(y_offset*2)+(hh*a),false);

And finally, let’s loop through the array and draw the text to the screen. Include the offset variables from the Create script. Just in case you want to move some stuff around later.

draw_set_color(c_white);
draw_set_alpha(1);
for (var i=0; i<a; i++) {
     draw_text(x_offset,y_offset + (hh*i),debugtext[i]);
}

Now that we’ve got our display object, we need to get it in the project. I’m a fan of using “controller” or “game controller” objects in games to organize this stuff. It can handle game states, initializing global variables, and creating objects you’ll need throughout the game.

if (!instance_exists(obj_debugdisplay)) {
     instance_create_layer(x,y,"Instances",obj_debugdisplay)
};

Script: scr_debugdisplay()

Now we just need a quick way for our objects to interact with our new object. A quick script, with the string input as an argument, will do the trick.

So whenever you need an object to display the value of any of it’s variables, just call the script with: scr_debugdisplay(“my value string”);

var text = argument0;
var a = array_length_1d(obj_debugtext.debugtext);
obj_debugtext.debugtext[a] = text;

Here’s the full Draw GUI event.

draw_set_font(debug_font); //set your font
var a = array_length_1d(debugtext) //get length of array

//GET STRING HEIGHT
var hh = string_height("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

//GET STRING MAX WIDTH
var ww = 0
for (var e=0; e<a; e++) {
     if (ww < string_width(debugtext[e])) ww = string_width(debugtext[e]);
}

//DRAW BOX BEHIND
draw_set_color(c_red);
draw_set_alpha(0.6);
draw_rectangle(0,0,(x_offset*2)+ww,(y_offset*2)+(hh*a),false);

//DRAW DEBUG TEXT
draw_set_color(c_white);
draw_set_alpha(1);
for (var i=0; i<a; i++) {
     draw_text(x_offset,y_offset + (hh*i),debugtext[i]);
}

And that does it. Since the array is getting cleaned out every frame, it’ll never grow too big. This will allow for multiple instances of objects to come and go in your display.

One thing to remember, is the debug text array will consistently be written to based on the order of instances in your room. Whether this is from the Instance Creation Order in the room, or from another controller object creating everything.

By Rob Nichols

Rob Nichols is an IT professional with years of experience creating games in GameMaker Studio, creating electronic music, and producing the weekly VGM podcast Rhythm and Pixels.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s