Загрузка...
 
Печать

Формы и методы управления игровым движком




Intro

Когда ты справшиваешь кого-либо о том, что собой представляет игровой движок, то часто можно слышать в ответ "3D-рендеринг" или "3D-графика". В принципе, они правы, т.к. большинство современных движков, так или иначе, используются для обработки 3D-рендеринга в играх. В то же время, термин "управление игровым движком" следует воспринимать в более широком смысле. Помимо 3D-рендеринга, игровой движок должен также "организовать" создание игры. Важно всё время помнить об этом, разрабатывая движок. И планировать его так, чтобы в нём было всё необходимое для создания FPS-игры. Среди разработчиков-любителей распространена ошибка, когда они забывают внедрить систему управления движком ещё на ранних стадиях его разработки. Вместо этого, они доводят до ума возможности 3D-рендеринга движка ещё до того, как попытались контролировать его.
Прежде чем отправится дальше, давай определим понятие "управление игровым движком" (Engine control). Точнее, определим, из чего же складывается этот самый контроль движка. Для этой цели мы разделим понятие "управление игровым движком" на 2 отдельных (но взаимосвязанных) аспекта:
  • Процессинг движка (Engine processing)
  • Пользовательский ввод (User input)

Процессинг движка (Engine processing)


Image
Рис.1 Главный цикл игрового приложения (Game loop)


Определяется как совокупность методов и процедур, созданных для того, чтобы контролировать все процессы, которые обрабатывает ("процессит") движок в любой отдельно взятый момент времени1.
Например, большинство движков работают с использованием так называемого игрового цикла (Game loop; см. Рис. 1). На Рис. 1 изображена упрощённая схема и часть пунктов здесь просто не представлено, но присутствуют основные компоненты. Игровой цикл - это просто продолжающийся цикл, который выполняется снова и снова до тех пор, пока не будет прерван (обычно это происходит при выходе пользователя из игры и закрытии приложения). Часто такие циклы выполняют более 30 проходов (= итераций) за секунду, что определяется фреймрейтом (framerate, частота смены кадровg) игры или по-другому - числом кадров в секунду (frames per second; отсюда аббревиатура fps). Если твой игровой цикл работает на скорости 40 fps, тогда теоретически каждый кадр занимает 2,5% от одной секунды, что соответсвует 25 милисекундам (мс) на кадр. Другими словами, игровой цикл совершает одно полное прохождение каждые 25 мс. Любой нормальный движок проделывает уйму работы за это время (см. Рис.1). Вот здесь-то контроль процессинга движка и выходит на первый план. Раз уж у нас в каждом кадре столь ограничено время, то необходимо расходовать его с умом. По сути, весь контроль процессинга нашего движка сводится к управлению этими 25 милисекундами и определению, какой отрезок времени будет выделен каждому компоненту.
Допустим, пользовательский ввод, сеть, звук и рендеринг вместе взятые занимают 18 мс. В таом случае у нас остаётся всего 7 мс для процессинга, специфичного для приложения (application-specific processing). Взять хотя бы игровую логику, которая также может содержать времязатратные операции, например систему искусственного интеллекта. Мы, конечно, проникли в эту тему несколько глубже, чем следовало бы для данной статьи. В любом случае, тебе важно помнить об этом, например для того, чтобы ты понимал некоторые девелоперские решения, которые мы реализуем позднее. Вот лишь некоторые из них:
  • Ограничение числа итераций детекции столкновений (collision detection);
  • Прекращение процессинга сетевых сообщений (network message processing) по истечении определённого времени;
  • Ограничение размера нашй иерархии сцены (scene hierarhy).
На данном этапе мы уже имеем более чёткое представление о контроле процессинга движка. Исходя из вышеизложенного материала, мы создадим систему, которая сможет указывать, как компоненты из Рис.1 будут работать вместе, чтобы обработать один аспект симуляции, более известный как стейт (англ. "state" - состояние). Подробнее о них читай здесь: Стейты игры и процессы (Game States and Processes). Эту систему часто называют машина конечных состояний (Finite-State Machine, далее - FSMg) или т.н. "конечный автомат". Этот абстрактный термин широко используется во многих отраслях программирования.

Машины конечных сосотяний (Finite-State Machines)


Image
Рис.2 Упрощённая FSM гипотетического животного


Мы будем использовать простую форму FSM для управления различными стейтами, которые нашему движку может понадобиться обработать в опеределённый момент времени. Прежде чем мы применим эту хитрую концепцию к нашему случаю, кратко обсудим FSM. На самом деле это очень простая концепция, если разбить её название на отдельные слова и рассмотреть каждое из них по отдельности.
Первым идёт слово finite (англ. "конечный, ограниченый"), который чаще всего означает ограниченый. В терминах FSM это звучит как имеющий определённое число стейтов. Вообще, теоретически вполне возможно, но на практике практически невозможно существование неограниченного числа стейтов. Мы можем заключить, что все машины состояний ограничены и имеют ограниченное число стейтов, зависящее от того, сколько их назначил программер. Очень скоро мы рассмотрим наглядный пример.
Второе слово state (англ. "стейт, состояние"). В программировании стейт - это текущая диспозиция (состояние) и поведение данного события (entity) в данный момент времени. Например, ты можешь вызвать стейт, в котором ты сейчас находишься (т.е. стейт чтения). Когда ты идёшь на прогулку, ты можешь назвать это стейтом прогулки (walking state). Позднее ты сядешь за стол, чтобы перекусить. Всё это действо ты также можешь назвать стейтом приёма пищи (eating state). Ещё более простым примером может служить обычный выключатель на стене, который имеет всего 2 стейта: вкл и выкл. В данный момент времени выключатель может находится только в одном из двух стейтов.
Третье слово machine (англ. "машина"), которое просто может быть определено как система. Ведь, елси подумать, любая машина - это ни что иное как система. Она получает ввод от пользователя (оператора), обрабатывает его и выдаёт результат. Взять, к примеру, двигатель автомобиля. Это машина, которую также можно назвать системой, так как он получает ввод (топливо), обрабатывает его (сжигает) и выдаёт результат (энергию).
Если быть более точным, наша FSM это на самом деле динамическая машина, так как она может изменять способы своей обработки, что, в свою очередь, связано со способностью сменять стейты. В то время как двигатель автомобиля во время своей работы имеет всего 1 стейт (т.к. в данный мометн времени он принимает только 1 вид ввода (топливо), обрабатывает его и выдаёт единственный вид результата (энергию)), то наша FSM в этом плане больше похожа на слайд-проектор. В то время, как сам слайд-проектор остаётся неизменным, его ввод (слайды), процессинг (в какой-то степени) и выводимый результат могут изменяться. Ты можешь сменить слайд (ввод), что приведёт к изменению поведения света, проходящего через слайд (процессинг) и даст различные изображения, спроектированные на экране (вывод).
Таким образом можно заключить, что FSM - это система, которая может динамически изменять свои ввод, процессинг и вывод, основываясь на ограниченном наборе предопределённых стейтов (состояний).
Рис.2 показывает упрощённую FSM гипотетического животного. У животного есть своя внутренняя FSM, которая может сменять стейты на любой из представленных. Вместе с тем, в данный момент времени активным может быть только один стейт. При установке определённого стейта животное ведёт себя соответственно этому стейту. В этом примере нас интересуют всего 2 вопроса:
  • Как FSM сменяет стейты?
  • Как мы можем это использовать при создании игрового движка?
Ответы, на удивление, очень просты. Любая FSM сменяет свои стейты двумя способами: автоматически и в ручном режиме. При автоматическом режиме FSM сменяет стейты через направление, указанное в текущем стейте. В нашем примере (из Рис.2) в стейте "охотиться" может содержаться инструкция, которая информирует FSM об автоматическом переходе на стейт "есть" всякий раз, когда животное поймает свою добычу. При ручном режиме пользователь вмешивается в работу FSM и выбирает желаемый стейт. Возвращаясь к нашему примеру с животным, после того как оно преследовало добычу какое-то время, хищник очень устал и принуждает свою FSM сменить стейт на "спать".
Остаётся последний вопрос: как мы можем использовать это в нашем движке? Для этого создают систему, которая позволяет игрокодеру (пользователю движка) определять для игры один или несколько стейтов. Затем система будет проверять, что движок обрабатывает нужный стейт в нужное время, параллельно предоставляя игрокодеру возможность переключаться между этими стейтами по мере необходимости. Это обезопасит нас от ситуации, когда движок затрачивает ценное время на процессинг фичей, которые в данный момент времени даже не используются Например, в стейте главного меню можно не задействовать 3D-рендеринг.

Пользовательский ввод (User input)

  • Также является формой контроля движка, так как позволяет пользователю контролировать в некоторой степени работу движка и в гораздо большей степени - работу игры, созданной на основе этого движка.
И ответственнен за это именно движок. Самый популярный метод его реализации - применить готовые интерфейсы Directlnput.

Источники


1. Young V. "Programming a multiplayer FPS in DirectX", Charles River Media Inc, 2005


Последние изменения страницы Понедельник 27 / Июнь, 2022 09:27:15 MSK

Последние комментарии wiki

No records to display

Search Wiki Page

Точное совпадение

Категории

|--> C#
|--> C++