This question burns my brain.
I have an object on a plane, but for the sake of simplicity let’s work just on a single dimension, thus the object has a starting position xs. I know the ending position xe. The object has to move from starting to ending position with an accelerated (acceleration=a) movement. I know the velocity the object has to have at the ending position (=ve). In my special case the ending speed is zero, but of course I need a general formula. The only unknown is the starting velocity vs.
The objects starts with vs in xs and ends with ve in xe, moving along a space x with an acceleration a in a time t.
Since I’m working with flash, space is expressed in pixels, time is expressed in frames (but you can reason in terms of seconds, it’s easy to convert knowing the frames-per-second).
In the animation loop (think onEnterFrame) I compute the new velocity and the new position with (a=0.4 for example):
vx *= a (same for vy)
x += vx (same for y)
I want the entire animation to last, say, 2 seconds, which at 30 fps is 60 frames.
Now you know that in 60 frames my object has to move from xs to xe with a constant deceleration so that the ending speed is 0. How do I compute the starting speed vs?
Maybe there’s a simpler way to do this in Flash, but I am now interested in the math/physics behind this.
edit as per DSM answer.
I’ve tried to apply his suggestions:
var vx:Number;
var a = -0.5;
var xs:Number = 0;
var xe:Number = Stage.width;
var mc:MovieClip;
var keyListener = {};
var startTime:Number;
init();
function init()
{
mc = attachMovie("pallino", "p1", 0);
mc._y = Stage.height/2;
Key.addListener(keyListener);
}
Acceleration is -0.5, starting x is 0, ending x is the stage width. I attach a movieclip to the middle of the stage and then wait for a keypress. Then:
keyListener.onKeyDown = function()
{
var k = Key.getCode();
mc._x = xs;
vx = 2 * (xe - xs) / 60;
trace("vx:"+vx);
startTime = new Date().getTime();
onEnterFrame = startAnimation;
}
In the keypress event I set the starting velocity; here I use 60 for the time because my stage is set at 30 fps and I want the animation to happen in 2 seconds. Finally the animation is:
function startAnimation()
{
trace("running, vx:" + vx);
mc._x += vx;
vx += a;
if ( mc._x >= xe )
{
trace("stopping because clip is on target position");
stopAnimation();
return;
}
if ( vx <= 0 )
{
trace("stopping because speed is too slow");
stopAnimation();
return;
}
}
function stopAnimation()
{
this.onEnterFrame = null;
var secsElapsed:Number = ( new Date().getTime() - startTime) / 1000;
trace(secsElapsed);
}
The animation stops because the speed is too slow (less than zero) before the clip reaches the destination x. Why??
v = v_0 + a*t
If you know v (final velocity), a (acceleration) and t (time), then v_0 (initial velocity) comes naturally:
v_0 = v – a*t
(You can also derive it from equation 1 in DSM’s answer if you know x and x_0, but this is simpler. If you do both, the results should match)
EDIT: Actually, I think your problem has too many constrains, and is therefore unsolvable. You need another variable that can change. If you arbitrate (“know”) a, t, and v, Then v_0 is defined as v-a*t. If you then arbitrate x_0, then x_f is defined (or vice-versa). But you want to arbitrate both! So, choose another variable that can actually vary, i.e., that doesn’t matter that much to you, and then your problem will become solvable.
EDIT2: The asker said in the comments that acceleration can vary. Thus, isolating v_0 in DSM’s equations 1 and 2, then solving for a, we have:
a=(2*v/t) + 2*(x_0-x_f)/(t^2)
Then v_0 is v – a*t. This does not require that v_f is zero.
EDIT3: The failure of the code edited into the question might be due to numeric imprecision. I suggest you allow for a small tolerance when comparing current and target position. (Or just print the position difference to make sure it’s very small, then decide the code is working well enough for use.)