Название немного сбивает с толку, но я не могу понять, как объяснить мой вопрос в короткой фразе. Итак, вот оно:
Всякий раз, когда я пишу игровые движки, независимо от того, основаны ли они на физике / плитке и т. Д., Я всегда дохожу до того, что не знаю, как мне следует управлять вещами. Должны ли сущности в мире справляться самостоятельно или должна существовать глобальная система, управляющая ими?
Вот простой пример: перемещение вещей. Должен ли каждый объект видеть окружающий его мир (проверять наличие столкновений) и двигаться на основе этого.
[обратите внимание, что это игра на основе тайлов, в которой объекты перемещаются за плитку, поэтому я не использую физику для перемещения от тайла к тайлу]
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
if (world.getTile(location) != solid && world.objAtTile(location) == null)
{
Tweener.addTween(this, location);
}
}
}
Или движение каждого объекта должно управляться в мире, где мир все проверяет?
public class Actor : GameObject
{
private void MoveTo(Vector2 location)
{
world.moveTo(location);
}
}
public class World
{
public void moveObject(GameObject obj, Vector2 location)
{
//called from object
if (getTile(location) != solid && objAtTile(location) == null)
{
Tweener.addTween(obj, location);
}
}
}
Я полагаю, что для этого примера это не имеет большого значения, но я вижу, что позже у меня возникают проблемы. Заранее спасибо.
источник
Actor
знать оworld
вообще?Ответы:
Я вижу, что ваши примеры написаны на Java, но в ваших тегах не указан язык. В C ++ ответ ни один - вы не должны использовать функцию-член для этого!
источник
Там нет простого ответа.
Как и в большинстве вещей в программировании, это компромисс. Предоставление большей мощности отдельным объектам делает их больше - и, следовательно, медленнее - но облегчает понимание и расширение двигателя. Наличие мега-класса, который может обрабатывать все вместе, может быть быстрее, но за счет наличия мега-класса; то есть вообще считается плохой формой делать сверхмассивные занятия.
Я прочитал несколько статей о компонентном и управляемом данными проектировании, где у вас есть один класс, который представляет все объекты определенного типа, хранит их данные в списках и передает только индексы, чтобы получить свойства отдельного объекта. Хотя я могу видеть это как жизнеспособный тип архитектуры, я чувствую, что это скорее винтики с целой точкой объектной ориентации, которая также получила свою долю критики.
Я лично рекомендую придать объектам больше энергии. Это имеет больше смысла в объектно-ориентированном языке, и (как мне кажется) легче понять и поддерживать с течением времени.
источник
Я обновляю свой ответ, потому что многое не было ясно до комментариев. Пожалуйста, держись со мной, пока я объясняю свои мысли.
В общем, два ключевых аспекта, которые следует учитывать в любой конструкции, это сплоченность и сцепление . Мы все знаем, что нам нужна высокая когезия и слабое сцепление, чтобы иметь возможность создавать более многократно используемую и расширяемую конструкцию.
Таким образом, если мир должен управлять всем, это означает, что у него низкая сплоченность и тесная связь (потому что он должен знать и делать все). Однако это также тот случай, когда игровой объект должен делать все. Обновить его местоположение, визуализировать его текстуру и т. Д. И т. Д.
Что вас действительно интересует, так это создание систем, ориентированных на один аспект сущности. Например, игровая сущность может иметь текстуру, но Renderer будет отвечать за отображение этой текстуры на экране. Рендереру не важно, какие другие свойства у объекта.
Если пойти немного дальше, игровая сущность - это просто мешок свойств. Этими свойствами управляют системы, ориентированные на конкретные свойства. И именно здесь вступают в действие системы сущностей на основе компонентов (CBES), где свойства = компоненты.
В частности, CBES с системами (или подсистемами). Этот дизайн имеет тенденцию иметь несколько систем, которые ориентированы на конкретные компоненты объекта, не заботясь о том, какие другие компоненты есть у объекта. Кроме того, Системы связаны только с информацией, которая им необходима для обработки этих компонентов.
Давайте возьмем ваш пример. Так как ввод, куда перемещать объект, основан на контроллере игрока, у вас, вероятно, будет PlayerControllerSystem. Эта система, помимо всего прочего, будет контролировать PositionComponent объекта. В этом случае PlayerControllerSystem необходимо знать об уровне и PositionComponent. Если позже вы решите добавить обнаружение столкновений, вы создадите систему CollisionSystem, которая снова будет использовать положение сущностей, но на этот раз для вычисления ограничивающих рамок (или вы можете иметь BoundingBoxComponent, ваш вызов). Дело в том, что вы можете легко включать и выключать поведение (даже на лету), просто добавляя / удаляя компоненты. Таким образом, большее поведение означает, что больше систем манипулируют компонентами сущности, но все они находятся в четко определенном классе с низкой связью. Хотите сценарии? Добавьте ScriptComponent. BAM! Вы только что добавили возможности сценариев с 2 классами. Физика? Звук? Опять то же самое.
Итак, причина, по которой я защищаю CBES с подсистемами, заключается в том, что это идеально ОО и в целом простая в обслуживании / расширяемая система. Добавить поведение к объекту так же просто, как решить, какие данные нужны этому поведению и какие объекты нужны.
Для получения дополнительной информации о Компонентных Entity Systems с Подсистемами, есть отличная серия постов в блоге от T = Machine на Entity Systems - будущее разработки MMOG . Автор даже дошел до создания вики для сбора различных реализаций под названием Entity Systems Project.
Общим (и хорошо известным) постом о компонентных системах сущностей в целом является Evolve, ваша иерархия , создавшая систему для Tony Hawk Pro.
Наконец, если вы ищете библиотеку с примером кода, не идите дальше, чем библиотека Artemis . Артемида в основном на Java, но здесь есть порт на C # (который я сейчас использую в своем проекте XNA).
источник
Я обычно использую дизайн, в котором объекты обрабатывают себя (в конце концов, для этого и нужны методы), но в базовом Мире есть списки всех объектов, и он использует эти списки для их координации. Так что-то вроде:
источник
Держи это сухим, застенчивым и скажи другому парню.
Лучше попросить мир переместить своего актера, чем спросить мир, можете ли вы переместиться туда, куда вы хотите. Таким образом, вы можете легко изменить алгоритм поиска пути в мировом классе и тому подобное. Конечно, вы можете просто оставить это до базового класса для актера, но я бы выбрал направление и причину.
источник
РЕДАКТИРОВАТЬ: переписано из-за обратной связи, заявив, что я не сделал достаточно четкую линию для этого ответа на исходный вопрос.
Я хотел бы прояснить вопрос немного больше, если это возможно. Должна ли логика, которая действует на объект, быть внутренней или внешней по отношению к этому объекту. В последней части поста конкретно упоминается долговечность дизайна в качестве основы для постановки вопроса, чтобы избежать неприятностей в дальнейшем.
Мой простой ответ высокого уровня - сохранить всю логику, которая воздействует на объект внутри этого объекта.
Вам не нужен мир для перемещения объекта, все, что вам нужно, это объект, который нужно переместить, и вектор, представляющий местоположение, в которое он должен переместиться. Мир может вступить в игру, когда выбирается пункт назначения или когда требуется реакция на окружающую среду из-за столкновения, но они находятся за пределами примера, который дан для работы.
Для решения основной части вопроса и достижения долговечности дизайна я бы предложил компонентно-ориентированную архитектуру. Компонентные архитектуры разбивают объект на отдельные наборы данных и функциональные возможности (при условии, что вы ответите на мой ответ выше, в котором говорится, что логика должна соответствовать данным). Если ваша структура выглядит как CEntity-> CHuman-> CSoldier-> CPlayerCharacter, то вы неизменно будете сталкиваться с проблемами, когда вам нужно изменить какую-то логику и в зависимости от того, куда она идет в этом дереве (например, сколько других типов людей существует?) это может иметь огромное влияние на несколько типов объектов.
Вместо этого система компонентов будет иметь набор интерфейсов, которые определяют, из чего состоит объект CEntity, таких как ICompRenderable, ICompMoveable, ICompHealth, ICompInventory и так далее. Где вы должны иметь CCompMoveableHuman и, возможно, CCompMoveableSoldier и CCompMoveablePlayer, чтобы разделить их отдельные шаблоны движения. Так скажем, Солдат переделан, чтобы бежать в строю. Это изменение повлияет только на объекты, созданные с использованием этого компонента.
Итак, чтобы подвести итог, я предлагаю вам содержать логику с данными, к которым применяется логика. Я также рекомендую разбивать объекты на отдельные компоненты, чтобы сократить «Где я могу это разместить?» вопросы и обеспечить стабильность в будущем с простотой обслуживания и его расширения.
Надеюсь это поможет.
источник
Я рекомендую вам попробовать ознакомиться с компонентными архитектурами. Есть довольно много постов в блогах, презентаций и публикаций о них, которые могут сделать лучшую работу, чем я когда-либо мог.
AltDevBlogADay имеет довольно много сообщений об этом, очень хороший, являющийся этой серией о игровых объектах: http://altdevblogaday.com/2011/07/10/the-game-entity-–-part-ia-retrospect/ Есть несколько частей, посвященных проблеме, которую вы пытаетесь решить.
источник