# Easing equations with moving end points

Usually easing equations have 4 parameters:

• time
• duration
• begin point
• end point

For example:

``````public static float EaseOutQuad(float currTime, float begin, float end, float duration)
{
currTime /= duration;

return -end * currTime * (currTime - 2f) + begin;
}
``````

Now afaik `begin` and `end` point are fixed values. In my game I have an object oscillating between 2 points on its local X axis. I'm interpolating its position using easing equations, but I would like to be able to modify the end point dynamically avoiding discontinous or abrupt changes.

Is it possible to do this using easing equations or something similar? Any suggestion?

-
When you modify the end point value t (currtime) needs to be adjusted too. Else it might jump position. Usually people just call a new "tween" ( assuming you are tweening here ) on the same object with new values. – Sidar Oct 9 '13 at 17:19
Looks like steering behaviors would be a better solution to your problem? – bummzack Oct 10 '13 at 7:17

If you parameterize the movement on time elapsed since the beginning (i.e. you don't compute the position incrementally, but fully every frame), and the end point also moves smoothly, you should get smooth movement without much problems.

Something like this:

``````start_x = 0
end_x = 100
total_time = 5  // 100 pixels in 5 seconds
t = 0
while t < total_time:
t = min(t + delta_t, total_time)
p = t / total_time
x = start_x + p*(end_x - start_x)
draw at x
``````

is a simple linear interpolation between start_x and end_x. Note that `x` is a function of the parameter `p`, and it doesn't depend at all on the previous value of `x`.

So if you want the end point to move smoothly, it's just like this:

``````start_x = 0
end_x = 100
total_time = 5  // 100 pixels in 5 seconds
t = 0
while t < total_time:
t = min(t + delta_t, total_time)
p = t / total_time
end_x += delta_t * speed_of_endx  // <----------
x = start_x + p*(end_x - start_x)
draw at x
``````

That should work fine. Of course, the computation of the position of `end_x` will probably be decoupled from the computation of `x`; this is just an example.

-

A common scheme is simply lerping the new and old functions

``````Blend(oldBegin, oldEnd, oldT, newBegin, newEnd, newT, blendT) {
oldPos = OldCurve(oldBegin, oldEnd, oldT);
newPos = NewCurve(newBegin, newEnd, newT);
return Lerp(oldPos, newPos, blendT);
}
``````

There are decisions and bookkeeping to keep track of and decide when and how fast to transition from the old to the new curves. Specifically if i'm going from point A to B from time 0 to 1, then at time T decide i need to go to point C instead you have the choices:

``````// migrate curves with a blend time.  smoothest, but can be have high speed variance if B and C are far apart.
Blend(time) = {
oldPos = Curve(A, B, time);
newPos = Curve(A, C, time);
return lerp(oldPos, newPos, (time - T) / BLEND_DURATION);
}
``````

or maybe

``````// start new curve from current position.  lower speed variance
Blend(time) = {
oldPos = Curve(A, B, time);
newPos = Curve(oldPos, C, (time - T));
return lerp(oldPos, newPos, (time - T) / BLEND_DURATION);
}
``````

or something else that suits your use case better. For the best results, a good grasp of the underlying calculus (of both the curves as well as the externals causing the end point changes) can go a long way to crafting a formula to produce the desired effect.

-
This seems like a long ways around the idea that this problem needs seeking/homing behavior instead of easing. – Patrick Hughes Oct 10 '13 at 0:15
Perhaps, I find in some cases that can lead to ringing, over-dampening and other issues. But of course it depends on the specifics of the case. – Jeff Gates Oct 10 '13 at 16:13