GML Misc Maths Scripts

Desix

Member
GM Version: Any
Target Platform: Any
Download: N/A
Links: N/A

Summary:
A few scripts I find useful and would like to share (and somewhat archive) here.
Some are much more common than others, and some are very obscure.
I can't promise these are the most efficient way to do things, but they work.

More obscure ones towards the bottom.

Tutorial:

1: Wrap
An alternative to clamp(), it loops a value around between a min and max.
For example, converting an angle to between 0-360 if it's below or above that, keeping the angle intact.
Code:
///wrap(value, minimum, maximum)
/*
    Makes sure a value stays between a min and max, looping round if it exceeds
*/

    //arguments
    var value = argument0; //value to change
    var val_min = argument1; //minimum of range
    var val_max = argument2; //maximum of range
 
    //calculate
    var val_mod = (value-val_min) mod (val_max-val_min);
    if (val_mod < 0) return val_mod+val_max else return val_mod+val_min;

2: Approach
Can be used to transition slowly between 2 amounts each step.
'Start' is where the value is currently at this step, and is what will be changed and returned.

This can be used to control the alpha of a fade to black, when called each step. Where start is the current alpha, with an end of 1, and a shift of 0.125.
Code:
///approach(start, end, shift)
/*
    Moves a start value by a shift amount towards an end goal
*/

    //arguments
    var start = argument0; //where the value is now
    var end_val = argument1; //where the value needs to be
    var shift = abs(argument2); //how fast the value should move
 
    //calculate
    var difference = end_val-start;
    var sign_val = sign(difference);
    var new_shift = min(abs(difference),shift)*sign_val;
 
    return start+new_shift;
3: Approach (scale)
Similar to normal approach, it uses an amount of the distance left rather than a flat shift to move smoothly
Code:
///approach_scale(start, end, scale)
/*
    Moves a start value by a relative shift scale towards an end goal
*/

    //arguments
    var start = argument0; //where the value is now
    var end_val = argument1; //where the value needs to be
    var shift = abs(argument2); //how much the value should move relative to the distance left
 
    //calculate
    return start+(end_val-start)*shift;
4: Stretch
Stretches a given range to a new range.
For example 75 with min and max 50 to 100, becomes 2 with a When the new min and max are 0 and 4
Code:
///stretch(val, vmin, vmax, newmin, newmax)
/*
    Stretches or compresses a value in a given range to a new equivilent value in a different range
*/
 
    //arguments
    var val = argument0; //value to change
    var vmin = argument1; //original range min
    var vmax = argument2; //original range max
    var newmin = argument3; //new range min
    var newmax = argument4; //new range max
 
    //calculate
    return (((val - vmin) * (newmax - newmin)) / (vmax - vmin)) + newmin;
5: Sine flicker
Adds some control via sine wave to a random value between 0-1.
Imagine a sine wave between 0-1 controlled by 'angle' but also a random offset of that controlled by 'flicker amount' (the sine is made smaller to accommodate this within 0-1).

This can be used for something like a flame light flickering where you'd want it to flicker between 0-1 but also glow in and out somewhat.
Code:
///sine_flicker(angle, flickeramount)
/*
    A somewhat controlled flicker, the flicker will be lower or higher depending on angle. Returns a flicker amount between 0-1
*/
 
    //arguments
    var angle = argument0; //used in a sine funcion
    var flickeramount = clamp(argument1/2, 0, 1); //amount of the flicker, between 0 and 1 (should be around 0.5)
 
    //calculate
    var corrected_sine = (dsin(angle)/2)+0.5;
    var sine_scale = 1-(flickeramount*2);
    var shrunk_sine = (corrected_sine*sine_scale)+flickeramount;
 
    return shrunk_sine+random_range(-flickeramount, flickeramount);
6: Amount by proximity
Gets a value from 0-1 based on how close a position is to a centre, within a radius of maxdist. (1 dimensional)

This could be used for a dynamic bridge, which dips as you walk on it. This script will find how fully the bridge should be dipping with center at the middle x of the bridge, pos at the players x position, and a maxdist of half the bridges length.
Code:
///amount_by_proximity(center, pos, maxdist)
/*
    Gets a value from 0-1 based on how close a position is to a centre, within a radius of maxdist
*/

    //arguments
    var center = argument0; //central value
    var pos = argument1; //dynamic value
    var maxdist = argument2; //maximim distance between values to check (radius)
 
    //calculate
    return clamp((1-(abs(center-pos))/maxdist), 0, 1);
7: Amount by proximity (linear)
Similar to above, but does not converge at 1 at the centre
Code:
///amount_by_proximity_linear(center, pos, maxdist, dir)
/*
    Gets a value from 0-1 based on a position around a center within a radius of maxdist.
    However it is linear, for example if pos=center, 0.5 will be returned
*/

    //arguments
    var center = argument0; //central value
    var pos = argument1; //dynamic value
    var maxdist = argument2; //maximim distance between values to check (radius)
    var dir = argument3; //whether it goes from 0-1 or 1-0
 
    //calculate
    var xmin = center-maxdist;
    var xmax = center+maxdist;
    var space = maxdist*2;
    var amount = clamp(pos-xmin, 0, space)/space;
    if (!dir) amount = 1-amount;
 
    return amount;
 
Last edited:

chance

predictably random
Forum Staff
Moderator
I'm not particularly fond of code dump topics containing several different examples. But you made an effort to clean this up and remove some trivial examples, as requested. So I appreciate that.

With the exception of the "flicker" effect, most of these examples are fairly basic. Most programmers have their own approach to things like value wrapping, range scaling, and moving a variable toward a destination value. Nonetheless, it's interesting to see other approaches.

You might consider providing a project file with examples of these in use. Especially for the transition examples, since starting and stopping the effect isn't discussed in your topic. But that's up to you.
 
I'm not particularly fond of code dump topics containing several different examples.
I'm particularly fond of THIS code dump. :p

With the exception of the "flicker" effect, most of these examples are fairly basic. Most programmers have their own approach to things like value wrapping, range scaling, and moving a variable toward a destination value. Nonetheless, it's interesting to see other approaches.
I'm fairly basic myself, but I found these examples helpful... Especially value wrapping.

You might consider providing a project file with examples of these in use.
I try not to promise anything to anyone, but if I use these scripts in my current project - I'll strip out the relevant bits and post examples here.

Thanks, Desix!
 

Joe Ellis

Member
You know, there's a better way to do wrap:

Code:
///wrap(val, min_val, max_val)

var
val = argument0,
min_val = argument1,
max_val = argument2;

return (frac((val - min_val) / (max_val - min_val)) * (max_val - min_val)) + min_val;
 
Last edited:

Desix

Member
@Joe Ellis
Mhm I've improved a bit since I posted them that's for sure, that script was rubbish. For now I've just replaced it with something better, so both options are here. Did you mean frac instead of fract?
 
Top