Я хочу задать вопрос о том, как должен осуществляться обмен информацией между частями игрового движка.
Движок разделен на четыре части: логика, данные, пользовательский интерфейс, графика. В начале я сделал этот обмен через флаги. Например, если новый объект добавлен в данные, флаг isNew
в классе объекта будет установлен как true
. И после этого графическая часть движка проверит этот флаг и добавит объект в игровой мир.
Тем не менее, при таком подходе я должен был написать много кода для обработки каждого флага каждого типа объекта.
Я думал об использовании некоторой системы событий, но у меня недостаточно опыта, чтобы понять, будет ли это правильным решением.
Является ли система событий единственным подходящим подходом, или я должен использовать что-то еще?
Я использую Ogre в качестве графического движка, если это имеет значение.
источник
Ответы:
Моя любимая структура игрового движка - это компонентная модель интерфейса и объекта <->, использующая обмен сообщениями для связи практически между всеми частями.
У вас есть несколько интерфейсов для основных частей движка, таких как менеджер сцены, загрузчик ресурсов, аудио, рендер, физика и т. Д.
У меня есть менеджер сцены, отвечающий за все объекты в 3D сцене / мире.
Объект - это очень атомарный класс, содержащий всего несколько вещей, которые являются общими для почти всей вашей сцены. В моем движке класс объекта содержит только положение, вращение, список компонентов и уникальный идентификатор. Идентификатор каждого объекта генерируется статическим int, так что никакие два объекта не будут иметь одинаковые идентификаторы, что позволяет отправлять сообщения объекту по его идентификатору, а не указывать на объект.
Список компонентов на объекте - это то, что дает объектам основные свойства. Например, для чего-то, что вы можете видеть в трехмерном мире, вы бы дали своему объекту компонент рендеринга, который содержит информацию о сетке рендеринга. Если вы хотите, чтобы объект имел физику, вы бы дали ему физический компонент. Если вы хотите, чтобы что-то действовало как камера, добавьте в нее компонент камеры. Список компонентов можно продолжать и продолжать.
Связь между интерфейсами, объектами и компонентами является ключевой. В моем движке у меня есть общий класс сообщений, который содержит только уникальный идентификатор и идентификатор типа сообщения. Уникальный идентификатор - это идентификатор объекта, к которому вы хотите отправить сообщение, а идентификатор типа сообщения используется объектом, получающим сообщение, чтобы он знал, к какому типу это относится.
Объекты могут обрабатывать сообщение, если они нуждаются, и они могут передавать сообщение каждому из своих компонентов, и компоненты часто будут делать важные вещи с сообщением. Например, если вы хотите изменить положение объекта и отправить ему сообщение SetPosition, объект может обновить свою переменную положения, когда он получает сообщение, но компоненту рендеринга может потребоваться сообщение, чтобы обновить положение сетки рендеринга, и физическому компоненту может потребоваться сообщение для обновления положения физического тела.
Вот очень простая компоновка менеджера сцены, объекта и компонента, а также потока сообщений, которую я написал примерно за час, написанная на C ++. При запуске он устанавливает позицию на объекте, и сообщение проходит через компонент рендеринга, а затем извлекает позицию из объекта. Наслаждайтесь!
Кроме того , я написал C # версию и Scala версию кода ниже для тех, кто может быть свободно в тех , а не C ++.
источник
Я думаю, что это лучший способ использовать Scene Manager и интерфейсы. Реализован ли обмен сообщениями, но я бы использовал его как вторичный подход. Обмен сообщениями хорош для связи между потоками. Используйте абстракцию (интерфейсы) везде, где можете.
Я не знаю много об Огре, поэтому я говорю в целом.
По сути, у вас есть основной игровой цикл. Он получает входные сигналы, вычисляет AI (от простого движения до сложного AI и игровой логики), загружает ресурсы [и т. Д.] И отображает текущее состояние. Это базовый пример, поэтому вы можете разделить движок на эти части (InputManager, AIManager, ResourceManager, RenderManager). И у вас должен быть SceneManager, который содержит все объекты, присутствующие в игре.
У каждой из этих частей и их частей есть интерфейсы. Поэтому постарайтесь организовать эти части, чтобы сделать их и только свою работу. Они должны использовать части, которые взаимодействуют внутри с целью их родительской части. Таким образом, вы не попадете в замешательство без шанса развернуться без полного переписывания.
PS, если вы используете C ++, подумайте об использовании шаблона RAII
источник