Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   UpdateScene and RenderScene (http://www.flasher.ru/forum/showthread.php?t=170222)

imena 20.10.2011 22:04

UpdateScene and RenderScene
 
Иго-гоооо

Сектор номер 2. Вопрос прислал пользователь из Пензы по имени imena.

Вопрос:
Пытаюсь смастерить каркас для игры... для несуществующей игры.
Решил сделать две главные функции - UpdateScene(deltaTime) и RenderScene()

В UpdateScene(deltaTime) выполняю все операции связанные с вычислением нового положения объекта(ов), текущий кадр в анимация(1) - анимация(N) и т.д. и т.п.
В RenderScene() - выполняю прорисовку всей сцены с учетом тех данных что были получены в UpdateScene()

Пихнул все это хозяйство в ENTER_FRAME.

А теперь, уважаемые знатоки, внимание вопрос:
1) правильно пихнул(обе функции) или
2) может одну из них пихнуть в EXIT_FRAME? Или может еще куда?

Всем заранее спасибо

dimarik 20.10.2011 22:44

Правильно пихнул [x]

Можно одну из них пихнуть в Event.RENDER.

Cчет 1:0 в пользу знатоков!

stweet 21.10.2011 00:06

Добавочный ответ в пользу знатоков.
В место "Event.ENTER_FRAME" советую использовать "TimerEvent.TIMER" с "updateAfterEvent();".

Код AS3:

// Сами методы оптимально было бы объединить.
public function updateScene():void // Прошу заметить, не UpdateScene а updateScene.
{
    // выполняем все операции по просчётам сцены
    // ...
    // ...
    // ...
 
    // И далее уже делаем перерисовку.
    renderScene();
}

и того 2:0, пользователь курит. Следующая игра!

crazyone 21.10.2011 01:07

Кстати, можно поподробнее - почему рендер сцены лучше вешать на таймер, чем на события кадра?

stweet 21.10.2011 01:20

Возможностей больше и производительность выше.

imena 21.10.2011 01:32

Мне тоже интересно. Я не волшебник, я только учусь... и как я понимаю, если мы поставим таймер на 1 секунду, то наш прощет сцены будет ТОЛЬКО раз в секунду?
В общем...вот как у меня было сделано(до того как я создал эту тему)

Код AS3:

/*************************************************************/
/*        Функция frameFunc() вызывается каждый раз когда присходит событие ENTER_FRAME. В этой          */       
/*        функции выполняются расчеты для всех объектов - координаты, номер текущего кадра и т.д.          */       
/*        Таким образом, у каждого не статичного объекта должна быть функция Update(dt)                          */       
/*******************************************************************************/
                private function frameFunc(e:Event):void {
 
                        var dt:Number = getTimeDelta();
 
                        switch(gameStage)
                        {
                                case GAME_INIT:
                                    //  Тут объекты со своими Update(deltaTime);
                                break;
 
                                case GAME_START:
                                    //  Тут объекты со своими Update(deltaTime);
                                break;
 
                                case GAME_OVER:
                                    //  Тут объекты со своими Update(deltaTime);
                                break;
 
                                default:
                                break;
                        }
 
                        sceneBuilder();
                }
 
                private function sceneBuilder():void {
                        switch(gameStage)
                        {
                                case GAME_INIT:
                                break;
 
                                case GAME_START:
                                break;
 
                                case GAME_OVER:
                                break;
 
                                default:
                                break;
                        }
                }
 
                private function getTimeDelta():Number {
                        now = getTimer();
                        deltaTime = now - lastFrameTime;
                        lastFrameTime = now;
 
                        return deltaTime;
                }


stweet 21.10.2011 02:06

Код AS3:

var timer:Timer = new Timer(40); // где 40 - это миллисекунды, секунда будит "delay = 1000;"
// delay = 40; Скорость рендера человеческого глаза.
// такой промежуток достаточен для машины что бы просчитать огромное количество операций.
 
default: break; // break после default не ставится. default и есть завершение switch.
 
// и признаться, в данной задаче я, switch, не использовал бы вообще.
// В классе "MyGame" удобнее было бы использовать пользовательский диспетчер
// который и будит следить за завершением игры. Тоже самое и с инициализацией настроек игры.


imena 21.10.2011 04:22

Спасибо.
Я в начале сделал по примеру Мука диспетчер.... сделал интерфейс... но... чет запутался во всех этих ограничениях с объвлением переменных, с доступом... и в конце-концов плюнул... оказЦа зря плюнул

Добавлено через 1 час 51 минуту
Я тут поэкспериментировал с анимацией...
В общем при использование Таймера анимация более 'рваная', не не равномерная, а именно 'рваная', НЕ ВСЕГДА, но все же слишком часто, а при использовании различных значений frameRate и скорости самой анимации ... анимация плавнее или если и скачками, то... мммм.. равномерными скачками

Вот кусок кода который разместил в enterFrameListener(frameRate = 30) и в timerListener(таймер на 40 миллисекунд):

Код AS3:

now = getTimer();
dt = now - lastFrame;
lastFrame = now;
/*Скорость самой анимации = 30*/
animation.update(dt);

Код animation.update(dt):
Код AS3:

 
spr.addChild(frame[curFrame]);
 
deltaFrame += (dt/1000)*_fps; // _fps - скорость воспроизведения самой анимации
 
curFrame += dFrame;

Попытался разобраться в чем тут дело.. и вышла следующая ситуация:
При использовании таймера, событие происходит не точно через каждые 40 миллисекунд... я трейсом вывел значения... там встречаются и 40 миллисекунд и 69 миллисекунд... с учетом кода производим расчеты... когда у нас 40 миллисекунд... все ок... т.к. 0.04*_fps(самой анимации = 30) = 1.2.. т.е. приращение идет на 1 кадр... и все хорошо, НО, когда deltaTime = 66 миллисекундам, тогда 0.069*30 = 2.07, т.е. приращение идет уже на два кадра, а в какой-то момент даже встретилось значение в 6 кадров.
При использовании ENTER_FRAME среднее deltaTime = 0.35.. в результате очередных расчетов... получаем 0.033*30 = 0.99, т.е., приращение идет все время на один кадр.

В общем... к чему это я все... сижу тут и думаю, какой вариант все же предпочтительнее? И почему у меня с вариантом таймера получается такая фигня?

Попробую сейчас сделать 20 анимаций одновременно...и гляну на результаты

stweet 21.10.2011 05:37

Что то я запутался в ваших цифрах. Сейчас накидаю пример.

imena 21.10.2011 05:41

вечером гляну... а то уже глаза закрываются

dimarik 21.10.2011 10:20

Только не через таймер. Я предупредил.

З.Ы. Секунда будит [x]

BuKT 21.10.2011 10:27

Цитата:

В место "Event.ENTER_FRAME" советую использовать "TimerEvent.TIMER" с "updateAfterEvent();".
Вопрос из зала: updateAfterEvent() вызывает EnterFrame или просто производит те же операции, что и вхождение в кадр? Иными словами - необходимо ли мне вызывать каждый раз camera.render() когда тикнул таймер, или оно сделает это самостоятельно, т.к. рендер камеры подписан на энтерфрейм?

crazyone 21.10.2011 21:05

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

Я еще понимаю, если у нас в приложении нет обычной анимации, а только програмная - ок, ставим фреймрейт в значение "1" и таймер даст нам больше производительности за счет отсутствия всякого функционала кадра типа фаз, вещания разных событий и т.д.
То, что возможностей больше - это конечно да, удобненько.

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

derhab 21.10.2011 21:28

Цитата:

Сообщение от crazyone (Сообщение 1040925)
Насколько я понимаю, таймер с updateAfterEvent() заставляет плеер отрисовывать содержимое не только во время, когда начинается кадр, но и в то время, когда срабатывает таймер. Каким образом это может увеличить производительность?
Но чтобы заявлять, что рендер нужно вешать исключительно на таймер - нужно привести побольше аргументов.

Плеер отрисовывает не когда "начинается кадр", а во второй фазе, когда выполнен весь код для текущего кадра. А updateAfterEvent() заставляет плеер производить внеплановую дополнительную отрисовку, что конечно, приведет к значительной потере производительности

crazyone 21.10.2011 23:31

Да, согласен, сначала код, потом рендер. Ошибся.

dimarik 22.10.2011 00:09

Цитата:

Сообщение от derhab (Сообщение 1040929)
Плеер отрисовывает не когда "начинается кадр", а во второй фазе, когда выполнен весь код для текущего кадра.

Скорее, в некоторой по счету фазе, которая наступает по прошествии (нескольких) фаз "выполнение кода в текущем кадре". Не забываем о событиях.

derhab 22.10.2011 00:16

Цитата:

Сообщение от dimarik (Сообщение 1040982)
Не забываем о событиях.

вечная память)

stweet 22.10.2011 10:39

Возможно я поспешил с выводами о ENTER_FRAME && TIMER т.к. получилось высказать сугубо личное мнение но и мнение сложилось с огромной пачки советов во время познания тонкостей оптимизации.

В первую очередь "в своё оправдание =)" хочу предложить прочитать главу "Программная анимация" ст.677 из книги К.Мука "AS3 Подробное руководство". Там как раз замечательно описывается в каких случаях и какой метод использовать. Я не отрицал ENTER_FRAME, вероятно я привел пример на TIMER т.к. сам пользуюсь только им. В общем я не использую в своих приложениях ENTER_FRAME, никогда. Все приложения которые я написал работают только на ОДНОМ TIMER-е, для многих думаю это удивительно но факт. Вопрос как можно одновременно использовать кучу анимационных объектов затронув всего один TIMER?
Вот тут на помощь приходит знания оптимизации. Которые можно черпнуть из таких книг как "Совершенный код", "300 рецептов AS3", "Оптимизация - советы профессионалов AS3". Своими словами я тут до седины буду расписывать как, что и зачем, по этому порекомендовал книги. Но на своём опыте я убедился в том что на любое приложение достаточно в основном классе зарегистрировать все один раз таких слушателей как:
Код AS3:

stage.addEventListener(MouseEvent.MOUSE_DOWN, MOUSE_DOWN);
stage.addEventListener(MouseEvent.MOUSE_UP, MOUSE_UP);
stage.addEventListener(MouseEvent.MOUSE_OVER, MOUSE_OVER);
stage.addEventListener(MouseEvent.MOUSE_OUT, MOUSE_OUT);
timer.addEventListener(TimerEvent.TIMER, TIMER);

Естественно сейчас наклон в пользу интерфейсов, но пока интерфейсы это самый удобный вариант, лучше ни чего ни нашёл. Если кого интересует как это всё работает, можем запустить ветку в пользу начинающим и на примере какой нибудь игрушки описать тонкости, собственно там их и обсуждать, этак сказать, на месте. Но тогда тема пойдёт о оптимизации.

Zebestov 22.10.2011 15:07

С каких это пор таймер для анимации стал лучше, чем ENTER_FRAME, который, к тому же, "всегда есть уже" хочешь ты того или нет?

stweet 22.10.2011 17:07

Интересно, аргументы в пользу ENTER_FRAME(А)? На самом деле, стало интересно, как организуют анимации за счёт ENTER_FRAME(А), чем выигрывает такой подход?

imena 22.10.2011 19:33

Скажите(я пока все еще на перепутье)... я так понимаю, установив timer delay в 40 миллисекунд... мы получаем те же 24 кадра в секунду.. тогда, в чем разница? Я еще не понимаю всех тонкостей.... Просто, я уже приводил тут пример(возможно код написан криво)... но мой Timer(40) не срабатывает строго каждые 40 миллисекунд.. и об этом написано у Мука... , ENTER_FRAME при фпс = 24.... тоже не срабатывает строго каждые 1000/24 = 41.6(6) миллисекунд.... НО, я вставил trace deltaTime в timerListener и enterFrameListener, и получилось что отклонения от среднего при использовании Timer больше чем при ENTER_FRAME, т.е., один раз 44 миллисекунды, другой раз 66 миллисекунд.. , а у ENTER_FRAME ...все значения примерно от 33 до 50 миллисекунд... и поэтому у меня анимация получается дерганная при использовании Timer.
Да, согласен, может я просто неправильный код для случая с Таймером использую... в общем... приведу еще раз...
Код AS3:

 
/*Кусок функции update объекта анимации... */
spr.addChild(frame[curFrame]);
 
deltaFrame += (deltaTime/1000)*_fps; // _fps - скорость воспроизведения самой анимации
 
curFrame += deltaFrame;

Может для Таймера нужно по-другому организовать анимацию?

Zebestov 22.10.2011 21:30

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

crazyone 22.10.2011 23:38

А мне вот уже третюю страницу интересно услышать аргументы в пользу Таймера.
У Мука, конечно, описывается анимация по таймеру, но ты, видимо, довольно давно читал, т.к. единственный весомый довод в пользу таймера, который приводит Мук - это независимость от фпс, в том числе - независимость от фпс родительской флешки, в которую загрузили нашу флешку.

Я бы побоялся публично давать советы типа
Цитата:

Сообщение от stweet (Сообщение 1041055)
на любое приложение достаточно в основном классе зарегистрировать все один раз таких слушателей как

Тут и за упоминание о синглтонах можно отгрести, а ты такое говоришь, да еще и вслух.

stweet 22.10.2011 23:48

Цитата:

Сообщение от crazyone (Сообщение 1041187)
А мне вот уже третюю страницу интересно услышать аргументы в пользу Таймера.
У Мука, конечно, описывается анимация по таймеру, но ты, видимо, довольно давно читал, т.к. единственный весомый довод в пользу таймера, который приводит Мук - это независимость от фпс, в том числе - независимость от фпс родительской флешки, в которую загрузили нашу флешку.

Я бы побоялся публично давать советы типа

Тут и за упоминание о синглтонах можно отгрести, а ты такое говоришь, да еще и вслух.

Не совсем понял, Вы ни когда не используете интерфейсы?

crazyone 23.10.2011 00:29

Не совсем понял - при чем здесь интерфейсы?

stweet 23.10.2011 00:54

Цитата:

Я бы побоялся публично давать советы типа
Цитата:

Цитата: Сообщение от stweet
на любое приложение достаточно в основном классе зарегистрировать все один раз таких слушателей как
Тут и за упоминание о синглтонах можно отгрести, а ты такое говоришь, да еще и вслух.
вероятно я не понял о чём тут говориться.

Genm 23.10.2011 00:54

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

-De- 23.10.2011 00:55

Зачем таймер использовать как замену ENTER_FRAME?
Ведь есть же ENTER_FRAME.

После ENTER_FRAME вызывается отрисовка, вызывается всегда (возможно, ничего не делает, но вызывается) сама по себе, не надо вызывать уродский updateAfterEvent() (если вдруг у вас что-то меняется между таймерами - можете получить фпс/2).

У меня всё на ENTER_FRAME (есть даже таймеры свои). Таймеры появились, т.к. выяснилось, что в играх время должно быть централизовано. Потому что в играх есть паузы. У таймеров пауз нет. И пауз к тому же не одна разновидность и есть их иерархия %), например есть пауза "рекламка показывается", есть пауза "юзер нажал ескейп и выехала менюха", есть пауза "юзер открыл меню здания на уровне" (при том в 3-й паузе может вызваться 2-я, а в ней 1-я).

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


Часовой пояс GMT +4, время: 17:18.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.