# GML Misc Maths Scripts

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

Tags:
1. ### DesixMember

Joined:
Jun 23, 2016
Posts:
435
GM Version: Any
Target Platform: Any

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. ### chancepredictably randomForum StaffModerator

Joined:
Apr 22, 2016
Posts:
798
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. ### SilentxxBunnyEpsilon

Joined:
Jun 21, 2016
Posts:
86
I'm particularly fond of THIS code dump. 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 EllisMember

Joined:
Aug 30, 2016
Posts:
964
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. ### DesixMember

Joined:
Jun 23, 2016
Posts:
435
@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 EllisMember

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