У меня возник вопрос об игровой архитектуре: как лучше связать друг с другом разные компоненты?
Я действительно извиняюсь, если этот вопрос уже задавался миллион раз, но я не могу найти ничего с той информацией, которую я ищу.
Я пытался создать игру с нуля (C ++, если это имеет значение) и наблюдал за некоторым вдохновляющим игровым программным обеспечением с открытым исходным кодом (Super Maryo Chronicles, OpenTTD и другие). Я заметил, что во многих игровых проектах повсеместно используются глобальные экземпляры и / или синглтоны (для таких вещей, как очереди рендеринга, менеджеры сущностей, менеджеры видео и т. Д.). Я пытаюсь избегать глобальных экземпляров и синглетонов и создавать движок, который настолько слабо связан, насколько возможно, но я сталкиваюсь с некоторыми препятствиями, которые связаны с моей неопытностью в эффективном дизайне. (Часть мотивации для этого проекта состоит в том, чтобы заняться этим :))
Я построил дизайн, в котором у меня есть один главный GameCore
объект, члены которого аналогичны глобальным экземплярам, которые я вижу в других проектах (т. Е. У него есть менеджер ввода, видео менеджер, GameStage
объект, который контролирует все сущности и игру). за какой этап загружен в данный момент и т. д.). Проблема в том, что, поскольку в GameCore
объекте все централизовано, у разных компонентов нет простого способа взаимодействия друг с другом.
Например, если взглянуть на Super Maryo Chronicles, всякий раз, когда компонент игры должен обмениваться данными с другим компонентом (т. Е. Вражеский объект хочет добавить себя в очередь рендеринга, которая будет отрисовываться на этапе рендеринга), он просто обращается к глобальный экземпляр.
Мне нужно, чтобы мои игровые объекты передавали соответствующую информацию обратно GameCore
объекту, чтобы GameCore
объект мог передавать эту информацию другим компонентам системы, которые в ней нуждаются (т. Е. Для вышеуказанной ситуации, каждому вражескому объекту). будет передавать свою информацию рендеринга обратно GameStage
объекту, который соберет все это и передаст его обратно GameCore
, что, в свою очередь, передаст ее диспетчеру видео для рендеринга). Это похоже на действительно ужасный дизайн как таковой, и я пытался придумать решение этой проблемы. Мои мысли о возможных конструкциях:
- Глобальные экземпляры (дизайн Super Maryo Chronicles, OpenTTD и т. Д.)
- Наличие
GameCore
объекта в качестве посредника, через которого все объекты взаимодействуют (текущий дизайн описан выше) - Присвойте указатели компонентов всем другим компонентам, с которыми им нужно будет общаться (т. Е. В приведенном выше примере с Maryo вражеский класс будет иметь указатель на видеообъект, с которым ему нужно общаться)
- Разбейте игру на подсистемы - например, в
GameCore
объекте есть управляющие объекты, которые управляют связью между объектами в их подсистеме. - (Другие опции? ....)
Я полагаю, что вариант 4, представленный выше, является лучшим решением, но у меня возникли некоторые проблемы при его разработке ... возможно, потому, что я думал о проектах, которые я видел, которые используют глобальные переменные. Такое ощущение, что я беру ту же проблему, которая существует в моем текущем проекте, и копирую ее в каждой подсистеме, только в меньшем масштабе. Например, GameStage
объект, описанный выше, является своего рода попыткой сделать это, но GameCore
объект все еще участвует в процессе.
Кто-нибудь может предложить какие-либо советы по дизайну здесь?
Благодарность!