Страницы

Поиск по вопросам

понедельник, 13 апреля 2020 г.

Игровой цикл

#qt

                    
Делаю кроссплатформенную игру с использованием Qt (из Линукса). Именно Qt выбрал,
потому что в перспективе понадобится графический интерфейс для всяких редакторов, а
также он предустановлен практически во все Linux'ы.
Пробовал использовать стандартный цикл QApplication::exec() и сделать таймер с нулевым
интервалом. Но всё это сильно дёргалось, хотя в полноэкранном режиме было ещё нормально.
Вот код:
QApplication app;
QTimer t;
t.setSingleShot(false);
t.start(0);
app.exec();

Потом попробовал сделать свой бесконечный цикл, вызывая processEvents, а после него
обновляя игру. Стало получше, но всё равно иногда дёргается в оконном режиме. Выдаёт
FPS от 50 до 70, хотя в Windows версии на WinAPI было больше 200. Код:
while(running)
{
    QApplication::processEvents();
    engine->Step();
}

Код, который я пробовал на WinAPI, когда ещё не перешёл на Linux:
while(GetMessage(...))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    engine->Step();
}

Вроде то же самое, что и на Qt, но на Qt тормозит, а на WinAPI нет. Хотя эксперимент
был не совсем чистым, так FPS на WinAPI я замерял на Windows, а FPS на Qt я замерял
в Linux.    


Ответы

Ответ 1



Обычно пишут для каждой платформы пачку платформозависимых файлов, которые обрабатывают ввод, собирают информацию о системе, инициализируют отдельные потоки для звука и приводят это все к форме принятой в движке. Затем где-нибудь в одном из файлов для каждой системы вставляют: int main(int argc, char *argv[]) { core.init(); while(1) //Специальная олимпиада открыта вдруг for(;;) быстрее { core.drawFrame(); } return 0; //should never get here } При этом сам кросс-платформенный код отрисовки инкапсулирован в core. Сам этот метод может быть достаточно сложен. Там могут быть счетчики FPS, работа с вводом , обработка AI, столкновений, логики и лишь в конце рендеринг/очистка памяти. При этом рендеринг осуществляется разными техниками для разных объектов/материалов в несколько проходов с разными шейдерами в разные буферы. По поводу редакторов для игры, очень сомнительно что ему реально нужна кросс-платформенность и непонятно что он будет делать. В лучшем случае комбинировать меши выгруженные из нормального 3D редактора в уровень. Но если игра маленькая это можно сделать и в любом другом 3D редакторе. А файл с описанием уровня/активов просто автоматически сгенерировать скриптом. По поводу core.init() это тоже зависит от реализации. Если игра маленькая она просто загружает все что можно загрузить. Если большая то грузится основной GUI, шейдеры, метафайл с описанием остальных активов, пользовательский кэш, загрузочный экран/заставка и.т.д. Геометрия и текстуры уровня же подгружаются отдельно по сигналу от GUI из обработчика ввода внутри drawFrame если пользователь решил таки загрузить очередной уровнеь. По поводу скачков FPS то непонятно каким образом вы его считаете. Взвешенное(weighted) скользящее среднее по 20ке последних тиков вроде неплохой метод. http://en.wikipedia.org/wiki/Moving_average P.S.Код Doom 3, на который я ориентируюсь сделан таким образом, если смотреть на то как он справляется с покрытием нескольких платформ.

Ответ 2



Оказалось, что дело не в главном цикле Qt. Попробовал перекомпилировать под Windows, где у меня уже был реализован WinAPI-вариант, там тот же самый низкий FPS. Сделал через XLib на Linux'е - вроде чуть плавнее, но FPS вроде не увеличился. Единственное что изменилось при портировании и не было проверено - это компилятор MSVC сменился на g++. Я пробовал также llvm-g++ и clang++, но на производительности никак не отражается. Да и дебаг от релиза по производительности ничем почти не отличается, а в студии сильно отличалось. Вообще не могу понять, что же такое произошло во время портирования. Были подозрения на некоторые изменения, но я попробовал их повторить в старой версии движка в студии и они никак не повлияли на высокий FPS. Так что буду учиться пользоваться Linux'овским профайлером. Ещё попробую создать отладочный контекст OpenGL и задействовать GL_AMD_debug_output. Может он что-нибудь скажет. Если нет, то попробую скомпилировать проект в студии.

Комментариев нет:

Отправить комментарий