Как правило, игра будет продолжать рисовать новые кадры все время, даже когда пользователь ничего не делает.Обычно это происходит там, где у вас есть вызов onIdle ().Если ваша игра обновляет окно / экран только тогда, когда пользователь нажимает кнопку или что-то подобное, или время от времени между ними, то MSGWaitForMultipleObjects
является хорошим вариантом.
Однако в игре с непрерывной анимацией вы обычно вообще не хочет блокировать или спать в потоке рендеринга , если вы можете помочь, вместо этого вы хотите рендериться на максимальной скорости и полагаться на вертикальную синхронизацию в качестве газа.Причина в том, что синхронизация, блокировка и спящий режим в лучшем случае неточны, а в худшем - ненадежны, и это вполне возможно добавит мешающие артефакты к вашей анимации.графическому API (скорее всего, OpenGL, поскольку вы сказали «любая платформа») как можно быстрее, подайте сигнал рабочему потоку, чтобы он начал выполнять игровую логику, физику и т. д., а затем заблокируйте SwapBuffers.
Все таймерыТайм-ауты и время ожидания ограничены разрешением планировщика, которое в Windows составляет 15 мс (можно установить 1 мс с помощью timeBeginPeriod
).При 60 кадрах в секунду кадр составляет 16,666 мс, поэтому блокировка на 15 мс катастрофична, но даже 1 мс - все еще значительное время.Вы ничего не можете сделать, чтобы получить лучшее разрешение (это значительно лучше в Linux).
Sleep
, или любая функция блокировки, которая имеет тайм-аут, гарантирует, что ваш процесс спит по крайней мере столько, сколько вы просили (на самом деле, в системах Posix, оно может спать меньше , если произошло прерывание).Это не дает вам гарантии того, что ваш поток будет запущен, как только истечет время, или каких-либо других гарантий.
Sleep (0) под Windows еще хуже.В документации сказано «поток освободит оставшуюся часть своего временного интервала, но останется готовым. Обратите внимание, что готовый поток не гарантированно запустится немедленно» .Реальность такова, что в большинстве случаев работает нормально, блокируя где-то от «совсем нет» до 5–10 мс, но в некоторых случаях я видел блок Sleep (0) и в течение 100 мс, что является неприятным случаем, когда это происходит.
Использование QueryPerformanceCounter
вызывает проблемы - просто не делайте этого .В некоторых системах (Windows 7 с недавним процессором) он будет работать просто отлично, поскольку использует надежный HPET, но во многих других системах вы увидите все виды странных эффектов «путешествия во времени» или «обратного времени», которые никто не может объяснить илиотладки.Это потому, что в этих системах результат QPC считывает счетчик TSC, который зависит от частоты процессора.Частота ЦП не является постоянной, и значения TSC в многоядерных / многопроцессорных системах не обязательно должны быть согласованными.
Тогда возникает проблема синхронизации.Два отдельных таймера, даже если тиканье на одной частоте, обязательно станут несинхронизированными (потому что не существует такого понятия, как «один и тот же»).В вашей видеокарте уже есть таймер, который выполняет вертикальную синхронизацию.Использование этого для синхронизации будет означать, что все будет работать, использование другого означает, что в конечном итоге все будет не синхронизировано.Нарушение синхронизации может вообще не иметь никакого эффекта, может нарисовать наполовину законченный кадр или может блокировать один полный кадр, или что-то в этом роде.
Хотя пропуск кадра обычно не так уж и важен (если он всего одини случается редко), в этом случае это то, чего вы можете полностью избежать.