Игровой цикл WIN32 работает медленно, не поддерживает частоту 60 Гц или 30 Гц. Что делать?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Игровой цикл WIN32 работает медленно, не поддерживает частоту 60 Гц или 30 Гц. Что делать?

Сообщение Anonymous »

Я просто пытаюсь научиться программировать несколько вещей, и игровой цикл является одним из них.
Этот игровой цикл обрабатывает только сообщения Windows, но он даже не может обрабатывать 30 кадров в секунду.
Это верно и в том случае, если обработка сообщения выполняется только один раз за цикл, заменяя WHILE на IF.
Я использую QueryPerformanceCounter() функция, чтобы получить количество тиков по 100 нс до завершения работы и после, вычитая их, чтобы получить использованное время. Время цикла составляет 100 нс * 166666 * 2 = 0,0333332 с.
Булевое значение timeExceeded устанавливается, если время ожидания положительное, что указывает на то, что используемое время превышает запланированное время цикла.
Что делать?
#include

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// windows class information
static const wchar_t class_name[] = L"Test";
WNDCLASS wc{ };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = class_name;
if (!RegisterClassW(&wc))
return 0;

// Get correct windows size based on disered client area
RECT client_rect;
client_rect.left = 0;
client_rect.top = 0;
client_rect.right = 800;
client_rect.bottom = 600;
if (!AdjustWindowRect(&client_rect, WS_OVERLAPPEDWINDOW, FALSE))
return 0;

// create windows
HWND hwnd = CreateWindowEx(
WS_EX_OVERLAPPEDWINDOW, class_name, L"Test",
WS_CAPTION | WS_SYSMENU | WS_OVERLAPPED,
100, 100, -client_rect.left + client_rect.right, -client_rect.top + client_rect.bottom,
0, 0, hInstance, 0
);
if (hwnd == 0)
return 0;

// Show Window
ShowWindow(hwnd, SW_SHOWNORMAL);

// Timer & setup
LARGE_INTEGER frequency;
if (!QueryPerformanceFrequency(&frequency))
return 0;
if (frequency.QuadPart != 10000000LL)
return 0;

HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
if (hTimer == 0)
return 0;

// timer data
LARGE_INTEGER start_time;
LARGE_INTEGER end_time;
LARGE_INTEGER rest_time;
LARGE_INTEGER loop_time;
loop_time.QuadPart = -166666LL*2; // loop time

bool timeExceeded = false; // does time exceeds loop time

// message loop data
MSG msg = { };
bool running = true;

while (running)
{
// measure time
if (!QueryPerformanceCounter(&start_time))
break;

// process messages
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
running = false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}

// other work

// Get elapsed time and wait for 30hz - elapsed time
if (!QueryPerformanceCounter(&end_time))
break;

rest_time.QuadPart = loop_time.QuadPart + (end_time.QuadPart - start_time.QuadPart);
if (rest_time.QuadPart >= 0)
{
timeExceeded = true;
continue;
}
if (!SetWaitableTimer(hTimer, &rest_time, 0, 0, 0, 0))
break;

if (WaitForSingleObject(hTimer, INFINITE) != 0)
break;
}

// clean up
CloseHandle(hTimer);

return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


Подробнее здесь: https://stackoverflow.com/questions/786 ... what-to-do
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»