PDA

Просмотр полной версии : Анимация enterFrame + getTimer


Akopalipsis
02.11.2013, 16:18
Со вчерашнего дня не получается сделать и сегодня я уже думаю, что не допонял чего то.
В advanceTime передаются значения
0.040000000000000036
0.04499999999999993
0.029999999999999805
0.020000000000000018
public function advanceTime(time:Number):void
{
//суммарное прошедшее время
_passedTime += time;
var balance:Number = 0;
//проверяю, если суммарное время больше либо равно
//_refreshRate ( _refreshRate - это сикунда поделённая на кол-во кадров )
if (_passedTime >= _refreshRate)
{
//вычитаю взятое время из суммарного
balance = _passedTime-_refreshRate;
//вычитаю это из суммарного времени
_passedTime -= balance;
//передаю время во все методы
for (var index:int = 0; index < _length; index++)
{
_animates[index].advanceTime(_refreshRate);
}
}
//и вот здесь проблема. я понимаю так - если произошёл лаг
//то этот метод не кто не вызовет, а значит лаги передадутся на анимацию
//по этому я возвращаю это значение в этот же метод
//но именно из-за этой рекурсии всё и отваливается.
//где я не правильно понял?
if (balance) this.advanceTime(balance);
}

Wolsh
02.11.2013, 16:45
//вычитаю взятое время из суммарного
balance = _passedTime-_refreshRate;
//вычитаю это из суммарного времени
_passedTime -= balance;
Почему просто не написать _passedTime = _refreshRate;?
Что такое "взятое" время? Почему "взятое" это "сикунда поделённая на кол-во кадров"?
Вообще не понимаю, как и раньше, что Вы делаете.
По сути Вы просто всем отдаете это самое предрасчетное время на один кадр — и _animates[index] и this получают просто _refreshRate.

Akopalipsis
02.11.2013, 17:56
Что такое "взятое" время? Почему "взятое" это "сикунда поделённая на кол-во кадров"?
//_refreshRate ( _refreshRate - это сикунда поделённая на кол-во кадров )
Вообще не понимаю, как и раньше, что Вы делаете.
Не поймёте наверное по тому, что я сам немного не правильно понимаю...
Тут я писал и переписывал три раза и наконец я понял предназначение этого подхода.
я ждал от него плавного течения времени, а он создан для того, чтобы обьект из точки А в точку Б дошел за точное время.

Добавлено через 15 минут
Но! я сам уже сбился :) Слова
я ждал от него плавного течения времени, а он создан для того, чтобы обьект из точки А в точку Б дошел за точное время.
это про метод, который рассылает время, а я спрашиваю о "обработке" этого времени.
Потому что, если мне нужно менять положение обьекта в зависимости от времени, то получится следующее
_object.x += time;
и пока лагов нет, то его движение можно назвать равномерным. Но тут происходит лаг и время не приходит, а обьект застывает. Потом приходит сразу много времени и обьект перепрыгивает через это время и выглядеть это будет, как лаг. Если выдавать это время частями, то цель этого мероприятия - из А в Б за секунду, то же теряется. Где я не пойму чего то?

Tails
02.11.2013, 18:01
это про метод, который рассылает время, а я спрашиваю о "обработке" этого времени.
Потому что, если мне нужно менять положение обьекта в зависимости от времени, то получится следующее
_object.x += time;
и пока лагов нет, то его движение можно назвать равномерным. Но тут происходит лаг и время не приходит, а обьект застывает. Потом приходит сразу много времени и обьект перепрыгивает через это время и выглядеть это будет, как лаг. Если выдавать это время частями, то цель этого мероприятия - из А в Б за секунду, то же теряется. Где я не пойму чего то?

Смысл в том, что объект достигнет точки Б за одно и то-же время, независимо от того были лаги или нет. При этом, "лаг" - превращается в понятие - низкий fps.
Это называется анимация, основанная на времени.

пс.
Прибавлять нужно не само время, а время * скорость. Скорость задаётся как расстояние, проходимое за 1 секунду. (Тут передаваемое время служит не только как показатель конкретно прошедшего времени, но и как математический коэффициент для нахождения изменения состояния. Это очень простая вещь, но может быть, немного сложная для начального понимания.)

пс.2
Если вам нужна плавная анимация, передавайте в advanceTime фиксированное значение, например: 1/60, если у вас фремрейт == 60. Однако, при таком способе, анимация будет закономерно замедляться вместе с лагами. А дробовики, перезарядка которых основана на этой анимации, будут иметь уникальное время перезарядки.

Akopalipsis
02.11.2013, 18:37
Tails Спасибо! Скорость у меня есть, я её не написал, так как смотрел на движение скорости по умолчанию.
При этом, "лаг" - превращается в понятие - низкий fps.
А это понятие, как то решает проблему с дерганьем?
Тут передаваемое время служит не только как показатель конкретно прошедшего времени, но и как математический коэффициент для нахождения изменения состояния.
Вот это я и пытаюсь понять, но пока безрезультатно. я понимаю, что время нужно передавать кусочками и если произойдёт лаг,
то сам метод advanceTime перестанет вызываться и всё встанет, хоть запас времени и будет. По этому я и делаю рекурсию, если есть время,
то лаги не страшны, метод сам себя будет вызывать. Но происходит завал плеера и по этому я и спросил - как это решить.
я не боюсь коэффициентов, я просто не пойму, как это реализовать.

Добавлено через 7 минут
Может нужно для равномерности написать какой то замедлитель или возможно есть, алгоритм равномерного распределения. Если так, то скажите правильное название. я просто пытаюсь сделать "что то", что заменит для всего приложения EnterFrame и позволит работать без тырчков.

Tails
02.11.2013, 19:26
А это понятие, как то решает проблему с дерганьем?

Дёрганье - это низкий фпс. А низкий фпс вы никаким образом не поднимите, пока не купите нормальный компьютер. (Или не произведёте оптимизацию для его повышения. пс. Здесь, конечно, можно придумать какой-то алгоритм, который будет стараться сгладить большую разность во времени между тиками. Этот механизм должен находиться на самом верху в ядре, в котором происходит первичное уведомление главного juggler. В старлинге, такого механизма нету. Готового решения я не искал. Разработка такого механизма должна быть не слишком сложная, может максимум - 1 день.)

Это два способа анимации:

На основе реального прошедшего времени - getTimer
Привязанной к частоте выполнения - 1/60


Иногда нужно, что-бы анимация проигрывалась с точно указанной скоростью, независимо от fps - 1 способ. Когда точная скорость анимации не важна, или нужна обязательно плавная анимация без лишнего гемора - 2 способ. (Однако длительность анимации будет возрастать, при понижений fps)


Вот это я и пытаюсь понять, но пока безрезультатно. я понимаю, что время нужно передавать кусочками и если произойд

Передаваемое время можно использовать как коэффициент, или процент от некоторого значения. Так, передаваемый 0 (ноль) - это 0%, 1 (единица) - 100%.
Если мы возьмём некоторый параметр как значение/секунду (значение в секунду), то мы сможем рассчитать конкретное изменение этого параметра: параметр * переданный коэффициент.
Пример:

Мячик двигающийся со скорость. 120px/sec за 0.5 времени - сместится на половину своей скорости.
Кровоточащая рана на герое, за 1 секунду выдаёт 50 брызг крови. За 0.2 времени - из него выльется 10 мувиклипов крови.

Wolsh
02.11.2013, 19:47
Вот, я еще тогда заподозрил, что Вы что-то не то придумали про эту технологию, когда прозвучал какой-то очень странный вопрос типа "как мне значение 0.2 поможет рассчитать сколько кадров займет движение из А в В".
Анимация по времени вообще не занимается плавностью, скорее даже наоборот — она рассчитывает, насколько надо скакнуть анимации, чтобы придти в нужную фазу в нужное время, и предназначена как раз не для сглаживания скачков, а для того, чтобы скачки не рассинхронизировали течения анимаций. Она гарантирует, что анимация с предрасчетным временем 1.5 сек закончится через 1.5 сек, даже если ей придется показать только начальную и конечную фазу.
А "плавность" анимации это абсолютно другая задача, и она в принципе не решается при низком фпс или его скачках. Никак. Это технически невозможно — если экран полсекунды не обновлялся из-за тормозов системы, то скачок будет и ничем его не смажешь. Объект не может двигаться на экране, когда экран НЕ обновляется))

Tails
02.11.2013, 19:51
Wolsh,
С разной степенью эффективности, скачки сгладить всё-же можно. Но в целом да, при рендере всего 2 кадров, мы увидим начальное и конечное состояние анимации.


Сглаживанием может заниматься сам объект, получающий уведомления.
Сглаживать разность перепадов может главный уведомитель перед уведомлением. Однако, при таком способе, завершение анимации отдельных объектов будет близкой к указанной.

Wolsh
02.11.2013, 20:08
Для начала, наверное, надо определиться в терминологии: есть скачок и есть фриз.
Скачок это когда объект "вдруг" оказывается слишком далеко, то есть как будто скорость неожиданно возросла (и объект оказывается в нужной точке в нужное время, но, возможно, "в три прыжка" вместо двенадцати, то есть после фриза объект будет двигаться с бОльшей скоростью, чем задумано).
Фриз это когда экран не обновляется, объекты на какое-то время застывают на месте, а затем продолжают двигаться дальше с той же скоростью (и оказываются в нужной точке позже чем планировалось, но будет показан каждый "кадр" анимации).

Tails
02.11.2013, 20:17
Со скачком и фризом понятно, продолжайте.

Wolsh
02.11.2013, 20:21
Сглаживанием может заниматься сам объект, получающий уведомления.Ну это динамический перерасчет остатка, я так понимаю.
То есть объект анимации знает, что ему надо пройти 200 пикселей за 4 секунды. Вот он получает время 2 секунды, а прошел 80 пикселей. Расчетная скорость была 200/4 = 50 в секунду. Сейчас осталось 120 пикселей и 2 секунды. Пересчитываем скорость: 120/2 = 60 пикселей в секунду.
При этом объекту не нужно знать, сколько еще тиков будет (что, конечно же, невозможно). Он просто подгоняет текущую скорость под остаток. А решение "в лоб" говорило бы, что объект во время "2 секунды" должен отобразиться на позиции 100 пикселей, и баста.
Вы об этом "сглаживании"?

Babylon
02.11.2013, 20:24
Уолш, мастер постановок задач, а в этом как известно большой процент решения.

Tails
02.11.2013, 20:27
Wolsh,
Именно, это один из способов для сглаживания.

Возможен так-же и вариант, когда сам уведомитель будет мониторить шаги. В случае слишком большого шага после фриза, он вышлет слегка заниженное его значение, распределив остаток на дальнейшие несколько кадров. (Подгонять анимацию на протяжении следующих n кадров)

Akopalipsis
02.11.2013, 20:34
Уолш, мастер постановок задач, а в этом как известно большой процент решения.
Согласен! И так как я не правильно понял предназначения анимации на времени, это не как не сказывается на моей цели, которая заключалась в "плавном течении времени". Так как для плавности анимации есть лишь один выход, твин, в котором ты указываешь скорость, то я буду анимировать весь поток.
И передавать время ровными частями, а если какой то обьект хочет ускориться, то свойство скорости ему это поможет сделать. Но меня мучают мысли, которых очень много и они все по разному говорят, что это не получится...

Добавлено через 30 секунд
Остаётся только сидеть и экспериментировать.

MikroAcse
02.11.2013, 20:40
Что за? Зачем это все?
Почему просто не использовать старый добрый Difference of Times (Delta)?
var lastTime:int = getTimer();
addEventListener(Event.ENTER_FRAME, onUpdate);

function onupdate(e:Event):void {
var currentTime:int = getTimer();
var dt:Number = (currentTime - lastTime) * 0.001 // тот самый difference of times
// тут выполняешь код, при этом умножая на dt, например:
lastTime = currentTime();
}
Или я чего-то не понимаю?

Akopalipsis
02.11.2013, 20:43
Или я чего-то не понимаю?
У меня точно так же, только вопрос - что с этим делать..
private function stage_enterFrameHandler(event:Event):void
{
var currentTime:Number = getTimer() /1000.0
var passedTime:Number = (currentTime-_lastTime);
_lastTime = currentTime;
_animator.advanceTime(passedTime);
}

Tails
02.11.2013, 20:45
Так ладно, мне кажется, тема полностью раскрыта. Отчаливаю.

MikroAcse,
Вот именно с этого всё и началось. Перечитайте внимательно тему и посмотрите, с какими проблемами столкнулся автор.
И да:
lastTime = currentTime();

MikroAcse
02.11.2013, 20:56
lastTime = currentTime();
Ошибочка. Интегер нельзя вызвать, или это магия?

Akopalipsis
03.11.2013, 20:41
Возможен так-же и вариант, когда сам уведомитель будет мониторить шаги.
А можно Вас спросить - Вы в своём просчете шагов updateAfterEvent используете?

MikroAcse
03.11.2013, 20:47
updateAfterEvent
Вот это вообще трогать не нужно.