GameMaker Custom tools you've made for projects (Discussion)

Evanski

Raccoon Lord
Forum Staff
Moderator
Hey!, I've been trying to create a ultimate template (game engine?) whatever you want to call it, so making projects becomes easier.
I've been really into this idea as well, especially after watching this GDC video

So I started this discussion to just have a place for people to share and discuss tools they've made for there projects, big or small, simple or complex, all are welcome!

To Start off I only have two things so far but I plan to make more.

I have my Debug console
you check that out/ download it HERE

and a function I wrote to place at the end of Draw events to just reset all the variables back to default so not everything is drawing upside down in the color red... only the name of my player is
GML:
/// @function draw_set_default
/// @description Sets all Draw options to there default states.

draw_set_alpha(1);
draw_set_circle_precision(24);
draw_set_color(c_black);
draw_set_font(-1);
draw_set_halign(fa_left);
draw_set_lighting(false);
draw_set_valign(fa_top);
Feel free to use it

But im more interested in your tools and to inspire me to make some more for my own use.
Tell me why you made it and how you went about doing it.

For me I typically have a problem or a repetitive code I write, so I find a way to automate it or make it easier.
 

Ches Rowe

Member
Cool debug console! I also created a debugging system for my game Augury. I needed an easier way to watch and edit variable values so I created a debug window that I could use to edit any instance inside my game while i'm play testing. It uses surfaces and the variable_instance_get/set functions!

&feature=youtu.be
 

Kezarus

Endless Game Maker
I am making a Framework to handle all sort of shenanigans I am doing. Be it UI, sound manager, particles playground, language support, rebindable keys, you name it! There is a lot of things there and the good people of the community are helping out and being credit for it too.

The main purpose is to ease the production of my new games. And, since I was going to make all from scratch and use it, why not distribute it for free too?

There you have it, Monastery Framework. =]
 
There is currently about a 30% chance that I will program my own level editor to use for my current project. I want to make one that specialized in making segments of levels for procedurally generated content. I would like to make it seamlessly compatible with my terrain generation asset, so it can save and load maps using the same functions. It would probably save a lot of time, but I'm uncertain about the commitment of making it in the first place.

The way I envision it working is having the ability to create various layers, then define randomization rules, and other procedural methods, for those layers. You would export the full map with every layer, then use a function at run-time to generate a subset of the room, only including certain layers. You could assign particular functions to apply to certain layers. For instance, you create a layer for the walls, then write code on the side that says: replace 25% of the walls on this layer with cracked walls. Or you make two layers and tell the output to chose to use only one of the two for the final subset.
 

ceaselessly

Member
I have a few scripts I use in most projects. Nothing too fancy, but handy little utilities to have:

gamepad_any_button():
GML:
// gamepad_any_button();

// cycle through every button on gamepad and check for input
// if button pressed, return which one. if no button pressed, return false.
for (var i = gp_face1; i < gp_axisrv; i++) {
    if (gamepad_button_check(0, i)) return i;
}
return false
--

draw_set_text(font, halign, valign, color):
GML:
///@desc draw_set_text(font, halign, valign, color)

/// @arg font
/// @arg halign
/// @arg valign
/// @arg color

draw_set_font(argument0);
draw_set_halign(argument1);
draw_set_valign(argument2);
draw_set_color(argument3);
--

sound_crossfade(sound1, sound2, level1, level2, time):
GML:
/// @param sound_crossfade(sound1, sound2, level1, level2, time)
/// @arg sound1
/// @arg sound2
/// @arg level
/// @arg level new song should reach
/// @arg time (milliseconds)

/// note: sound1 must already be playing

var _sound1 = argument0;
var _sound2 = argument1;
var _level1 = argument2;
var _level2 = argument3;
var _time = argument4;

// fade out sound1
audio_sound_gain(_sound1, _level1, _time);

// fade in sound2
sound_play(_sound2); // start sound2
audio_sound_gain(_sound2, 0, 0); // start sound2 at 0
audio_sound_gain(_sound2, _level2, _time);
--

I'm not much of a programmer, so forgive me if these are pedestrian, but I find them useful.

I also tend to write scripts that draw menus for me, once I have an idea of what the menus will generally look like across the whole game. I won't share those, as they are project specific, but writing a draw_menu script based on the project's individual needs has saved me a lot of time on my current WIP.
 
Last edited:
I wrote a script that returns a randomly generated number based off of a dice notation string input.
Code:
///@func rollDice(rollCode)
///@arg {string} rollCode
///@desc Returns result of a roll based on an dice-notation input string
// rollCode format: [count]d[faces]+[bonus]
// [count] and [bonus] are optional
// Using "-" instead of "+" is also acceptable
var rollCode = string_lower(argument[0]);

var result = 0,
    ct    = "",
    face  = "",
    bonus = "";

// Throw error when d not specified
if (!string_count("d", rollCode)) {
  show_error("Incorrect dice string format!", true);
  exit;
}

var _ctPos = string_pos("d", rollCode);
if (_ctPos == 1) {
  // Default dice count to 1 when there is no count is specified
  ct = "1";
} else {
  ct = string_copy(rollCode, 1, _ctPos-1);
}

// Throw error when both + and - are found in string
if (string_count("+", rollCode) && string_count("-", rollCode)) {
  show_error("Incorrect dice string format!", true);
  exit;
}

// Default roll bonus to 0 when no bonus is specified
var _bonusPos = max(string_pos("+", rollCode), string_pos("-", rollCode));
if (_bonusPos == 0) {
  bonus = "0";
  face = string_copy(rollCode, _ctPos+1, (string_length(rollCode)-_ctPos)+1);
} else {
  // This copies the sign in front of the bonus since real() takes that into account anyway
  bonus = string_copy(rollCode, _bonusPos, (string_length(rollCode)-_bonusPos)+1);
  face = string_copy(rollCode, _ctPos+1, (_bonusPos-_ctPos)-1);
}

if (string_length(face) == 0) {
  show_error("Incorrect dice string format!", true);
  exit;
}

repeat(real(ct)) {
  result += irandom_range(1, real(face));
}
result += real(bonus);

// Use "return (result);" if negative numbers are OK
return (max(1, result));

It's not perfect, but it does what I need it to do: number of dice, number of faces, and +/- bonuses.
 
Last edited:

Cpaz

Member
I have a few scripts I use in most projects. Nothing too fancy, but handy little utilities to have:

gamepad_any_button():
GML:
// gamepad_any_button();

// cycle through every button on gamepad and check for input
// if button pressed, return which one. if no button pressed, return false.
for (var i = gp_face1; i < gp_axisrv; i++) {
    if (gamepad_button_check(0, i)) return i;
}
return false
I actually had a script like this. Except it also accepted analog inputs. Probably ran slow as crap, but it worked.
 
@nacho_chicken, you can do a minor optimization on your dice rolling by doing a once-off calculation that completely eliminates the repeat loop, as such:

Code:
result = irandom_range(real(ct), real(face) * real(ct)) + real(bonus);
 
@nacho_chicken, you can do a minor optimization on your dice rolling by doing a once-off calculation that completely eliminates the repeat loop, as such:

Code:
result = irandom_range(real(ct), real(face) * real(ct)) + real(bonus);
While I'm sure most of that script can be optimized heavily, that's not one of the places you can do that. The loop is required to produce correct results. With your suggestion, 3d6 would effectively be d16+2. While both have potential outcome ranges between 3-18, rolling more dice tends towards the mean and rolling one die provides equal chances to any outcome.
 
Last edited:

Tthecreator

Your Creator!
While I'm sure most of that script can be optimized heavily, that's not one of the places you can do that. The loop is required to produce correct results. With your suggestion, 3d6 would effectively be d16+2. While both have potential outcome ranges between 3-18, rolling more dice tends towards the mean and rolling one die provides equal chances to any outcome.
You could definately optimize it. I don't have the time to look up the math for you, but it comes down to this: you generate a number on a flat distribution (each number has an equal chance of dropping). Then you need to turn your output into a normal distribution.
 
I tend to be quite messy when doing my coding, and have lots of commented out code where I've tried different methods (and may still want to come back to it later) / unused variables / unoptimised code and other messy practices.

So I have been making a text parser that finds variables in my project and reads whether they are local or permanent, and then see's whether they were used or not. It currently deletes ones that aren't used and strips out commented code, but ultimately I intend for it to:

1) Redefine permanent variables as local, if that is what they should be

2) Find repeated values in an event / script and optimise it so that the value is set to a local variable, then updated back into the code

3) If I have multiple local variables, and these could be merged so as to reduce the amount that need defining, it will see if one is last used before the other is introduced. If the original one is no longer in use, then the second one is unnecessary

This is all done by having the scripts and objects as included files, since GMS can read those as text files. There's a couple of other additions where I've included the list of GMS functions (GMS will export those as a text file too), and then I created a list of GML commands not covered by these means (such as if / with / other / for etc)

So it knows what is a GMS command / what is a variable of mine - be it local or permanent / what is a numerical value / where they were used, and how often etc

Using a mixture of string functions and data structure functions it can build up a database that will eventually combat my rather poor programming habits. Once the files have been edited it can rebuild them, by using @Samuel Venable execute shell program to load up Notepad and save them back into a project.
 

Tsa05

Member
I made this: https://forum.yoyogames.com/index.php?threads/photoshop-to-json-to-gamemaker.64726/
Takes a Photoshop document, turns it into a GameMaker user interface.

I've also made a JSON data entry utility, but haven't posted it yet; been too busy and based upon post frequency and downloads, the forums seem more interested in 1-script ideas than in multi-step tools--low incentive to clean up dev tools and post.
 
Top