C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Что делать, когда sleep(1) — много?
Алексей
Отправлено: 11.07.2003, 22:59


Не зарегистрирован







Что делать, когда sleep(1) — много?
Георгий
Отправлено: 12.07.2003, 01:00


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



OS Microsoft Windows 9x и Windows NT — не являются системами реального времени и путём экспериментов удалось выяснить, что управление задаче передаётся (даже в случае наступления ожидаемого события) не быстрее чем через 5ms
проверить это можно так:
CODE
DWORD t[10];
int i;
for (i=0;i<10;i++)
   {
   t[i]=GetTickCount();
   Sleep(1);
   };
for (i=0;i<10;i++)
   {
   this->Memo1->Lines->Add(t[i]);
   };

это было сказано, что бы показать отсутствие большого смысла не только в Sleep(1), но и даже в Sleep(10), а о меньших интервалах времени можно только мечтать.
Хотя принципиально такие интервалы времени можно отследить (хотя бы циклом с RDTSC), но никогда нельзя быть уверенным, что ОС не отнимет процессорное время у задачи и самый важный момент времени (тот самый < 1 ms) будет пропущен...

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

Расскажи — зачем тебе такие малые интервалы нужны, может быть удастся что-то придумать, что увеличит их без потери качества и прочих желаемых характеристик.
Алексей
Отправлено: 12.07.2003, 02:05


Не зарегистрирован







Без проблем, расскажу smile.gif

Мне нужно двигать, допустим, небольшой круг по канве. Нужно, чтобы этот круг двигался не перескакивая через пиксели, и чтобы двигался достаточно быстро. В принципе, пустые циклы решают проблему, но только на моем компьютере...
Георгий
Отправлено: 12.07.2003, 12:18


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



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

наверное сейчас у тебя это сделано так:
1. стираем старый
2. рисуем со смещением новый

очевидные минусы — между 1 и 2 есть некоторая пауза — которую видно как мерцания (если сейчас не видно, то значит быстрая видеокарта+процессор и маелнькая картинка)

избавление от мерцания (т.н. двойная буфферизация):
3. VisibleBuf=1,HiddenBuf=2
4. устанавливаем видимым буфер № visibleBuf
5. очищаем буфер # HiddenBuf
6. рисуем рисунок в буфере #HiddenBuf
7. visibleBuf<=>HiddenBuf (т.е. VisibleBuf=2,HiddenBuf=1)

мерцаний нет (судя по всему синхронизацию с обратным ходом луча развёртки выполниет Windows), а есть неприятное для глаза "перескакивание через пиксели", которое обусловлено тем, что глаз не видит всех промежуточных состояний (наверное во время прямого хода луча развёртки Windows все изменения экрана выполняет над скрытым буфером, а переключение выполняет во время обратного хода луча — т.е. все промежуточные состояния физически не отображаются на экране).

идея спасения от такой ситуации следующая (для простоты описания забудем о двойной буфферизации):

8. рисуем новую (смещённую картинку) не стирая старой
9. старием старую, но не затирая новую

в результате за изображением есть некоторый шлейв (обьект как бы перетекает из одного состояния в другое) — который и маскирует эти перескакивания через пиксели. Причём если в начаме работы алгоритмя повторить шаг 8 несколько раз, то это позволит задать велечину шлейфа на всё последующее время работы алгоритма.
Кстати — нечто подобное использует Blizzard в своих играх — если в Starcraft присмотреться к движению мелких юнитов (людская пехота) или быстро движущихся (людские стелсы), то видно смазывание мелких деталей и небольшой шлейф.

Хотя у меня есть смутное подозрение, что функции плавной анимации давным-давно были разработаны и оформлены в виде библиотек...
Гость_Matt
Отправлено: 12.07.2003, 13:30


Не зарегистрирован







>>Хотя у меня есть смутное подозрение, что функции плавной анимации давным-давно были разработаны и оформлены в виде библиотек...

Конечно! OpenGL для этого и создана. Только на канве, наверное, OpenGL применить не получится sad.gif( (сам не пробовал — не знаю).
Guest
Отправлено: 12.07.2003, 17:18


Не зарегистрирован







Я делаю через CopyRect — и никакого мерцания.
Проблема в том, что изменяя координаты на пиксель со sleep'ом — медленно, без слипа — носится как бешеный smile.gif

PS. запустил старкрафт посмотреть — вспомнил только через час, зачем я его запустил smile.gif
Asher
Отправлено: 13.07.2003, 16:53


Мастер участка

Группа: Модератор
Сообщений: 550



Можно ппробовать поработать с парой
LARGE_INTEGER PFreq;
LARGE_INTEGER PCount;
Функцией QueryPerformanceFrequency получаем частоту (обычно> 1МГц) и вычислям длительность одного тика, а затем в цикле считываем значение QueryPerformanceCounter
Guest
Отправлено: 14.07.2003, 01:23


Не зарегистрирован







Спасибо, как попробую — напишу!
seg_r
Отправлено: 14.07.2003, 15:26


Дежурный стрелочник

Группа: Участник
Сообщений: 74



А можно и ваще ничего не стирать, создать ну...
TBitmap, и рисовать на нем и стирать на нем, а на Canvas кидать Draw'ом в нужное время и все, никаких перерисовок, сразу готовую картинку, поменял все че надо и снова на Canvas ...
Георгий
Отправлено: 16.07.2003, 08:15


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



по поводу движения без перескакиваний — а оно нужно?
у меня есть програмка http://www.georgiestar.pisem.net/3dgraph.rar (для запуска лучше написать 3dgraph 10 3) так у неё обекты между кадрами перескакивают через несколько пикселей, но визуально это не ощущается, а вот если отключить двойную буферизацию или синхронизацию переключения страниц с обратным ходом луча развёртки, то и начинаются разные неприятности.

Вернуться в Вопросы программирования в C++Builder