Я делаю небольшую гусеницу в космосе, и мне хотелось бы услышать несколько советов о том, как сделать бэкэнд двигателя более приятным. По сути, в настоящее время все основано на куче менеджеров:
- BackgroundManager: есть
AddBackground(image, parallax)
метод создания крутых фоновых эффектов. - ConfigManager: читает / создает файл конфигурации, а также содержит данные, считанные из этого файла конфигурации.
- DrawManager: имеет
Draw(sprite)
метод для рисования материала на экране, и тому подобноеSetView(view)
,GetView()
и т. Д. - EntityManager: содержит все активные сущности и имеет методы для добавления, удаления и поиска сущностей.
- DungeonManager (на самом деле называется GridManager, но это для простоты): имеет такие методы, как
GenerateDungeon()
,PlaceEnemies()
иPlaceFinish()
т. Д.
Сейчас я даже не на полпути перечисляю всех своих менеджеров, поэтому я думаю, что это должно измениться. Моя игра также основана на экранах, что делает ее более раздражающей, потому что мне не нужна половина вещей, которыми управляют мои менеджеры, например, главное меню (мне не нужны физики / сущности / подземелья в моем главном меню) !)
Теперь я подумал о том, чтобы сделать менеджеры не статичными, и дать моему ScreenMainGame экземпляр всех игровых менеджеров. Но это делает вызов / получение чего-либо, связанного с менеджерами, огромным беспорядком ... например, если бы я хотел вытащить свое подземелье из любого места, где его нет ScreenMainGame.Draw()
, я должен был бы сделать это ...
((ScreenMainGame)ScreenManager.CurrentScreen).GridManager.Draw()
Это действительно некрасиво.
Итак, коллеги-разработчики игр, у кого-нибудь из вас есть идея, как решить эту проблему? Я был бы признателен!
Ответы:
Как насчет компонентного движка ?
У вас будет основной класс с именем
Engine
, который будет хранить списокGameScreens
, который будет содержать списокComponents
.Двигатель имеет
Update
иDraw
метод , и как вызов наGameScreen
«SUpdate
иDraw
методы, которые сами по себе пройти через каждый компонент и вызовUpdate
иDraw
.Представлено так, я согласен, что это звучит как плохой и повторяющийся дизайн. Но поверьте мне, мой код стал намного чище благодаря использованию компонентного подхода, чем со всеми моими старыми классами менеджера .
Также гораздо проще поддерживать такой код, поскольку вы просто проходите большую иерархию классов и вам не нужно искать
BackgroundManager
все специфические фоны. Вы просто естьScrollingBackground
,ParallaxBackground
,StaticBackground
и т.д. , которые все вытекают изBackground
класса.В конечном итоге вы создадите довольно солидный движок, который вы сможете повторно использовать во всех своих проектах со множеством часто используемых компонентов и вспомогательных методов (например,
FrameRateDisplayer
в качестве утилиты отладки,Sprite
класса в качестве базового спрайта с текстурой и методов расширения для векторов и генерация случайных чисел).У вас больше не будет
BackgroundManager
класса, но естьBackground
класс, который будет управлять собой.Когда ваша игра начинается, все, что вам нужно сделать, это в основном:
И это все для кода запуска вашей игры.
Затем для экрана главного меню:
Вы получите общую идею.
Вы также должны сохранить ссылку на
Engine
все вашиGameScreen
классы, чтобы иметь возможность добавлять новые экраны даже внутриGameScreen
класса (например, когда пользователь нажимает кнопку StartGame , находясь внутри вашегоMainMenuScreen
, вы можете перейти кGameplayScreen
).То же самое относится и к
Component
классу: он должен содержать ссылку на своего родителяGameScreen
, чтобы иметь доступ как кEngine
классу, так и к его родителюGameScreen
для добавления новых компонентов (например, вы можете создать класс, связанный с HUD,DrawableButton
который называетсяDrawableText
компонентом иStaticBackground
компонентом).После этого вы даже можете применять другие шаблоны проектирования, например, «шаблон проектирования служб» (не уверен в точном названии), где вы можете хранить различные полезные службы в своем
Engine
классе (вы просто храните списокIService
s и позволяете другим классам добавлять службы самостоятельно. ). Например, я бы оставилCamera2D
компонент над всем моим проектом как сервис, чтобы применить его преобразование при рисовании других компонентов. Это избавляет от необходимости передавать его как параметр везде.В заключение, конечно, могут быть и другие лучшие конструкции для двигателя, но я нашел двигатель, предложенный по этой ссылке, очень элегантным, чрезвычайно легко обслуживаемым и многоразовым. Я лично рекомендовал бы по крайней мере попробовать это.
источник
GameComponent
s и сервисы. Нет необходимости в отдельномEngine
классе.То, что вы хотите сделать, это разделить ваш код на компоненты и сервисы. XNA уже имеет встроенную поддержку для них.
Смотрите эту статью на
GameComponents
и услуги. Затем посмотрите этот ответ об использовании служб в XNA и более общий ответ об услугах на любом языке.источник
То, что они являются статическими или глобальными, не означает, что их всегда нужно загружать / инициализировать. Используйте шаблон Singleton и разрешите менеджерам быть свободными и загружаться снова по требованию.
источник