2008-10-14 4 views
4

Я пишу легкий игровой движок, и, проводя некоторые исследования для него, я столкнулся с рядом убедительных статей, посвященных реализации объектов игры через модель «коллекция компонентов», а не «заблуждение от конкретных классов», модель. Есть много преимуществ:Как движок игры, который моделирует объекты как «коллекции компонентов», работает во время выполнения?

  • объектов может быть составлен с использованием данных управляемых методами проектирования, позволяющими дизайнеров придумать новые объектов без привлечения программиста;
  • там, как правило, меньше исходного файла зависимостей, позволяющих код скомпилирован быстрее;
  • двигатель в целом становится больше обычный;
  • непредвиденные последствия, связанные с необходимостью изменение классов бетона высоко вверх inheiritance иерархия может быть avoided;
  • и так далее.

Но есть части системы, которые остаются непрозрачными. Прежде всего, это то, как компоненты одного и того же объекта общаются друг с другом. Например, предположим, что объект, который моделирует пулю в игре реализована в терминах этих компонентов:

  • немного геометрии для визуального представления
  • положение в мире
  • объем используемых для столкновения с другими объектами
  • другие вещи

время рендеринга геометрии должен знать свое место в мире, чтобы отобразить совместное правильно, но как он находит эту позицию среди всех своих родственных компонентов в объекте? А во время обновления, как объем столкновения находит позицию объекта в мире, чтобы проверить его пересечение с другими объектами?

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

+0

Это отличный вопрос, и, хотя я много читал эту тему, я хотел бы, чтобы кто-то опубликовал окончательный ответ! – Iain 2008-10-15 15:56:27

+0

Я много читал об этом за последние несколько недель, в Game Programming Gems # 6 есть довольно хорошая статья об этом ... но нет хорошего примера времени выполнения. Мне все же хотелось бы знать, как вы можете управлять несколькими визуальными компонентами внутри Game Entity (для семейства визуальных игр, у вас может быть компонент Particle System, компонент оружия и компонент модели Character), и все эти компоненты внутри тот же игровой объект. Как вы можете управлять ими? – Goles 2009-11-29 21:31:30

ответ

1

Композитные архитектуры обычно полагаются на интерфейсы. Компонент затем представляет собой данные реализации +, позволяющие разработчикам повторно использовать доступные реализации с разными данными. например используя ракетный код один раз с ракетой и один раз со стрелкой. Гибкость заключается в возможности «настроить» такие комбинации вне фактического времени выполнения.

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

-1

Это звучит немного переоценено; что вы получаете, делая местоположение абстрактным компонентом объекта вместо фундаментального свойства?

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

Но опять же, ИМХО это очень похоже на перебор.

0

Невозможно ли дать объектам ссылку на объект игры?

Это позволило бы найти мировое положение, возвращаясь к объекту Game, затем свернув до мирового положения.

+0

Это звучит как хороший простой способ (см. Мой пример) - Интересно, есть ли еще один способ? – Iain 2008-10-15 15:57:19

1

Еще одна важная причина для реализации этой стратегии - это способность составлять поведение объекта из компонентов поведения, позволяя повторно использовать поведение в нескольких игровых объектах.

Так, к примеру, у вас есть базовый класс игры объект с этими свойствами: горючего, подвижного, живого. По умолчанию каждый имеет ссылку на null. Если вы хотите, чтобы ваш объект будет горючим, установите:

object.burnable = new Burnable(object); 

Теперь, в любое время вы хотите, чтобы записать объект, используйте:

if (object.burnable != null) 
{ 
    object.burnable.burn(); 
} 

И Сгораемые поведение будет изменять объект игры в любом как вы хотите.

+0

Я бы сделал Burnable в functor (operator operator), а не метод burn(), поэтому вы можете просто сказать object.burnable(); (И тогда переименуйте burnable для записи), я также сделал бы это так, чтобы object.burn по умолчанию содержал функтор no-op, поэтому вашему клиенту не нужно проверять, является ли оно нулевым. – 2008-10-17 19:47:21

+0

Что делать, если внутри сжигания вы также хотели бы хранить некоторые переменные, например, как легковоспламеняющийся, сколько времени он будет гореть и т. Д.? Могут ли они по-прежнему находиться в объекте «сжигания»? – Iain 2008-10-19 20:46:09

1

Я видел (и пытались) несколько способов реализации этого:

1) Компоненты существуют не в вакууме, но собраны в «сущности» (или «игра объект») объекта. Все компоненты имеют ссылку на свою сущность, поэтому ваше столкновение может сделать что-то вроде GetEntity() -> GetComponent («Position») -> GetCoords() (возможно, проверка нулевых векторов и т. Д.), Зависит от языка, работаю).

В этом случае иногда бывает удобно разместить некоторую общую информацию непосредственно в объекте (положение, уникальный идентификатор, статус «активный/неактивный») - есть компромисс между созданием чего-то «чистого» и общего, и сделать что-то быстрое и эффективное.

2) Нет сущности, только компоненты (я использую это для своего собственного легкого игрового движка). В этом случае компоненты должны быть явно связаны с другими компонентами, поэтому, возможно, ваши «столкновения» и «графика» будут содержать указатель на «позицию».

1

Я всегда находил Kyle Wilson's blog, чтобы быть интересным источником от кого-то, кто работает с этим и, кажется, много думает. Особенно эта запись может представлять интерес: http://gamearchitect.net/2008/06/01/an-anatomy-of-despair-aggregation-over-inheritance/. Это не ключевой момент статьи, но в основном он говорит, что они (при разработке «Fracture») имели отдельные иерархии. Один для GameObjects и SceneGraph для визуального представления. Лично я считаю, что это очень здоровый дизайн, но я не эксперт в этой области.

0

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

Целью приложения на основе компонентов является то, что вы можете добавлять и удалять компоненты, когда захотите, во время выполнения и иметь небольшую или отсутствующую связь; компоненты могут сосуществовать, даже не зная друг о друге.

Итак, как компонент «визуализации» знает, где он должен выглядеть или хуже, что он должен визуализировать? Отвечу, что каждый компонент родственный имеют доступ к общей таблице proprerties принадлежащих их контейнера (обычно в игру объекта или игрового объекта)

Для примера предположим, что объект игры с компонентом движения, визуализации компонент

компонентов и характер

Компоненты рендеринга запрашивают у своего контейнера свойство «positionx», «positiony» и «positionz» (если это 3D-игра), а затем запрашивают свойство «rendermodel». Исходя из этого, компоненты рендеринга отображают свойство, возвращаемое rendermodel в positionx, positiony и positionz. Свойства позиционирования изменяются компонентом движения, который сам задает свойство «скорость» на контейнере, которое, в свою очередь, настраивается компонентом символа на основе ввода с клавиатуры.

Если эти свойства не существуют, они создаются в момент их запроса и инициализируются с допустимым значением (например: 0).

С моей точки зрения, компоненты никогда не должны запрашивать другие компоненты, поскольку они должны рассматриваться как общие.