Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2003.08.21;
Скачать: [xml.tar.bz2];

Вниз

Синхронизация по времени   Найти похожие ветки 

 
Juster~   (2003-02-11 17:29) [0]

Здравствуйте! Мне нужно чтобы скорость анимации в OGL программе не зависела от FPS. А то у меня если 1 обьект на экране, то FPS=~90 и все двигается быстро, а если 10 обьектов, то FPS снижается и соответственно снижается скорость. Это все потому, что я пользую обычный цикл прорисовки (как у Jan Horn"a). А нужно чтоб все по атомным часам шло :) Кто знает?


 
Ketmar   (2003-02-11 18:28) [1]

с часам сложно. придётся свой драйвер делать, часы искать. опять же Windows -- не RealTime OS.

Satanas Nobiscum! 11-Feb-XXXVIII A.S.


 
pasha676   (2003-02-11 18:55) [2]

Простейший способ - цикл прорисовки идет по таймеру в 1/25 сек.
Это есссесно не гарантирует все как по атомным часам. Но во многом поможет.


 
Juster~   (2003-02-11 20:03) [3]

А может просто использовать коэффициент при расчетах движения, который зависит от времени прошедшем между итерациями цикла?


 
A_n_t   (2003-02-12 11:08) [4]

Канэчно!

коэффициент = 90/FPS
при 90 FPS будет равен 1
при 45 FPS будет равен 2
То есть при понижении FPS будет увеличиваться коэффициент, что и требовалось!

P.S. Единственная проблема: при резких перепадах FPS будут скачки.


 
Darthman   (2003-02-12 14:07) [5]

А не проще привязаться к тикам процессора, или на худой конец к GetTickGout() ?


 
Anatoly Podgoretsky   (2003-02-12 14:15) [6]

Есть же мультимедиа таймер, срабатывание до 1 мс, если система позволит.


 
Juster~   (2003-02-12 19:43) [7]

->Anatoly Podgoretsky: если не сложно, скажи где найти его можно
->Darthman: про GetTickCount я знаю, но чем он поможет? И насчет тиков процессора поподробнее, пожалуйста


 
Anatoly Podgoretsky   (2003-02-12 19:58) [8]

В справке Multimedia Timer Functions


 
Darthman   (2003-02-13 04:53) [9]

2Juster:
Делаешь (например, как самый простой вариант) таймер, с интервалом 1. Неважно, сколько он выдаст, суть не в этом.
Объявляешь глобальные переменные:
ThisTickCount, LastTickCount, ElapsedTime : DWORD;

При старте приложения:
ThisTickCount:=GetTickCount();

В обработчике таймера:
LastTickCount:=ThisTickCount;
ThisTickCount:=GettickCount();
ElapsedTime:=ThisTickCount-LastTickCount;

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


 
pasha676   (2003-02-13 10:39) [10]

2Darthman ( используя API) 2Darthman
Нафига такой гемор. Он и по быстродействию будет хуже и в исполнении далеко не самый удачный вариант.

Juster
Имхо - слушай Подгорельского. Организуй свой таймер (используя API). Это достаточно просто.


 
Anatoly Podgoretsky   (2003-02-13 10:41) [11]

Я еще не совсем Подгорел :-)
Это из стандартных системных, вероятно и в DirectX есть что нибудь специализированное.


 
pasha676   (2003-02-13 11:54) [12]

Извиняюсь описался. В смысле описАлся :). Не так написал вообщем.



 
Juster~   (2003-02-13 19:08) [13]

Спасибо за дельные советы.
-> Pasha676: Ты, наверное, ф-ции API хорошо знаешь, а я вот не очень. Поэтому просьба поподробнее, как организовать свой таймер
-> All: А как это дело реализовано в серьезных проектах, кто-нибудь знает?


 
pasha676   (2003-02-14 11:56) [14]

Функции API я знаю хреново (даже хуже). Я лучше знаю как найти нужное в хэлпе.
Вызываю из дельфина хелп по Windows SDK. Набираю в поиске слово timer и (о чудо!!!) мне появляется About Multimedia Timer.
Потом пробую делать и если у меня что то не получается то читаю еще раз или задаю вопрос на форуме.


 
Anatoly Podgoretsky   (2003-02-14 12:29) [15]

К этому просто нечего добавить!
Пройди этим путем и с непоянтками сюда.


 
Juster~   (2003-02-14 14:44) [16]

Мне стыдно говорить, но...я давно удалил хелпы по Дельфи (лишние файлы стирал), а инсталлятора пока нет. Большая просьба прислать на мэйл: juster.seth@mail.ru Спасибо!


 
Darthman   (2003-02-14 18:49) [17]

const
TIMER_RATE = 200;
TIMER_ID = 1;

SetTimer(hWnd,TIMER_ID,TIMER_RATE,nil);

Где Rate=мсек


 
Anatoly Podgoretsky   (2003-02-14 19:17) [18]

Juster~ (14.02.03 14:44)
Все 200 иб?


 
Juster~   (2003-02-14 21:17) [19]

-> Anatoly Podgoretsky: А ладно, не надо, спасибо...
-> Darthman: про это я знаю. Это ф-ция в лучшем случае выдает 50 милли сек. но никак не меньше, а это ~20 fps. Поэтому не годиться...


 
Darthman   (2003-02-16 03:22) [20]

Ладно, а тики процессора?


 
Juster~   (2003-02-16 08:07) [21]

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


 
cyborg   (2003-02-16 20:23) [22]

Подключи модуль MMSystem, или используй эти описания функций:

{$EXTERNALSYM timeKillEvent}
function timeKillEvent(uTimerID: UINT): UINT; stdcall; external "winmm.dll" name "timeKillEvent";
{$EXTERNALSYM timeSetEvent}
function timeSetEvent(uDelay, uResolution: UINT;lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): UINT; stdcall; external "winmm.dll" name "timeSetEvent";


//Установка таймера:

VAR
MM_Timer : Cardinal=0;

//Обработчик события таймера:
procedure On_Timer(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD); stdcall;
Begin
End;

//Установка таймера:
MM_Timer:=TimeSetEvent(10, 0, On_Timer, 0, 1);
//Удаление таймера:
TimeKillEvent(MM_Timer);


TimeSetEvent:
1 параметр - интервал в миллисекундах
3 параметр - процедура обработки события
5 параметр - 0 - один раз вызвать событие, 1 - повторять постоянно


 
Alek Aaz   (2003-02-17 04:18) [23]

А можно сделать так? Создать поток. Ему присвоить наивысший приоритет. В потоке высчитывать время наступления события и генерить событие.
ИМХО думаю должно сработать.


 
pasha676   (2003-02-17 09:57) [24]

2Alek Aaz
Сделать так можно. Даже наивысший приоритет наверное не нужен. Наоборот он на себя все время сожрет фиг че нарисуеш. Но таймер наверное проще.

Кстати почему SetTimer(hWnd,TIMER_ID,TIMER_RATE,nil);
Делает только 50 мс. По идеи точность должна быть гораздо выше. Даже используя таймера из DelphiX и GLScene простые сцены показывають кучу ФПС. В десятки раз больше. 1 мс конечно не добьешся, но на 3-5 я думаю можно расчитывать.
Кстати почему последний параметр nil. По идеи последний параметр должен быть ссылкой (адресом) функции, которая срабатывает на таймер.

Вообщем данная тематика меня заинтересовала. Свояю таймер этим способом. Посмотрю как он по скорости.



 
Anatoly Podgoretsky   (2003-02-17 10:15) [25]

SetTimer это обычный таймер, минимальный такт определеяется ОС - это или 10 мс или 55 мс, кроме того у него очень низкий приоритет.
Более высокую скорость обеспечивает мультимедиа таймер - у него такт около 1 мс, функция называется по другому timeSetEvent. Пример есть выше.


 
Juster~   (2003-02-17 12:27) [26]

То что надо! Хвала cyborg"у!
Кстати: допустим я установил мультимедиа таймер с интервалом 1мс, в on_timer процедуре я рисую сцену, но пока она рендерится, подошло время следующего тика таймера. Что произойдет? События выстроются в очередь или будут игнорироваться пока не дорендериться текущая сцена?
И еще, я хочу сделать так: создать таймер с интервалом 10 мс для обновления переменных (движение, поворот итд) и другой таймер 20 мс для рендеринга сцены. А они не будут мешать друг другу (задерживать или глючить)?


 
pasha676   (2003-02-17 15:11) [27]


> Кстати: допустим я установил мультимедиа таймер с интервалом
> 1мс, в on_timer процедуре я рисую сцену, но пока она рендерится,
> подошло время следующего тика таймера. Что произойдет?

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


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


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


 
Juster~   (2003-02-17 19:16) [28]

Дело в том, что мне нужно обновление переменных независимое от рендеринга.


 
cyborg   (2003-02-18 01:35) [29]

Зависания не будет, пробовал я так рендерить, всё как обычно, хотя что происходит там незнаю. Введи флаг, при начале рендеринга устанавливай его, при окончании сбрасывай. И перед рендерингом смотри, если флаг сброшен, тогда рендерить, если занято, тогда естественно не рендерить :).

Несколько таймеров мешать друг другу не должны.


 
cyborg   (2003-02-18 01:51) [30]

Поправка, если слишком маленький интервал поставить, всё будет ужасно тормозить :), сейчас проверил, видимо как сказал pasha676 (17.02.03 15:11) там образуется очередь. Используй флаги как я сказал выше.


 
pasha676   (2003-02-18 09:06) [31]

Да надо ставить флаги "запрет вывода" и "запрет обновления данных". Чтоб разрулить это дело. Возможно можно использовать не таймеры, а потоки (или таймер и поток(и)). И пользоваться семафорами.

В принципе как то делал так - идет поток обновляет данные с устройств. Если данные обновлены, то посылается мессага на рендеринг и вывод. Все на фиг посыпалось и затормозилось, когда один из датчиков начал постоянно прыгать. Видать очередь образуется. Перешел на таймеры.


 
Juster~   (2003-02-18 16:53) [32]

По-моему, флаг запрета обновления переменных вводить не стоит. Так-ведь скорость игры меняться будет, а мне постоянная нужна, т.е. чтобы, к примеру, обьект прошел 10 едениц за секунду на любом компьютере, независимо от fps


 
pasha676   (2003-02-18 18:04) [33]

Тут от постановки задачи зависит. Надо так надо. А почему вывод на экран обязательно делать по таймеру?
Может сделать так:

Таймер на 10 мс. Обновляет данные. Если данные изменились по сравнению с последним состоянием, то проверяем флаг "могу рисовать". Если рисовать могу - то посылает мессагу на отрисовку.

Обработчик мессаги. На входе выставляет флаг "не могу рисовать".
После рендинга и вывода на экран "могу рисовать".


 
Juster~   (2003-02-18 18:37) [34]

А обязательно делать через посылку мессаги, можно сделать так?
procedure Update_timer(...); - обработчик события таймера
begin
update_vars; //Обновляем переменные
if canRender then RenderScene; //Попытка рендеринга
end;

procedure RenderScene;
begin
canRender := false;
//отрисовка всего
canRender := true;
end;

или так неправильно будет?


 
pasha676   (2003-02-19 10:19) [35]

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


 
Juster~   (2003-02-19 21:36) [36]

Кстати, если обработчики таймера будут выстраиваться в очередь, то флаг canDraw не поможет, т.к. следующая процедура запуститься после окончания предыдущей (и флаг здесь будет всегда true)



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2003.08.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.008 c
8-68419
Romeo5
2003-04-22 19:01
2003.08.21
Рисование Form.Canvas


14-68518
ferrik
2003-07-31 19:35
2003.08.21
Http


1-68319
IGoRka
2003-08-08 17:58
2003.08.21
как узнать завершение роботи программи ...


4-68595
dimonf
2003-06-19 12:29
2003.08.21
Как считать из ресурса иконку с параметрами 16x16 8bit???


1-68282
Evg12
2003-07-30 16:30
2003.08.21
Помогите решить проблему с ProgressBar





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский