Prev « NexGen is Hiring! Next » Molecule Match, a Game

11 Nov 2013

In the 2002 book, **"Robert Penner's Programming Macromedia Flash MX"** the author wrote a chapter about tweening; a word you may now know as "easing". Anyhoo, these easing functions have made their way into mainstream programming culture and have been ported over into every conceivable language and many popular frameworks.

Simply, easing functions are a way to animate in a smooth or interesting manner.

These functions have been all but unaltered for the past decade, however while looking into the relatively new gameclosure framework I found an opportunity to contribute by adding these functions to their javascript codebase.

So I did the logical thing, read some background information, found a modern port (jQuery) and started dissecting the code... what I found was bewildering and confusing.

- t: current time
- b: beginning value
- c: change in value
- d: duration

I might be missing the point, but these parameters make the functions difficult to read and complex to use outside of their intended animation scope. I *wrongly* surmised that the functions would accept one parameter akin to **Math.sin**, **Math.cos** or **Math.tan**, *after* which the transformations and manipulations could be applied.

So I modified the jQuery easing functions to accept one parameter:

If you consider the above parameters we can assume a special scenario:

- t: current time
- Between 0 and 1

- b: beginning value
- Always 0

- c: change in value
- Always 1

- d: duration
- Always 1

Means that we can rewrite the functions to an extremely compact form, for example:

// Original Function easeInQuad = function (t, b, c, d) { return c * (t /= d) * t + b; }; // Swapping our special values easeInQuad = function (n) { return 1 * (n /= 1) * n + 0; }; // Refactored easeInQuad = function (n) { return n * n; };

You can quickly see that my version is *MUCH* more readable. Furthermore, I've found an amazing oddity in the jQuery port of the elastic easing:

// Original easeInElastic = function (t, b, c, d) { var s=1.70158;var p=0;var a=c; if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3; if (a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; }; // Expanded easeInElastic = function (t, b, c, d) { var s = 1.70158; var p = 0; var a = c; if (t == 0) { return b; } if ((t /= d) == 1) { return b + c; } if (!p) { p = d * .3; } if (a < Math.abs(c)) { a = c; var s = p / 4; } else { var s = p / (2 * Math.PI) * Math.asin(c / a); } return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b; }; // Swapping our special values and adding comments... easeInElastic = function (n) { var s = 1.70158; var p = 0; var a = 1; if (n == 0) { return 0; } if ((n /= 1) == 1) { return 0 + 1; } // "p" is ALWAYS 0, why set it above? if (!p) { p = 1 * .3; } // "s" is ALWAYS replaced regardless, why set it above? if (a < Math.abs(1)) { // "a" is already set to 1... err... // not that it matters, as 1 is NEVER < 1 thus this is NEVER executed a = 1; var s = p / 4; } else { var s = p / (2 * Math.PI) * Math.asin(1 / a); } return -(a * Math.pow(2 , 10 * (n -= 1)) * Math.sin((n * 1 - s) * (2 * Math.PI) / p )) + 0; }; // Refactoring A easeInElastic = function (n) { if (n == 0) { return 0; } if (n == 1) { return 1; } var p = 0.3; var s = p / (2 * Math.PI) * Math.asin(1); // This is ALWAYS 0.075 return -(a * Math.pow(2 , 10 * (n -= 1)) * Math.sin((n * 1 - s) * (2 * Math.PI) / p )) + 0; }; // Refactoring B easeInElastic = function (n) { if (n == 0) return 0; if (n == 1) return 1; var p = 0.3; var s = 0.075; // p / (2 * Math.PI) * Math.asin(1) return -(Math.pow(2, 10 * (n -= 1)) * Math.sin((n - s) * (2 * Math.PI) / p)); };

You may have missed it, but there's a LOT of redundant code and needless logical checks; the resulting function is not only faster, but in my mind **just better**.

My full refactor is available on github here

Prev « NexGen is Hiring! Next » Molecule Match, a Game