определение начальной скорости для ускоренной анимации (во flash / actionscript, но это математический вопрос) - PullRequest
1 голос
/ 07 января 2011

Этот вопрос сжигает мой мозг.

У меня есть объект на плоскости, но для простоты давайте поработаем только с одним измерением, поэтому у объекта есть начальная позиция xs.Я знаю конечную позицию хе.Объект должен двигаться из начальной в конечную позицию ускоренным (ускорение = а) движением.Я знаю скорость, которую должен иметь объект в конечной позиции (= ve).В моем особом случае конечная скорость равна нулю, но, конечно, мне нужна общая формула.Единственным неизвестным является начальная скорость против

. Объекты начинаются с vs в xs и заканчиваются ve в xe, двигаясь по пространству x с ускорением a за время t.

Так как я работаю со вспышкой, пространство выражается в пикселях, время выражается в кадрах (но вы можете рассуждать в терминах секунд, это легко преобразовать, зная количество кадров в секунду).

В цикле анимации (например, onEnterFrame) я вычисляю новую скорость и новую позицию с (например, = 0,4):

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

Я хочу, чтобы вся анимация длилась, скажем, 2секунд, что при 30 кадрах в секунду составляет 60 кадров.Теперь вы знаете, что в 60 кадрах мой объект должен перемещаться от xs к xe с постоянным замедлением, чтобы конечная скорость равнялась 0. Как рассчитать начальную скорость против?

Может быть, есть более простой способ сделатьэто во 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 кадров в секунду, и я хочу, чтобы анимация происходила через 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.Почему ??

Ответы [ 3 ]

2 голосов
/ 07 января 2011

v = v_0 + a * t

Если вам известны v (конечная скорость), a (ускорение) и t (время), то v_0 (начальная скорость) получается естественным образом:

v_0 = v - a * t

(Вы также можете вывести его из уравнения 1 в ответе DSM, если вы знаете x и x_0, но это проще. Если вы сделаете оба, результаты должны совпадать)

РЕДАКТИРОВАТЬ: На самом деле, я думаю, что ваша проблема имеет слишком много ограничений, и поэтому неразрешима.Вам нужна другая переменная, которая может измениться.Если вы судите («знаете») a, t и v, то v_0 определяется как va * t.Если вы затем арбитрируете x_0, тогда определяется x_f (или наоборот).Но вы хотите судить оба!Итак, выберите другую переменную, которая на самом деле может изменяться, т. Е. Для вас это не имеет большого значения, и тогда ваша проблема станет решаемой.

РЕДАКТИРОВАТЬ 2: Автор вопроса сказал в комментариях, что ускорение может варьироваться.Таким образом, выделив v_0 в уравнениях DSM 1 и 2, а затем решив для a, имеем:

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

Тогда v_0 есть v - a * t.Для этого не требуется, чтобы v_f был равен нулю.

EDIT3: сбой кода, отредактированного в вопросе, может быть вызван неточностью чисел.Я предлагаю вам учесть небольшой допуск при сравнении текущей и целевой позиции.(Или просто напечатайте разницу позиций, чтобы убедиться, что она очень мала, а затем решите, что код работает достаточно хорошо для использования.)

1 голос
/ 07 января 2011

Пусть x, v - мгновенное положение, скорость и ускорение, а t - время.Используйте _0 для начальной и _f для финальной.

В общее время мы имеем t

(уравнение 1) x = x_0 + v_0 t + 1/2 при ^2 для постоянного ускорения a,

и

(уравнение 2) v = v_0 + при

В конце, т.е. t= t_f, вы хотите, чтобы x = x_f и v = v_f = 0. Последнее условие дает v_0 = -a t_f (вставьте v = 0 в (уравнение 2)).Вставка этого в (уравнение 1) в момент времени t = t_f дает

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, то, как заметил Аль Браун, в вашей ситуации скорость никогда не станет нулевой, поэтому вам придется жить с небольшим v_f> 0. Тогда v_f = v_0.* k ^ t_f как одно уравнение и x_f = x_0 + v_0 k ^ (t_f) / log (t_f) - интегрируйте уравнение скорости, чтобы получить это - как другое;Решение оставлено читателю в качестве упражнения.

0 голосов
/ 07 января 2011

Из того, что вы говорите ve = Math.pow(a, frames) * vs так vs = ve / Math.pow(a, frames).

Однако это не будет работать с ve = 0 (как 0 * X = 0), поэтому вам придется попробовать его для ve = 0.0000001 или чего-то близкого.

На дополнительной ноте ускорение должно относиться к скорости так же, как скорость к положению. x += vx, vx += a (<0 для замедления) В этом случае <code>vs = ve - a*frames

...