Category: игры

Category was added automatically. Read all entries about "игры".

flow

Про GUI, игры и реальное время

В коде игр есть такая прекрасная штука - игровой цикл (game loop).

Для типичной игры он выглядит так:

1. Узнать системное время и новый input со стороны клавиатуры, мыши, геймпадов, etc.
2. Выполнить шаг симуляции игрового мира - логики, физики, AI, GUI/HUD и других подсистем.
3. Обновить картинку и звук.
4. Перейти к шагу 1.

Элементы 1-3, а также их фрагменты, часто обозначают словом таймтик (timetick): таймтик физики, таймтик рендерера. Симуляция может учитывать не только события между двумя срезами времени, но и глобальные затраты ресурсов. Например, когда бот в трёхмерном шутере выбирает новую позицию для стрельбы, то на "посмотреть-посмотреть-подумать" могут потребоваться заметные вычисления. Чтобы не происходило фриза (freeze) от одновременно задумавшихся ботов и частота обновления картинки оставалась в пределах нормы - ботов учат действовать одновременно, но думать по очереди.

Код игрового движка часто обновляется или заменяется между играми. Программисты пишут game loop первый, второй, десятый раз. Опытные геймдевелоперы способны спроектировать game loop левой ногой, на непонятом ими языке программирования, и результат будет хорошо работать (пример - исходники Doom 3).

Так делаются игры. И так должны делаться приложения. Ввод-обработка-вывод-повторить это основа любого программного обеспечения, под разными именами - game loop, REPL. Фоновые задачи в отдельных тредах и обработчики запросов на сервере - то же самое, с вводом/выводом в промежуточной "машинной" форме.

Однако, loop во многих системах GUI выглядит иначе. Вам предлагают множество мелких объектов, которые связаны через обработку сообщений, которые придут сюда, если их не поймают в чужом коде вот здесь, но для accelerator'ов они пойдут иначе, в в случае модального диалога всё совсем не так. Взаимодействие по принципу "вчера положили асфальт, но сегодня вскрывают для плановой замены труб". У вас есть множество привязок обработчиков и датабайндингов, "что и где", но никто не может ответить на вопрос "когда?". Ошибки, артефакты, фликающие или недорисованные окна, тормоза и странности - а чего вы ещё хотели, если игнорируется время?

Полноценные системы GUI проектируются редко. Обычными людьми, как мы с вами, которые делают это в первый или второй раз. Некоторые проектировались под требования тех ещё времён ("сэкономить 10 килобайт на окно любой ценой"), некоторые проектируются по образу и подобию привычных авторам древних решений. Даже при использовании кроссплатформенных API темпоральные аспекты выполнения кода приложения могут отличаться самым чудесатым образом.

Что делать? Как получить хороший отзывчивый UI приложения в таком бардаке? Решение есть.

Заменить дефолтные механизмы на свой game loop. Даже выделение из бардака сообщений двух таймтиков на "сначала закапывать трубы" и "потом класть асфальт" принесёт пользу, исправит ошибки и ускорит отрисовку интерфейса. Можно на этом остановиться. А можно продолжить, и решить остальные проблемы.

Главное - помните, если в треде вы взаимодействуете с временем пользователя, то для любого клочка кода должны знать его "когда", иначе будете постоянно огребать "невовремя".