1
\$\begingroup\$

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?

\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$
    – Sidar
    Oct 9, 2013 at 17:19
  • \$\begingroup\$ Looks like steering behaviors would be a better solution to your problem? \$\endgroup\$
    – bummzack
    Oct 10, 2013 at 7:17

2 Answers 2

1
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
2
  • \$\begingroup\$ This seems like a long ways around the idea that this problem needs seeking/homing behavior instead of easing. \$\endgroup\$ Oct 10, 2013 at 0:15
  • \$\begingroup\$ 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. \$\endgroup\$
    – Jeff Gates
    Oct 10, 2013 at 16:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .