Easing algorithms are something I know I will need in every single game I make. It could be for making items smoothly move onto the screen, make things bounce around in a natural way, highlighting buttons when they are selected etc etc.

None of the images above have animated sprites, they are all static images that are moved with easing.
I’ve never found an easy way to explain what Easing and Tweening is but it’s basically gradually changing the speed something moves at rather than instantly changing its speed. However it doesn’t just have to be with movement, it could be with the angle or transparency etc. This video by Code Workshop explains easing far better than me.
If you are familiar with lerp() in GameMaker (linear interpolation) it’s like that, but rather than changing at a constant rate it changes with either an acceleration or deceleration.
I mostly use easing to smooth out animations so they don’t instantly start and stop but everything slides with a momentum.
EaseInQuad(how far along the curve you want to find the value, the minimum output you want, the maximum output you want, what your maximum input could be)
EaseLinear (5,0,10,10) // output 5 because 50% of 10 is 5 EaseInCubic (5,0,10,10) // output 1.25 because 50% of the way up the curve is only 1.25 out of 10

At the very bottom of this document I will include some usage examples of how it can be used in animation.
If you want a GML script you can just import into your project you can download it here and it is identical to the code on this page with the option to either import as a tabbed script or multiple individual scripts.
Most of these functions were made by Robert Penner and I have converted them to run in GML so I have kept all of his original copyright messages in: http://robertpenner.com/easing/
The other resource I think is really important especially for new people or to help visualise this the easing is this website: http://easings.net/
#define Default_Ease_Algorithms /* * TERMS OF USE - EASING EQUATIONS * Open source under the BSD License. * Copyright (c)2001 Robert Penner * All rights reserved. * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

/// EaseLinear(inputvalue,outputmin,outputmax,inputmax)
return argument2 * argument0 / argument3 + argument1;

/// EaseInQuad(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3; return argument2 * argument0 * argument0 + argument1;

/// EaseOutQuad(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3; return -argument2 * argument0 * (argument0 - 2) + argument1;

/// EaseInOutQuad(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * argument0 * argument0 + argument1; } return argument2 * -0.5 * (--argument0 * (argument0 - 2) - 1) + argument1;

/// EaseInCubic(inputvalue,outputmin,outputmax,inputmax)
return argument2 * power(argument0/argument3, 3) + argument1;

/// EaseOutCubic(inputvalue,outputmin,outputmax,inputmax)
return argument2 * (power(argument0/argument3 - 1, 3) + 1) + argument1;

/// EaseInOutCubic(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * power(argument0, 3) + argument1; } return argument2 * 0.5 * (power(argument0 - 2, 3) + 2) + argument1;

/// EaseInQuart(inputvalue,outputmin,outputmax,inputmax)
return argument2 * power(argument0 / argument3, 4) + argument1;

/// EaseOutQuart(inputvalue,outputmin,outputmax,inputmax)
return -argument2 * (power(argument0 / argument3 - 1, 4) - 1) + argument1;

/// EaseInOutQuart(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * power(argument0, 4) + argument1; } return argument2 * -0.5 * (power(argument0 - 2, 4) - 2) + argument1;

/// EaseInQuint(inputvalue,outputmin,outputmax,inputmax)
return argument2 * power(argument0 / argument3, 5) + argument1;

/// EaseOutQuint(inputvalue,outputmin,outputmax,inputmax)
return argument2 * (power(argument0 / argument3 - 1, 5) + 1) + argument1;

/// EaseInOutQuint(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * power(argument0, 5) + argument1; } return argument2 * 0.5 * (power(argument0 - 2, 5) + 2) + argument1;

/// EaseInSine(inputvalue,outputmin,outputmax,inputmax)
return argument2 * (1 - cos(argument0 / argument3 * (pi / 2))) + argument1;

/// EaseOutSine(inputvalue,outputmin,outputmax,inputmax)
return argument2 * sin(argument0 / argument3 * (pi / 2)) + argument1;

/// EaseInOutSine(inputvalue,outputmin,outputmax,inputmax)
return argument2 * 0.5 * (1 - cos(pi * argument0 / argument3)) + argument1;

/// EaseInCirc(inputvalue,outputmin,outputmax,inputmax)
// This is a really radical curve... haha hidden programmer joke.
argument0 /= argument3; return argument2 * (1 - sqrt(1 - argument0 * argument0)) + argument1;

/// EaseOutCirc(inputvalue,outputmin,outputmax,inputmax)
argument0 = argument0 / argument3 - 1; return argument2 * sqrt(1 - argument0 * argument0) + argument1;

/// EaseInOutCirc(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * (1 - sqrt(1 - argument0 * argument0)) + argument1; } argument0 -= 2; return argument2 * 0.5 * (sqrt(1 - argument0 * argument0) + 1) + argument1;

/// EaseInExpo(inputvalue,outputmin,outputmax,inputmax)
return argument2 * power(2, 10 * (argument0 / argument3 - 1)) + argument1;

/// EaseOutExpo(inputvalue,outputmin,outputmax,inputmax)
return argument2 * (-power(2, -10 * argument0 / argument3) + 1) + argument1;

/// EaseInOutExpo(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3 * 0.5; if (argument0 < 1) { return argument2 * 0.5 * power(2, 10 * --argument0) + argument1; } return argument2 * 0.5 * (-power(2, -10 * --argument0) + 2) + argument1;

/// EaseInElastic(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; var _p = 0; var _a = argument2; if (argument0 == 0 || _a == 0) { return argument1; } argument0 /= argument3; if (argument0 == 1) { return argument1+argument2; } if (_p == 0) { _p = argument3*0.3; } if (_a < abs(argument2)) { _a = argument2; _s = _p*0.25; } else { _s = _p / (2 * pi) * arcsin (argument2 / _a); } return -(_a * power(2,10 * (--argument0)) * sin((argument0 * argument3 - _s) * (2 * pi) / _p)) + argument1;

/// EaseOutElastic(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; var _p = 0; var _a = argument2; if (argument0 == 0 || _a == 0) { return argument1; } argument0 /= argument3; if (argument0 == 1) { return argument1 + argument2; } if (_p == 0) { _p = argument3 * 0.3; } if (_a < abs(argument2)) { _a = argument2; _s = _p * 0.25; } else { _s = _p / (2 * pi) * arcsin (argument2 / _a); } return _a * power(2, -10 * argument0) * sin((argument0 * argument3 - _s) * (2 * pi) / _p ) + argument2 + argument1;

/// EaseInOutElastic(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; var _p = 0; var _a = argument2; if (argument0 == 0 || _a == 0) { return argument1; } argument0 /= argument3*0.5; if (argument0 == 2) { return argument1+argument2; } if (_p == 0) { _p = argument3 * (0.3 * 1.5); } if (_a < abs(argument2)) { _a = argument2; _s = _p * 0.25; } else { _s = _p / (2 * pi) * arcsin (argument2 / _a); } if (argument0 < 1) { return -0.5 * (_a * power(2, 10 * (--argument0)) * sin((argument0 * argument3 - _s) * (2 * pi) / _p)) + argument1; } return _a * power(2, -10 * (--argument0)) * sin((argument0 * argument3 - _s) * (2 * pi) / _p) * 0.5 + argument2 + argument1;

/// EaseInBack(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; argument0 /= argument3; return argument2 * argument0 * argument0 * ((_s + 1) * argument0 - _s) + argument1;

/// EaseOutBack(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; argument0 = argument0/argument3 - 1; return argument2 * (argument0 * argument0 * ((_s + 1) * argument0 + _s) + 1) + argument1;

/// EaseInOutBack(inputvalue,outputmin,outputmax,inputmax)
var _s = 1.70158; argument0 = argument0/argument3*2 if (argument0 < 1) { _s *= 1.525; return argument2 * 0.5 * (argument0 * argument0 * ((_s + 1) * argument0 - _s)) + argument1; } argument0 -= 2; _s *= 1.525 return argument2 * 0.5 * (argument0 * argument0 * ((_s + 1) * argument0 + _s) + 2) + argument1;

/// EaseInBounce(inputvalue,outputmin,outputmax,inputmax)
return argument2 - EaseOutBounce(argument3 - argument0, 0, argument2, argument3) + argument1

/// EaseOutBounce(inputvalue,outputmin,outputmax,inputmax)
argument0 /= argument3; if (argument0 < 1/2.75) { return argument2 * 7.5625 * argument0 * argument0 + argument1; } else if (argument0 < 2/2.75) { argument0 -= 1.5/2.75; return argument2 * (7.5625 * argument0 * argument0 + 0.75) + argument1; } else if (argument0 < 2.5/2.75) { argument0 -= 2.25/2.75; return argument2 * (7.5625 * argument0 * argument0 + 0.9375) + argument1; } else { argument0 -= 2.625/2.75; return argument2 * (7.5625 * argument0 * argument0 + 0.984375) + argument1; }

/// EaseInOutBounce(inputvalue,outputmin,outputmax,inputmax)
if (argument0 < argument3*0.5) { return (EaseInBounce(argument0*2, 0, argument2, argument3)*0.5 + argument1); } return (EaseOutBounce(argument0*2 - argument3, 0, argument2, argument3)*0.5 + argument2*0.5 + argument1);
That’s the end of all the easing functions I have. Let’s look at how you can use that in an example.
This is the code to animate this button bounce.

CREATE:
/// animation engine buttonwidth = 120 buttonheight = 26 frame = 0 framesmax[1] = 20 // heading towards the button framesmax[2] = 20 // squishing against the button framesmax[3] = 20 // going back framesmax[4] = 20 // bouncing out part = 1 // what part of the animation we are on distancebounce = 30 strechamountx = 0.4 strechamounty = 1.0STEP:
frame++ if (frame >= framesmax[part]) { // this part of the animation has finished move onto the next one part++ frame = 0 if (part >= array_length_1d(framesmax)) { // the whole animation has finished so reset the whole thing part = 1 } }DRAW:
switch (part) { case 1: var distance = distancebounce-EaseInCubic(frame, 0, distancebounce, framesmax[part]) draw_sprite_ext(spr_buttonselect, 0,x-distance,y,1,1,0,c_white,1) break; case 2: var strechh = 1-(EaseOutCubic(frame,1,100,framesmax[part])/100)*strechamountx var strechv = EaseOutCubic(frame,1,strechamounty/2,framesmax[part]) draw_sprite_ext(spr_buttonselect, 0,x,y,strechh,strechv,0,c_white,1) break; case 3: var strechh = (1-(EaseOutCubic(framesmax[part]-frame,1,100,framesmax[part])/100)*strechamountx) var strechv = EaseOutCubic(framesmax[part]-frame,1,strechamounty/2,framesmax[part]) draw_sprite_ext(spr_buttonselect, 0,x,y,strechh,strechv,0,c_white,1) break; case 4: var distance = EaseOutCubic(frame, 0, distancebounce, framesmax[part]) draw_sprite_ext(spr_buttonselect, 0,x-distance,y,1,1,0,c_white,1) break; }
