В моем игровом движке ECS создаются состояния, которые регистрируют определенное количество объектов и присваивают им их компоненты. Функции обновления систем вызываются один раз за цикл обновления. На этом этапе они запрашивают текущее игровое состояние (через статическую ссылку на менеджер состояний) для соответствующих типов компонентов (то есть: система рендеринга запрашивает компоненты рендеринга и позиционирования).
Состояния игры нуждаются в способе хранения своих сущностей и соответствующих компонентов, а также в способности предоставить системам контейнер компонентов данного типа. Как я могу хранить компоненты, производные от базового класса компонентов, чтобы системы могли получать производные классы?
Некоторые из решений, которые я читал в Интернете, включают в себя:
Должен ли я использовать одну карту? Два? Должны ли они содержать общие или слабые указатели, или ни того, ни другого? Как мне написать мою шаблонную функцию для возврата производных классов компонентов?
component.hpp
struct Component {
public:
// Perhaps some sort of static derived class identifier would go here
};
typedef vector<Component> ComponentVector;
state.hpp
class State {
protected:
// The game class is the game's entry point, where states and systems are created.
// It also holds a reference to the state and system managers, so they can be
// accessed by each other
friend class Game;
static Game *game;
// ie: assignComponent<RenderComponent>(player)
template <typename C, typename Args ...>
void assignComponent(Entity entity, Args && ... args);
Entity createEntity();
void destroyEntity();
template <typename C>
ComponentVector<C> getComponents();
public:
// The names identify each state so the state manager can queue them
const StateName name;
typedef shared_ptr<State> Pointer;
State(StateName name) : name(name) {}
virtual void registerEntities() = 0;
virtual ~State() {}
};
overworld_state.hpp (пример производного класса состояний)
class OverworldState : public State {
public:
OverworldState() : State(OVERWORLD) {}
void registerEntities() {
Entity player = createEntity();
assignComponent<RenderComponent>(player);
}
};
system.hpp
class System {
protected:
friend class Game;
static Game *game;
public:
virtual void update() = 0;
virtual ~System() {}
};
render_system.hpp (пример системного класса)
class RenderSystem : public System {
public:
void update() {
// Pseudo code of how I would like it to work:
ComponentVector<RenderComponent> components =
game.currentState.getComponents<RenderComponent>();
}
};
Задача ещё не решена.
Других решений пока нет …