Я просто пытаюсь научиться программировать несколько вещей, и игровой цикл является одним из них.
Этот игровой цикл обрабатывает только сообщения 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
Игровой цикл WIN32 работает медленно, не поддерживает частоту 60 Гц или 30 Гц. Что делать? ⇐ C++
Программы на C++. Форум разработчиков
1719910866
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);
}
Подробнее здесь: [url]https://stackoverflow.com/questions/78673961/win32-game-loop-is-slow-cant-handle-60hz-or-30hz-what-to-do[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия