Кодирование на самом деле не так сложно . Сложная часть заключается в написании кода, который имеет смысл, читабелен и понятен. Поэтому я хочу найти лучшего разработчика и создать надежную архитектуру.
Поэтому я хочу создать архитектуру для неигровых персонажей в видеоигре. Это стратегия в реальном времени, такая как Starcraft, Age of Empires, Command & Conquers и т. Д. И т. Д. Так что у меня будут разные виды NPC. NPC может иметь один ко многим способностям (методы) этим: Build()
, Farm()
и Attack()
.
Примеры:
рабочий может Build()
и Farm()
воин может Attack()
гражданин может Build()
, Farm()
а Attack()
рыбак может Farm()
иAttack()
Я надеюсь, что пока все ясно.
Так что теперь у меня есть типы NPC и их способности. Но давайте перейдем к техническому / программному аспекту.
Какой будет хорошая программная архитектура для моих разных типов NPC?
Хорошо, я мог бы иметь базовый класс. На самом деле я думаю, что это хороший способ придерживаться принципа СУХОЙ . Таким образом, у меня могут быть методы, как WalkTo(x,y)
в моем базовом классе, так как каждый NPC сможет двигаться. Но теперь давайте подойдем к настоящей проблеме. Где я могу реализовать свои способности? (помните: Build()
, Farm()
а Attack()
)
Поскольку способности будут состоять из одной и той же логики, было бы досадно / нарушать принцип СУХОГО, чтобы реализовать их для каждого NPC (Рабочий, Воин, ..).
Хорошо, я мог бы реализовать способности в базовом классе. Это потребует какой - то логики , которая проверяет , если NPC может использовать способность X. IsBuilder
, CanBuild
.. Я думаю, ясно , что я хочу выразить.
Но я не очень хорошо себя чувствую с этой идеей. Это звучит как раздутый базовый класс со слишком большой функциональностью.
Я использую C # в качестве языка программирования. Так что множественное наследование здесь не вариант. Означает: наличие дополнительных базовых классов вроде Fisherman : Farmer, Attacker
не сработает.
источник
Ответы:
Композиция и наследование интерфейса - это обычные альтернативы классическому множественному наследованию.
Все, что вы описали выше, начинающееся со слова «может», - это возможность, которая может быть представлена интерфейсом, например
ICanBuild
, илиICanFarm
. Вы можете наследовать столько интерфейсов, сколько считаете нужным.Вы можете передавать в «общие» строительные и сельскохозяйственные объекты через конструктора вашего класса. Вот где приходит композиция.
источник
ICanBuild
. То, что у вас также есть инструменты для сборки, имеет второстепенное значение в иерархии объектов.Как упоминали другие авторы, компонентная архитектура может быть решением этой проблемы.
В этом случае расширьте функцию обновления, чтобы реализовать любую функциональность, которую должен иметь NPC.
Повторение контейнера компонента и обновление каждого компонента позволяет применять определенные функциональные возможности каждого компонента.
Поскольку каждый тип объекта необходим, вы можете использовать некоторую форму фабричного шаблона для создания отдельных типов, которые вы хотите.
Я всегда сталкиваюсь с проблемами, поскольку компоненты становятся все более и более сложными. Низкая сложность компонентов (одна обязанность) может помочь решить эту проблему.
источник
Если вы определяете интерфейсы как,
ICanBuild
то ваша игровая система должна проверять каждого NPC по типу, который обычно не одобряется в ООП. Например:if (npc is ICanBuild)
.Вам лучше с:
Затем:
... или, конечно, вы можете использовать несколько разных архитектур, например, какой-то специфичный для предметной области язык в форме плавного интерфейса для определения различных типов NPC и т. д., где вы создаете типы NPC, комбинируя различные варианты поведения:
Строитель NPC может реализовать функцию,
DefaultWalkBehavior
которая может быть переопределена в случае NPC, который летает, но не может ходить и т. Д.источник
if(npc is ICanBuild)
иif(npc.CanBuild)
. Даже когда я предпочел быnpc.CanBuild
выход из моего нынешнего отношения.Я бы поместил все способности в отдельные классы, которые наследуются от Способностей. Затем в классе типов юнитов есть список способностей и других вещей, таких как атака, защита, максимальное здоровье и т. Д. Также есть класс юнитов, который имеет текущее здоровье, местоположение и т. Д. И имеет тип юнита в качестве переменной-члена.
Определите все типы модулей в конфигурационном файле или базе данных, а не жестко их кодируйте.
Тогда дизайнер уровней может легко настроить способности и характеристики типов юнитов без перекомпиляции игры, а также люди могут писать моды для игры.
источник