frengels / matter

C++20 highly parallel ECS implementation
20 stars 0 forks source link

Supporting archetypes #79

Open frengels opened 5 years ago

frengels commented 5 years ago

Archetypes are a way to identify components which belong together, a rough example could be.

struct player
{
    // must be set for the ECS to figure out what components this archetype wants
    using components = std::tuple<position, health, weapon, armor>;
    position& pos;
    health& h;
    weapon& weap;
    armor& arm;

    // must be constructable from references in the tuple
    player(position& pos, health& h, weapon& weap, armor& arm)
      : pos{pos}, h{h}, weap{weap}, arm{arm}
    {}

    // other member functions
};

This would give access to member functions without violating the dumb components idea. This could be accessed from the registry with registry::view<Archetype>(). Which will give a specialized registry_view that passes the given archetype on for_each invocation.

frengels commented 5 years ago

Now that access specifiers are being used we can have an archetype's members be value types rather than reference types.

The above would change to:

struct player
{
    using components = std::tuple<position, health, weapon, armor>;
    position pos;
    health h;
    weapon weap;
    armor arm

    player(const position& pos, const health& h, const weapon& weap, const armor& arm)
      : pos{pos}, h{h}, weap{weap}, arm{arm}
    {}
};

It will be accessed through

auto pview = reg.view<readwrite<player>>()

pview.for_each([] (auto player) {
    auto p = player.get();
    // do mutations
    player.stage(p);
});

Archetype registration can be done either through registering each type within or by using

reg.register_archetype<player>();

Because a subset of components could already be registered this will check if each component is registered and register each one that hasn't been registered yet.

template<Archetype A>
registry::register_archetype()
{
    for_each(T : components_t<A>)
    {
        if (!reg.contains<T>()) {
            reg.register_component<T>();
        }
    }
}