Каков правильный объектно-ориентированный подход к дизайну классов в разработке игр?

31

Я занимаюсь разработкой 2D спрайтовой игры для Windows 7 Phone с использованием XNA. Обучение и учебные пособия, доступные для него, довольно полезны, но проблема, с которой я сталкиваюсь, заключается в том, что каждый из них по-своему подходит к дизайну своего класса, и код не очень хорошо продуман. В результате мне было трудно понять, какие обязанности я должен дать конкретному классу.

Например, у меня может быть базовый класс спрайтов, BaseSpriteкоторый знает, как рисовать себя, проверять наличие коллизий и т. Д. Затем у меня может быть AnimatedSpriteкласс, который будет знать, как перемещаться по его листу спрайтов, ExplodingSpriteклассу и так далее. Эта техника продемонстрирована на примере Space Invaders в материалах Windows 7 Phone Jumpstart Session 2 .

В качестве альтернативы, я мог бы вместо этого поместить большую часть рендеринга и запуска игры в GameScreenкласс; этот класс и его производные классы ведут себя больше как формы или веб-страницы с точки зрения своих обязанностей. Классы Sprite - это более простые контейнеры с гораздо меньшей логикой.

Эта техника используется в игре Alien Sprite для Windows 7 Phone Training Kit и в других примерах менеджера состояний игры.

Каков правильный объектно-ориентированный подход к дизайну классов в разработке игр?

Джош Э
источник

Ответы:

26

Я использую более компонентно-ориентированный подход, где у вас будет класс Sprite, в котором есть такие компоненты, как Visual, Collision, Animation, Input и т. Д. При таком подходе у меня нет глубокой иерархии классов (что хорошо) ,

Для получения дополнительной информации о компонентно-ориентированном дизайне см. Здесь .

thbusch
источник
2
+1 статья, на которую вы ссылались, была фантастической. Я был так сосредоточен на чистом ОО-дизайне, что полностью упустил из виду модель компонента / декоратора.
Джош Э
1
Шаблон компонентов на самом деле не «менее чистый» ОО :)
Srekel
2
Верно. ОО часто приравнивают к наследованию. Но наследование - это только один инструмент, который предлагает ОО, а композиция - другое.
haffax
Именно так. Я должен был быть более точным в моей формулировке; Я имел в виду, что я сосредоточился на наследовании ОО вместо того, чтобы думать о шаблонах проектирования ОО / других аспектах ОО, которые могли бы помочь мне достичь того, чего я хотел.
Джош Э
Хотя подход, основанный на комопозиции, довольно очевиден и часто используется, мне еще предстоит найти решение для сохранения переносимости компонента рендеринга. Любые намеки будут великолепны.
Андреас
11

В играх шаблон компонентов является распространенным решением.

необычайно щедрый
источник
Это еще одна фантастическая статья, которую стоит прочитать.
Джош Э
1
Отличная статья!
Кевин
6

В SOLID принципы применяются так же для дизайна игры кода , как в любой другой профессии , - по крайней мере , пока вы не дойдете до оптимизируют, так что я хотел бы использовать свой первый пример в качестве отправной точки.

Я бы пошел дальше, потому что BaseSprite звучит так, как будто имеет тенденцию становиться мегаклассом. Принцип единой ответственности предписывает, что столкновение, рендеринг и навигация должны обрабатываться компонентами, а не отдельными записями в иерархии классов. Класс владения всеми этими компонентами должен обрабатывать только толкающие мировые позиции между ними.

tenpn
источник
5

Для последних нескольких проектов я больше склонялся к стилю MVC.

Сначала мы не были уверены, что это сработает, но сработало идеально.

модель

Объекты данных. Просто чистые данные. Нет поведения, нет рендеринга.

Менеджер данных. Просто обработка «списков» объектов данных. (Может также быть улучшено для поддержки объединения.)

Посмотреть

Мы называем их рендерерами. Для каждого типа объекта данных существует средство визуализации. При вызове с менеджером он будет отображать все объекты в этом списке.

контроллер

То же, что и рендеры, но контролирует поведение.

пример

У ShipManager есть список кораблей. ShipController будет перемещать корабли в соответствии с их состоянием. ShipRenderer будет отображать корабли в соответствии с их состоянием.

Зачем

Таким образом, взгляд и логика строго разделены. Это делает перенос на новую платформу довольно простым. Оптимизация размещения данных внутри XxxManager также очень проста.

Andreas
источник
2
Я голосую за вас, потому что мне надоело видеть более или менее голое «Использование MVC» в качестве приемлемого ответа. Если вы разрабатываете на любой современной платформе, вы уже используете MVC на нескольких уровнях. Это не конкретный ответ и не очень хороший ответ, потому что на самом деле он не говорит людям, как структурировать классы, что зависит от задачи / домена. Вы просто получаете много людей, пишущих "класс Modal ...; класс View ...; класс Controller ..." MVC - это шаблон с большим количеством хороших объяснительных возможностей высокого уровня, когда речь идет о существующем коде. Это не шаблон с хорошей планировочной силой.
4
@ Джо, я понял твою точку зрения, но нашел свой выбор слов ненужным грубым. Я просто объяснил, как мы это делаем. Поскольку выбор архитектуры более высокого уровня делает выбор дизайна более низкого уровня устаревшим, я считаю это правильным ответом.
Андреас