GML Misc Maths Scripts

Discussion in 'Tutorials' started by Desix, Jan 25, 2017.

Tags:
  1. Desix

    Desix Member

    Joined:
    Jun 23, 2016
    Posts:
    430
    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: Aug 3, 2019
    tagwolf, SilentxxBunny and abd_sab like this.
  2. chance

    chance predictably random Forum Staff Moderator

    Joined:
    Apr 22, 2016
    Posts:
    785
    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.
     
    SilentxxBunny and Desix like this.
  3. SilentxxBunny

    SilentxxBunny Epsilon

    Joined:
    Jun 21, 2016
    Posts:
    62
    I'm particularly fond of THIS code dump. :p

    I'm fairly basic myself, but I found these examples helpful... Especially value wrapping.

    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!
     
  4. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    890
    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: Aug 5, 2019
    Desix likes this.
  5. Desix

    Desix Member

    Joined:
    Jun 23, 2016
    Posts:
    430
    @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?
     
    Joe Ellis likes this.
  6. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    890
    Yeah, I got mixed up cus it's fract in glsl lol, normally I've got the error checker telling me
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice