![]() |
|
||||||||||
|
|
|
|||||
|
Регистрация: Jan 2008
Сообщений: 84
|
Возникла небольшая проблемка, а именно: при повороте объекта на угол формируемый некторым вектором, объект поворачивается до 2П, далее угол скидывается на -2П, и плавно уходит в ноль. Цикл повторяется, объект крутиться.
Только это ая-яй как плохо, ибо нужно чтоб крутилось от -nП до nП (требуется знать сколько витков намоталось или наоборот размоталось). На сегодняшний день, решение достаточно простое, есть некая переменная к которой прибавляется либо отнимается шаг угла. Сей алгоритм в некторых случаях уходит в погрешность и со временем вырастает в серьёзную проблему... Может быть кто-нибудь с таким сталкивался и красиво решил всё это дело?... |
|
|||||
|
Регистрация: Mar 2008
Адрес: Ростов-на-Дону
Сообщений: 354
|
ммм... ну ведь rotation это тоже некоторая переменная типа Number, и точность её не выше точности любой другой переменной типа Number. Ну ладно, геттер это, но суть от этого не меняется.
Проблема тут не в другой переменной, а в том, что шаг угла прибавляется итеративно, и погрешность накапливается. Так будет не только во флэше, но и в любой другой системе с ограниченной памятью. Поэтому подходить нужно с другой стороны: пусть угол поворота в момент времент t вычисляется как a*t + b. Теперь запоминаем время начала вращения, и в каждом кадре вычисляем прошедшее с этого момента время. Для всего этого есть глобальная функция getTimer(). Ну а далее, думаю, понятно ![]() Последний раз редактировалось SamFR; 06.11.2009 в 04:28. |
|
|||||
|
Регистрация: Jun 2006
Сообщений: 400
|
Если значение с 2Пи скидывается на минус 2Пи, это, как мне кажется, ошибка алгоритма уже. По поводу накопления ошибки, это конечно возможно. Если вы крутите объект туда сюда раз эдак 10^8. Тогда может и накопиться. А в вашем случае, опять же, думаю что навран алгоритм.
А что конкретно и как крутится? Как вариант Решение взял из статьи мерлина про игру с астеройдами. Она прилеплена. Последний раз редактировалось proxiServer; 06.11.2009 в 12:17. |
|
|||||
|
Регистрация: Mar 2008
Адрес: Ростов-на-Дону
Сообщений: 354
|
proxiServer, вы забыли учесть, что прибавление угла происходит в каждом кадре, а их 30 в секунду. Так что ошибка очень даже накапливается, можете проверить.
Поэтому, если важно, чтобы объект не просто крутился (перемещался), а оказывался в определённый момент в определённом положении, то про последовательное прибавление угла (координаты) нужно забыть. Последний раз редактировалось SamFR; 06.11.2009 в 16:27. |
|
|||||
|
можно сохранять угол поворота в отдельной переменой в градусах, и проводить операции тоже в градусах, с целыми значениями, а потом при применении к обьекту заранее вычисленного угла поворота переводить в радианы...
|
|
|||||
|
Регистрация: Mar 2008
Адрес: Ростов-на-Дону
Сообщений: 354
|
Да зачем же все эти ухищрения? Всё ж просто:
//перед началом вращения var t0:uint = getTimer(); //момент начала вращения var T:uint = 10000; //полное время вращения (в мс.) //каджый кадр var t:Number = 2*(getTimer() - t0)/T - 1; //от -1 (в начале вращения) до 1 (в конце) object.rotation = N*t*Math.PI; //от -N*PI в начале вращения до N*PI в конце |
|
|||||
|
Регистрация: Jan 2008
Сообщений: 84
|
Цитата:
Еще раз про задачу. Пользователь накручивает некоторый вектор Nое кол-во раз, может совершить хоть 20000 витков, и в этоге получится какой-то бешеный угол в 34234Пи+отступ И вот на этот угол совершенно не торопясь будет поворачиваться объект. (r+=(endR-r)*speed) Причём чем больше кол-во витков тем "туже" идёт поворот (скорость уменьшим), но это уже лирика =) P.s. немного пояснений: нет проблемы от -180 до 180, преобразовать это не составляет труда, есть проблема, что после 360 идёт 0 а не 361 и т.д. Ибо при "мгновенном" повороте что 360 что 0 - одно и тоже, а при динамическом, думаю понятно как всё происходит. |
|
|||||
|
Регистрация: Mar 2008
Адрес: Ростов-на-Дону
Сообщений: 354
|
T – это время, в течение которого будет продолжаться вращение (назовём его полное время). Так как getTimer() даёт время в миллисекундах, то для удобства (чтобы всё время не делить начальное время на 1000) полное время также задаётся в миллисекундах.
Полное время нужно, во-первых, для того, чтобы привести текущее время к заданному отрезку отрезку (в моём примере (-1, 1), можно к любому другому, как вам удобно). А, во-вторых, чтобы определить момент окончания вращения. Таким образом, в каждом кадре нужно проверять текущее время вращения, которое равно getTimer() - t0. Вычитать t0 нужно для того, чтобы время шло с 0, так как getTimer() возвращает время, прошедшее с момента запуска плеера. Как только величина getTimer() - t0 превзойдёт T, то в последний раз вычисляем угол для времени T, а затем заканчиваем анимацию (путём отписывания от события ENTER_FRAME, либо установки флага, как вам больше нравится). Цитата:
![]() Можно (и даже лучше) взять не такую формулу, а что-то типа вашОбъект.rotation = angle0 + (angle1 – angle0)*t/T, где angle0 – начальный угол поворота в радианах, angle1 – конечный угол поворота в радианах, t = getTimer() – t0 задаёт текущее время. Это как раз-таки можно сделать, задавая перед запуском анимации T в зависимости от нужного количества витков. Чем больше будет полное время вращения, тем меньше будет скорость, естественно. Последний раз редактировалось SamFR; 06.11.2009 в 23:33. |
|
|||||
|
Регистрация: Jan 2008
Сообщений: 84
|
Где то я видимо объясняю криво.
Смотрим пример, который я вам приводил. Задаём N, исходя из того, сколько витков пользователь совершил [/quote] Ведь в этом и проблема =) Зная N, можно устанавливать угол например так: currentAngle+2Pi*n и не нужны эти сложности с таймерами и прочим. Вычислить максимально точно N у меня не получается (стоит очень быстро покрутить мышкой и все слетает) отсюда погрешности и прочее. Перегружать rotation как то не охота =) он не виноват, ему смело можно указать rotation=720 |
|
|||||
|
Регистрация: Mar 2008
Адрес: Ростов-на-Дону
Сообщений: 354
|
Тогда
Цитата:
Можно смотреть, сколько раз object.rotation перешёл значения PI/2 и -PI/2, и в какой последовательности. И на основе этого предполагать, сколько было сделано полных оборотов. Либо изначально количество оборотов задавать не вращением объекта, а, например, перетягиванием ползунка (вводом числа). Тут уж всё зависит от специфики. Но, как мне кажется, общая схема, если не получается точно определить количество оборотов, такова: узнали angle0 (object.rotation перед началом вращения объекта пользователем) и angle1 (object.rotation в конце вращения объекта пользователем), а также [N], то есть количество полных оборотов. Далее к angle0 и angle1 прибавили (вычли) период (то есть 2*PI) столько раз, чтобы оба угла лежали на полуотрезке [0; 2*PI). Далее к angle1 прибавали количество полных оборотов, умноженное на 2*PI (то есть angle1 += [N]*2*PI). Далее вращаем. Последний раз редактировалось SamFR; 09.11.2009 в 22:17. |
![]() |
![]() |
Часовой пояс GMT +4, время: 19:47. |
|
|
« Предыдущая тема | Следующая тема » |
|
|