Gw Temp

Menu

Tutorial - 'Alternate Debug Script' by Kuro

An item about Gamemaker posted on

Blurb

Kruo doesn't dissapoint! This time it's a debugging script system for GameMaker.

Body

GM Tutorial: Alternate Debug Script by Kuro

Part I: Searching for Variables

Here's a quick little script I came up with to help debug your game when something unexpected happens. Its inspired by a forum topic over at the Game Maker Forums.(http://gamemaker.nl) Can't remember exactly what the topic was about, but I remember them discussing whether people use GM's default debugger. Personally, I've always thought it to be useful, but its not exactly pleasant to look at and managing the windows is annoying when in Fullscreen 640x480. So here's my alternate method to checking out object variables (as well as editing them).

// -- Script: system_search()
// -- Arguments: none

{
ask = "";
message_caption(true,"Variable Search");

for(i=0;i iid = instance_find(all,i);
ask += string(iid.name)+"("+string(iid.object_index)+")["+string(iid.id)+"]|";
}

ask += "global";
ask = show_menu_pos(window_client_left+window_width/2,window_client_top+window_height/2,ask,0);

if(ask != instance_number(all)){
with(instance_find(all,ask)){
ask = get_string("Search "+string(name),"foo");
if(variable_local_exists(ask)){
show_message("Local value "+ask+" = "+string(variable_local_get(ask)));
}else{
if(string_count("[",ask) > 0){
pos = string_pos("[",ask)+1;
ind = "";
while(string_char_at(ask,pos) != "]"){
ind += string_char_at(ask,pos); pos += 1;
}
show_message("Local array value "+ask+" = "+string(variable_local_array_get(ask,real(string_digits(ind)))));
}else{
show_message("Local value "+ask+" not found.");
}
}
}
}else{
ask = get_string("Search Global Values","foo");
if(variable_global_exists(ask)){
show_message("Global value of "+ask+" = "+string(variable_global_get(ask)));
}else{
if(string_count("[",ask) > 0){
pos = string_pos("[",ask)+1;
ind = "";
while(string_char_at(ask,pos) != "]"){
ind += string_char_at(ask,pos); pos += 1;
}
show_message("Global array value of "+ask+" = "+string(variable_global_array_get(ask,real(string_digits(ind)))));
}else{
show_message("Global value "+ask+" not found.");
}
}
}
}

The first several lines set up a popup menu that will contain all of the objects in the current room. Focusing on this line...

ask += string(iid.name)+"("+string(iid.object_index)+")["+string(iid.id)+"]|";

... each item in the popup menu will display the 'name' of the instance, the object_index (which will appear as a number), then in the brackets the instance id. I set it up like this because numbers aren't very descriptive of each object, and they have very little value to humans unless they're being applied to some math or statistic, hence the reason for the 'name' variable. Now if you're wondering where the 'name' variable comes from, read on.

There are a few drawbacks to Game Maker in respect to objects. The unique numbers used to store id's and indexes can't be reverted to words that have meaning to us. So to compensate for this, I add a variable named 'name' to the 'Create' events in each object I make. Unless I'm using a special script to spawn objects and set custom names, I use this piece of code to name my objects (in the Create event of the object):

name = "ObjectNameHere"+string(instance_number(ObjectNameHere)-1);

The rest of the code does all the real work for you. An input prompt will ask you to search the current object for any variables you may have set. Note that this code can only check local and global variables, as well as 1-dimensional arrays. If you need to check special values that are not a part of any object, but isn't a global either, like view_width[n], simply select any item except 'global' from the popup menu and input it like so:

window_width;
view_height[0];
any_variable_that_i_havent_said_yet[20];


Part II: Editing Variables

To edit variables is a simple matter of changing the code a bit.

// -- Script: system_edit()
// -- Arguments: none

{
ask = "";
message_caption(true,"Variable Edit");

for(i=0;i iid = instance_find(all,i);
ask += string(iid.name)+"("+string(iid.object_index)+")["+string(iid.id)+"]|";
}

ask += "global";
ask = show_menu_pos(window_client_left+window_width/2,window_client_top+window_height/2,ask,0);

if(ask != instance_number(all)){
with(instance_find(all,ask)){
ask = get_string("Search "+string(name),"foo");
if(variable_local_exists(ask)){
show_message("Local value "+name+"."+ask+" = "+string(variable_local_get(ask)));
if(is_real(variable_local_get(ask))){
edit = real(get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo"));
}else{
edit = get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo");
}
variable_local_set(ask,edit);
show_message("Local value "+name+"."+ask+" = "+string(variable_local_get(ask)));
}else{
if(string_count("[",ask) > 0){
pos = string_pos("[",ask)+1;
ind = "";
while(string_char_at(ask,pos) != "]"){
ind += string_char_at(ask,pos); pos += 1;
}
show_message("Local array value "+ask+" = "+string(variable_local_array_get(ask,real(string_digits(ind)))));
if(is_real(variable_local_array_get(name,real(string_digits(ind))))){
edit = real(get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo"));
}else{
edit = get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo");
}
variable_local_array_set(ask,real(string_digits(ind)),edit);
show_message("Local array value "+ask+" = "+string(variable_local_array_get(ask,real(string_digits(ind)))));
}else{
show_message("Local value "+ask+" not found.");
}
}
}
}else{
ask = get_string("Search Global Values","foo");
if(variable_global_exists(ask)){
show_message("Global value of "+ask+" = "+string(variable_global_get(ask)));
if(is_real(variable_global_get(ask))){
edit = real(get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo"));
}else{
edit = get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo");
}
variable_global_set(ask,edit);
show_message("Global value of "+ask+" = "+string(variable_global_get(ask)));
}else{
if(string_count("[",ask) > 0){
pos = string_pos("[",ask)+1;
ind = "";
while(string_char_at(ask,pos) != "]"){
ind += string_char_at(ask,pos); pos += 1;
}
show_message("Global array value of "+ask+" = "+string(variable_global_array_get(ask,real(string_digits(ind)))));
if(is_real(variable_global_array_get(ask,real(string_digits(ind))))){
edit = real(get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo"));
}else{
edit = get_string("Change value of "+string(name)+"."+string(ask)+" to:","foo");
}
variable_global_array_set(ask,real(string_digits(ind)),edit);
show_message("Global array value of "+ask+" = "+string(variable_global_array_get(ask,real(string_digits(ind)))));
}else{
show_message("Global value "+ask+" not found.");
}
}
}
}

This modified version of the first script will first show you the value of the current variable you search for, then prompt you to change the value, and then show you the modified value. Not much to say about that, but you most likely won't use this script as much, if at all.

The last thing I'd like to note should be common knowledge to anyone using Game Maker. I figure it should be worth mentioning that true and false have values of non-zero and zero, respectfully. False will always show up as '0', but true (at least in most programming languages) is non-zero and will normally show up as '1' in variable searches.

That's all for this tutorial. If you want to see a working example of this tutorial, you can download my GM5 file here. Any and all questions/comments can be directed to krealm2k@yahoo.com. Thanks for reading.


Kuro