确定加速动画的起始速度(在 flash/actionscript 中,但这是一个数学问题)

发布于 2024-10-11 03:50:55 字数 1895 浏览 5 评论 0原文

这个问题烧伤了我的大脑。

我在平面上有一个物体,但为了简单起见,我们只在单个维度上工作,因此该物体有一个起始位置 xs。我知道结束位置xe。对象必须以加速(加速度=a)运动从起始位置移动到结束位置。我知道物体在结束位置 (=ve) 时必须具有的速度。在我的特殊情况下,结束速度为零,但当然我需要一个通用公式。唯一未知的是起始速度 vs。

物体以 xs 中的 vs 开始,以 xe 中的 ve 结束,在时间 t 内以加速度 a 沿着空间 x 移动。

由于我使用闪光灯,空间以像素表示,时间以帧表示(但您可以以秒为单位进行推理,知道每秒帧数很容易进行转换)。

在动画循环中(想想 onEnterFrame),我用(例如 a=0.4)计算新速度和新位置:

vx *= a (same for vy)
x += vx (same for y)

我希望整个动画持续 2 秒,在 30 fps 下是 60 帧。 现在您知道,在 60 帧中,我的对象必须以恒定的减速度从 xs 移动到 xe,以便结束速度为 0。我如何计算起始速度 vs?

也许在 Flash 中有一种更简单的方法可以做到这一点,但我现在对其背后的数学/物理感兴趣。

根据 DSM 答案进行编辑。

我尝试应用他的建议:

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);
}

加速度为-0.5,起始x为0,结束x是舞台宽度。我将一个影片剪辑附加到舞台中间,然后等待按键。然后:

keyListener.onKeyDown = function()
{
    var k = Key.getCode();

    mc._x = xs;
    vx = 2 * (xe - xs) / 60;
    trace("vx:"+vx);

    startTime = new Date().getTime();
    onEnterFrame = startAnimation;
}

在按键事件中我设置了起始速度;这里我暂时使用 60,因为我的舞台设置为 30 fps,并且我希望动画在 2 秒内发生。最后的动画是:

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);

}

动画停止,因为在剪辑到达目标 x 之前速度太慢(小于零)。为什么??

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??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花桑 2024-10-18 03:50:55

v = v_0 + a*t

如果你知道 v(最终速度)、a(加速度)和 t(时间),那么 v_0(初速度)自然就出来了:

v_0 = v - a*t

(你也可以从方程推导它如果您知道 x 和 x_0,则 DSM 的答案中为 1,但这更简单,如果您同时执行这两个操作,结果应该匹配)

编辑:实际上,我认为您的问题有太多限制,因此无法解决。您需要另一个可以更改的变量。如果仲裁(“知道”)a、t 和 v,则 v_0 定义为 va*t。如果您随后仲裁 x_0,则定义 x_f(反之亦然)。但你想对两者进行仲裁!因此,选择另一个实际上可以变化的变量,即对你来说并不那么重要的变量,然后你的问题就会变得可以解决。

EDIT2:提问者在评论中说加速度可能会有所不同。因此,在 DSM 方程 1 和 2 中分离出 v_0,然后求解 a,我们有:

a=(2*v/t) + 2*(x_0-x_f)/(t^2)

那么 v_0 就是 v - a*t 。这并不要求 v_f 为零。

EDIT3:编辑到问题中的代码失败可能是由于数字不精确。我建议您在比较当前位置和目标位置时允许较小的公差。 (或者只是打印位置差异以确保其非常小,然后确定代码运行良好以供使用。)

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.)

迎风吟唱 2024-10-18 03:50:55

设 x、v、a 为瞬时位置、速度和加速度,t 为时间。使用 _0 作为初始值,使用 _f 作为最终值。

对于恒定加速度 a,我们有一般时间 t

(eq. 1) x = x_0 + v_0 t + 1/2 at^2

并且

(eq. 2) v = v_0 + a t

最后,即 t = t_f,您需要 x = x_f 和 v = v_f = 0。后一个条件给出 v_0 = -a t_f(将 v = 0 插入(式 2))。在时间 t=t_f 处将其插入到(等式 1)中,得到

a = 2 (x_0-x_f)/t_f^2

,因此

v_0 = 2 (x_f - x_0) / t_f

只是基本运动学方程的推导,即初始速度和最终速度的平均值是平均速度((v_0+v_f)/2 = d/t,同样对于恒定加速度),其中我们设置 v_f = 0. [实际上,只需注意单位即可在常数因子内得到上述结果:速度的单位为[长度/时间],因此最终答案可能看起来像位移除以时间..]

我认为使用不正确的公式 (v *= 'a' ) 会产生更平滑的动画,因为该方程不对应于恒定加速度(其加加速度为零,其中加加速度是加速度的时间导数,就像加速度是时间一样速度的导数),但它是一个更平滑的变量(因为 v ~ 'a'^t)。

如果您确实想要一种更平滑的非恒定加速(即您的 v *= k 方法给出的加速),那么在这种情况下计算出细节也很简单,但这是更容易解释的。

更新: 噢,什么鬼。如果 v = v_0 * k^t,那么正如 Al Brown 指出的那样,在您的情况下速度永远不会为零,因此您将不得不忍受一些小的 v_f > 。 0. 然后,我们将 v_f = v_0 * k^t_f 作为一个方程,并将 x_f = x_0 + v_0 k^(t_f) / log(t_f) - 对速度方程进行积分以获得这个 - 作为另一个方程;解决问题留给读者作为练习。

Let x, v, a be instantaneous position, velocity, and acceleration, and t the time. Use _0 for the initial and _f for the final.

We have at a general time t

(eq. 1) x = x_0 + v_0 t + 1/2 a t^2 for constant acceleration a,

and

(eq. 2) v = v_0 + a t

At the end, i.e. t = t_f, you want x = x_f and v = v_f = 0. The latter condition gives v_0 = -a t_f (insert v = 0 into (eq. 2)). Inserting this into (eq. 1) at time t=t_f gives

a = 2 (x_0-x_f)/t_f^2

and thus

v_0 = 2 (x_f - x_0) / t_f

which is simply a derivation of the basic kinematic equation saying that the average of initial and final velocity is the average velocity ((v_0+v_f)/2 = d/t, again for constant acceleration) where we've set v_f = 0. [Actually, you can get the above within a constant factor just by noting the units: velocity has units of [length/time], so the final answer should probably look like the displacement divided by the time..]

I think using the incorrect formula (v *= 'a' ) produces a smoother animation because that equation doesn't correspond to a constant acceleration (which has a jerk of zero, where jerk is the time derivative of acceleration the same way that acceleration is the time derivative of velocity) but a variable one which is smoother (because v ~ 'a'^t).

If you really do want a smoother, non-constant acceleration -- i.e. the one given by your v *= k approach -- it's straightforward to work out the details in that case too, but this was the easier one to explain..

Update: oh, what the heck. If v = v_0 * k^t, then as Al Brown noted, the velocity isn't ever going to go to zero in your situation, so you'll have to live with some small v_f > 0. We then have v_f = v_0 * k^t_f as one equation and x_f = x_0 + v_0 k^(t_f) / log(t_f) -- integrate the velocity equation to get this -- as the other; solving is left as an exercise for the reader.

清风无影 2024-10-18 03:50:55

根据你所说的ve = Math.pow(a,frames) * vs所以vs = ve / Math.pow(a,frames)

然而,这不适用于 ve = 0(如 0 * X = 0),因此您必须尝试 ve = 0.0000001 或接近的值。

另外需要注意的是,加速度对待速度的方式应与速度对待位置的方式相同。
x += vx,
vx += a(a < 0 表示减速)
在本例中 vs = ve - a*frames

From what you are saying ve = Math.pow(a, frames) * vs so vs = ve / Math.pow(a, frames).

However that won't work with ve = 0 (as 0 * X = 0), so you will have to try it for ve = 0.0000001 or something close.

On an additional note acceleration should treat velocity in the same way as velocity does to position.
x += vx,
vx += a ( a < 0 for deceleration)
In this case vs = ve - a*frames

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文