Компонентная система объектов - компоненты, требующие друг друга
Я написал систему компонентов сущности для моей игры (C++). Затем я реорганизовал мою систему рендеринга для работы с Entities / RenderComponents, а не с каким-то виртуальным интерфейсом для рисования. Это некоторые классы, для которых я не думаю, что имеет слишком много смысла, чтобы заставить их быть компонентом. Одним из таких классов является карта.
Мой класс карты состоит из класса плиточной местности и некоторых других данных (не важно). Класс плиточной местности управляет несколькими слоями в форме (что на данный момент) TiledTerrainLayer
учебный класс. Перед рефакторингом системы рендеринга я просто унаследовал от Drawable
а также Transformable
чтобы этот класс отображался системой рендеринга. Теперь необходимо быть субъектом с по крайней мере TransformComponent
и немного RenderComponent
,
Теперь TiledTerrainLayerRenderComponent
должен действительно иметь только вершины и ссылку на текстуру и, возможно, флаг того, была ли она уже создана. TiledTerrainComponent
будет принадлежать список индексов плитки, а также размер плитки и карты.
Теперь моя проблема в том, что когда я устанавливаю плитку (используя что-то вроде SetTile(size_t tileIndex, const Position & pos)
Метод, я также должен обновить текстурные координаты массива вершин.
Я обычно в порядке с одним компонентом, требующим другого компонента. Например, SpriteRenderComponent
требует TransformComponent
и я также в порядке с одним компонентом доступа к информации другого. Например, метод GetBoundingBox() использует положение компонента преобразования.
Чего я хочу избежать, так это того, что два компонента "перекрестно ссылаются" друг на друга, как это было бы в случае с TiledTerrainComponent
(TTC) и TiledTerrainRenderComponent
, (TTRC) (TTRC получает tileIndexList TTC для создания себя, и TTC вызывает метод UpdateVertices() TTRC, когда вызывается его метод SetTile().
Наконец, я знаю, что компоненты должны быть в основном данными. Я только добавил методы, которые напрямую получают или изменяют эти данные, такие как SetTile() или GetTexture(). Будет ли система жизнеспособной в случае, описанном выше, и если да, как она будет выглядеть?
1 ответ
Похоже, все, что вам нужно здесь, это грязный флаг.
Когда вы изменяете индекс, размер или другие свойства тайла на своем Tiled Terrain, вы не сразу звоните в Tiled Renderer, чтобы обновить его вершины (в конце концов, у вас может быть много обновлений плиток, которые еще не появились в этом фрейме - это может быть расточительно пересчитать твои вершины каждый раз)
Вместо этого рендерер Tiled Terrain просто устанавливает свой внутренний hasBeenModifiedSinceLastUse
признак истины. Ему вообще не нужно знать о рендерере.
Затем, когда вы обновляете свой Tiled Renderer непосредственно перед рисованием, вы должны спросить его Tiled Terrain, обновлялся ли он с момента последнего рисования (вы даже можете запросить список обновлений, если хотите нацелить изменения). Если это так, вы обновляете вершины в одном большом пакете, чтобы улучшить код и локальность данных.
При этом вы сбрасываете измененный флаг, чтобы в случае отсутствия обновлений в последующих кадрах вы могли повторно использовать последний сгенерированный набор вершин как есть.
Теперь ваша зависимость указывает только на один путь - рендеринг зависит от данных мозаики, но данные мозаики не знают о рендеринге, кроме поддержания своего флага.