Reputation:
I'm trying to modify Flash CS3's supplied fl.motion.easing.bounce
function to make the resulting animation bounce less. I appreciate that 'bounce less' is a bit vague, but I'd appreciate any help in understanding the function.
Thanks.
/**
* @param t Specifies the current time, between 0 and duration inclusive.
*
* @param b Specifies the initial value of the animation property.
*
* @param c Specifies the total change in the animation property.
*
* @param d Specifies the duration of the motion.
*
* @return The value of the interpolated property at the specified time.
*/
public static function easeOut(t:Number, b:Number,
c:Number, d:Number):Number
{
if ((t /= d) < (1 / 2.75))
return c * (7.5625 * t * t) + b;
else if (t < (2 / 2.75))
return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
else if (t < (2.5 / 2.75))
return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
else
return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
}
Upvotes: 4
Views: 2771
Reputation: 113
For anyone looking for a good way to do this, check out this desmos graph:
https://www.desmos.com/calculator/uyfe8x7zrj
Here's the code in C# for it. bounceMult
is a number from 0 to 1 that adjusts the height of all the bounces, but you can easily adjust the parameters independently if you want.
If you change any of the cutoffs (as long as 0 < cutoff0
< cutoff1
< cutoff2
< 1) or the bounces (as long as each bounce is between 0 and 1) the math still works and the animation is smooth.
static float EaseOutBounceAtPoint(float x, float bounceMult)
{
float cutoff0 = 1f / 2.75f;
float cutoff1 = 2f / 2.75f;
float cutoff2 = 2.5f / 2.75f;
float bounce1 = MultiplyBounce(.75f, bounceMult);
float bounce2 = MultiplyBounce(.9375f, bounceMult);
float bounce3 = MultiplyBounce(.985375f, bounceMult);
if (x < cutoff0)
return x * x / (cutoff0 * cutoff0);
if (x < cutoff1)
{
return OneBounce(x, cutoff0, cutoff1, bounce1);
}
if (x < cutoff2)
{
return OneBounce(x, cutoff1, cutoff2, bounce2);
}
else
{
return OneBounce(x, cutoff2, 1, bounce3);
}
}
static float OneBounce(float x, float previousCutoff, float thisCutoff, float thisBounce)
{
float height = previousCutoff + (thisCutoff - previousCutoff) / 2;
float inverseHeight = height - previousCutoff;
float multiplier = (1 - thisBounce) / (inverseHeight * inverseHeight);
return multiplier * Mathf.Pow(x - height, 2) + thisBounce;
}
static float MultiplyBounce(float currentBounce, float bounceMult)
{
return 1 - ((1 - currentBounce) * bounceMult);
}
Obviously, this calculation is a lot less efficient than the original, but it's way more flexible and has fewer hard coded values. If you needed efficiency you could play around with the values and then hard code the constants you like.
It's also pretty easy to see how you can add additional bounces if you wanted.
Upvotes: 0
Reputation: 481
You can also cheat by remapping the input value to fit within the number of bounces you want.
float easing_bounce_count(float t, int bounces)
{
switch (bounces) {
case 0:
return easing_bounce(map(t, 0.0f, 1.0f, 1.0f - (1.0f / 2.75f), 1.0f));
case 1:
return easing_bounce(map(t, 0.0f, 1.0f, 1.0f - (2.0f / 2.75f), 1.0f));
case 2:
return easing_bounce(map(t, 0.0f, 1.0f, 1.0f - (2.5f / 2.75f), 1.0f));
default:
return easing_bounce_in(t);
}
}
Upvotes: 0
Reputation: 1160
To anyone still wondering how the bounce works, they are parabolas, and written in a really weird way. It's nothing else than (x - horizontal)^2 * width + vertical and limited to 0-1 in some predefined ranges.
https://www.desmos.com/calculator/0t2a24dcrh
I did the elbow grease, you can use this to tailor the bounce more or less. You have to make sure not to go above 1 and center it into the ranges so you have continuity
Upvotes: 0
Reputation: 318
try to enlarge the first touch down time,and reduce the time of bouncing,I make first whole distance of 1.4/2.7, then 1.4~2.1,this range is 0.7,half range is 0.35,0.35*0.35=0.1225,1-0.1225=0.8775,that looks good,if you want to lower bouncing range,try to use this concept: decrease the range of two time point.
t /= d;
if (t < 1.4 / 2.75) {
return 3.858419 * t * t;
}
else if (t < 2.1 / 2.75) {
t -= 1.75f / 2.75;
return 7.5625 * t * t + 0.8775f;
}
else if (t < 2.5 / 2.75) {
t -= 2.3f / 2.75;
return 7.5625 * t * t + 0.96f;
}
t -= 2.625f / 2.75;
return 7.5625 * t * t + 0.984375f;
Upvotes: 1
Reputation: 25147
Basically, the function returns an interpolated value for the new position depending on 4 factors: current time of animation, initial value of the property being animated, total change of the animation to be done, and the total duration of the animation.
What you have there is a check for different timings: if the animation still didn't reach aprox 36% (1 / 2.75) of total duration, apply the first equation; if it's between 36% and 72%, apply the second; etc.
Every equation is a function depending on the first tree arguments, so basically you need to tweak them a little bit.
I'd suggest playing with that hard-coded 7.5625 (make it greater and lower to see the results) until you're satisfied.
The 7.5625
is Math.pow(2.75, 2);
, but hard-coded to save on processing.
Upvotes: 1
Reputation: 21236
I know this is not going to give you a clear cut answer either but these equations where first conceived by Robert Penner in his book Programing Macromedia Flash MX. I know it's not an easy answer, but in his book he explains in detail how these functions work. To really understand you might want to pick up a copy and dig in.
Upvotes: 0