Easing Explained for AS2 and AS3

http://www.actionscript.org/resources/articles/791/1/Easing-Explained-for-AS2-and-AS3/Page1.html

Jean André Mas

Graphic designer converted since 2004 to coding. I play around with C++, OpenGL, Java, Javascript, AND Actionscript.

My website: ASWC

My website: ASWC

By Jean André Mas

Published on June 20, 2008

An overview of easing methods and how to create your own.

In this tutorial I will explain how easing works in relationship to the Tween class either in AS3 and AS2 and how you can easily modify existing easing classes to fit your needs or create your own easing methods. To understand this tutorial you should at least know how to use a tween in AS3 or AS2 and have also a basic understanding of classes.

So here is a basic tween (AS3):

var Xtween:Tween = new Tween(square,"x",Back.easeIn,square.x,square.x+100,1,true);

We create an instance of the Tween class: var Xtween:Tween = new Tween();

We pass a reference to an object: var Xtween:Tween = new Tween(square,

We tell which property of the object we want to tween: var Xtween:Tween = new Tween(square,"x",

We pass an easing function: var Xtween:Tween = new Tween(square,"x",Back.easeIn,

We pass a starting value: var Xtween:Tween = new Tween(square,"x",Back.easeIn,square.x,

We pass an ending value: var Xtween:Tween = new Tween(square,"x",Back.easeIn,square.x,square.x+100,

We pass a duration: var Xtween:Tween = new Tween(square,"x",Back.easeIn,square.x,square.x+100,1,

And finaly we tell if the duration will be expressed in seconds or in frames: var Xtween:Tween = new Tween(square,"x",Back.easeIn,square.x,square.x+100,1,true);

So already one word about the two last parameters, duration and type (seconds/frames), no matter what you choose, the tween will still use frames as a basis for its calculations. You can check that out easily by setting a frame rate to 1 and then run a Tween using seconds ... not pretty right? So the frame rate matters even if you use seconds.

The Tween takes all the parameters and calculates how many frames it will need to go from the initial value (here square.x) to the final value (square.x+100), it then call the easing function this exact number of frames. So if the tween needs 30 frames to reach the final value, it will call the easing function 30 times. The Tween will call the easing

function with 4 parameters: First: The initial time (starting at zero of course) , second: The initial value of the property being tweened (in our example square.x) , third: The final value needed (100) , fourth: The total duration of the tween. The Tween expects to receive a number from the easing function each time it calls it. Fairly simple, let's create our own easing function to see this in action:

var Ytween:Tween = new Tween(square,"y",crazyTween,square.y,square.y+100,1,true);

function crazyTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

if(TimeOrigin/FinalTime<1){

return FinalValue+Math.random()*200;

}else{return InitialValue+FinalValue;}

}

That's right, we can pass our own easing function as long as we return a number! Try this awesome easing function and see, the tween uses it! If you trace all this you'll see that the only value changng from call to call is the first one, the initial time. On a 30 frames tween, the initial time will go from 0 to 30, 30 being the duration time. Now you see why the useless crazyTween function was still able to end up at the right place. Now if we want to apply a linear motion, all we need is to divide the amount needed (in our example 100) by the number of frames needed and add that to the initial value:

var Ytween:Tween = new Tween(square,"y",normalTween,square.y,square.y+100,1,true);

var increase:Number = 100/30;

function normalTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

increase += 100/30;

return InitialValue+increase;

}

A perfect linear tween if you have a framerate of 30, now how do we translate so that no matter the number of frames needed it will always end up right?

Remember, the only value changing in the call to the easing function is the initial time. It's gonna start with zero and end up being exactly the duration time so if we divide it by the duration time we get a ratio that we can use to calculate the amount we need to add to the initial value:

TimeOrigin/FinalTime this is our ratio. So FinalValue*(TimeOrigin/FinalTime) will give us the right amount we need to add each time but of course we need to add it to the initial value so the final formula is: InitialValue+FinalValue*(TimeOrigin/FinalTime) let's try:

var Ytween:Tween = new Tween(square,"y",normalTween,square.y,square.y+100,1,true);

function normalTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

return InitialValue+FinalValue*(TimeOrigin/FinalTime)

}

Of course we always think about moving objects with tweens but look at this:

var theNumber:Number = 0;

var Ytween:Tween = new Tween(this,"theNumber",normalTween,0,300,1,true);

function normalTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

trace(InitialValue+FinalValue*(TimeOrigin/FinalTime))

return InitialValue+FinalValue*(TimeOrigin/FinalTime)

}

That's right, we are tweening a simple variable!

Now before we move deeper into easing functions I want to point out the default easing method that can be found in the tween class. This default easing method is a linear easing exactly like the one we created and the tween class will run it if no easing function is provided so :

var Ytween:Tween = new Tween(this,"theNumber",null,0,300,1,true);

Will force the tween class to run its internal easing method. Note that this internal easing method is equivalent to the None easing class with AS2 and the Linear easing class with AS3.

Let's look at a typical class easing method like in the Back class for example:

public static function easeIn(t:Number, b:Number, c:Number,

d:Number, s:Number = 0):Number

{

if (!s)

s = 1.70158;

return c * (t /= d) * t * ((s + 1) * t - s) + b;

}

We recognize our 4 numbers here t: initial time, b: initial value, c: final value, and d: duration. But there's another one: s, that's the amplitude of the back effect. Change this hard coded value to any number you want to get a different back effect, or even better create a public method and then set s as an instance property:

public var amplitude:Number;

public function easeIn(t:Number, b:Number, c:Number,

d:Number):Number

{

return c * (t /= d) * t * ((amplitude + 1) * t - amplitude) + b;

}

Then in your code create an instance of the Back class:

var theBack:Back = new Back();

set the amplitude:

theBack.amplitude = 10;

then run the tween!

var Ytween:Tween = new Tween(this,"theNumber",theBack.easeIn,0,300,1,true);

Now you can also create different effect with the same easing method:

var theBack:Back = new Back();

theBack.amplitude = 1;

var theBackY:Back = new Back();

theBackY.amplitude = 20;

var Xtween:Tween = new Tween(tween_mc,"x",theBack.easeIn,tween_mc.x,tween_mc.x+100,2,true);

var Ytween:Tween = new Tween(tween_mc,"y",theBackY.easeIn,tween_mc.y,tween_mc.y+100,2,true);

Up to you to go through all easing classes and mess with their formulas. Now let's explore a bit custom easing.

We know that any easing function needs to be able to end up no matter what with the right value. Remember the crazyTween function was giving back random values to the tween while the tween was running but at the final call, it was giving the right value so the object would end up at the right place. Any custom easing method or function should do just that, ending with the right value, but between the start of the tween and the end, you are free to apply any mathematical equation. let's try a few.

function shakeTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

var i:Number = 0;

if(TimeOrigin/FinalTime<1){

i = Math.random()*FinalTime*10;

}else {i = 0}

return InitialValue+i+FinalValue*(TimeOrigin/FinalTime)

}

This will give a shake effect to your tween.

var i:Number = 0;

var current:Number = 0;

function clockTween(TimeOrigin:Number,InitialValue:Number,FinalValue:Number,FinalTime:Number):Number{

if(TimeOrigin>i){

i += FinalTime/3;

current = InitialValue+FinalValue/FinalTime*(TimeOrigin/FinalTime)

return current;}

return current;

}

I created this one to create a clock effect with a rotation property. Now you know how to create and apply your own easing function so go get your old math books and then share with us your creations!