Печать C32 win32 на консоль с фиксированными временными шагами
Я пытаюсь создать функцию, которая позволит мне вводить нужные кадры в секунду и максимальное количество кадров, а затем использовать функцию "cout" для консоли на фиксированных временных шагах. Я использую Sleep(), чтобы избежать занятого ожидания. Кажется, я заставляю программу спать дольше, чем нужно, потому что она продолжает останавливаться на команде сна, я думаю. ты можешь помочь мне с этим? У меня проблемы с пониманием времени, особенно на окнах.
В конечном счете, я, вероятно, буду использовать этот метод хронометража для определения времени и анимации простой игры, например, понга, или даже простой программы с объектами, которые могут ускоряться. Я думаю, что я уже понимаю GDI и васапи достаточно для воспроизведения звука и отображения цвета на экране, так что теперь мне нужно понять время. Я долго искал, прежде чем задавать этот вопрос в интернете, и я уверен, что что-то упустил, но не могу понять, как это сделать:(вот код:
#include <windows.h>
#include <iostream>
// in this program i am trying to make a simple function that prints frame: and the number frame in between fixed time intervals
// i am trying to make it so that it doesn't do busy waiting
using namespace std;
void frame(LARGE_INTEGER& T, LARGE_INTEGER& T3, LARGE_INTEGER& DELT,LARGE_INTEGER& DESI, double& framepersec,unsigned long long& count,unsigned long long& maxcount,bool& on, LARGE_INTEGER& mili)
{
QueryPerformanceCounter(&T3); // seccond measurement
DELT.QuadPart = &T3.QuadPart - &T.QuadPart; // getting the ticks between the time measurements
if(DELT.QuadPart >= DESI.QuadPart) {count++; cout << "frame: " << count << " !" << endl; T.QuadPart = T3.QuadPart; } // adding to the count by just one frame (this may cause problems if more than one passes)
if(count > maxcount) {on = false;} // turning off the loop
else {DESI.QuadPart = T.QuadPart + DESI.QuadPart;//(long long)framepersec; // setting the stop tick
unsigned long long sleep = (( DESI.QuadPart - DELT.QuadPart) / mili.QuadPart);
cout << sleep << endl;
Sleep(sleep);} // sleeping to avoid busy waiting
}
int main()
{
LARGE_INTEGER T1, T2, Freq, Delta, desired, mil;
bool loopon = true; // keeps the loop flowing until max frames has been reached
QueryPerformanceFrequency(&Freq); // getting num of updates per second
mil.QuadPart = Freq.QuadPart / 1000; // getting the number clock updates that occur in a millisecond
double framespersec; // the number of clock updates that occur per target frame
unsigned long long framecount,maxcount; //to stop the program after a certain amount of frames
framecount = 0;
cout << "Hello world! enter the amount of frames per second : " << endl;
cin >> framespersec;
cout << "you entered: " << framespersec << " ! how many max frames?" << endl;
cin >> maxcount;
cout << "you entered: " << maxcount << " ! now doing the frames !!!" << endl;
desired.QuadPart = (Freq.QuadPart / framespersec);
while(loopon == true) {
frame(T1, T2, Delta, desired, framespersec, framecount, maxcount,loopon, mil);
}
cout << "all frames are done!" << endl;
return 0;
}
2 ответа
Время, в течение которого вы спите, ограничено частотой системных часов. Частота по умолчанию равна 64 Гц, поэтому вы в конечном итоге увидите сны с шагом 16 мс. Любой сон менее 16 мс будет длиться не менее 16 мс - он может быть дольше в зависимости от загрузки процессора. Аналогично, сон в 20 мс, вероятно, будет округлен до 32 мс.
Вы можете изменить этот период, вызвав timeBeginPeriod(...) и timeEndPeriod(...), что может повысить точность сна до 1 мс. Если вы посмотрите на мультимедийные приложения, такие как VLC Player, вы увидите, что они используют эти функции для получения надежной синхронизации кадров. Обратите внимание, что это изменяет частоту планирования всей системы, что влияет на время автономной работы ноутбуков.
Дополнительная информация: http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298%28v=vs.85%29.aspx
Таймеры ожидания более точны, чем Sleep
, а также лучше интегрировать с циклом сообщений GUI (заменить GetMessage
с MsgWaitForMultipleObjects
). Я успешно использовал их для синхронизации графики раньше.
Они не дадут вам высокой точности, например, для управления последовательным или сетевым выходом с точностью до миллисекунды, но обновления пользовательского интерфейса в любом случае ограничены VSYNC.