Boost logo

Boost :

Subject: Re: [boost] [Mixin] Some comments
From: Klaim - Joël Lamotte (mjklaim_at_[hidden])
Date: 2015-01-11 10:02:35


On Sun, Jan 11, 2015 at 8:41 AM, Matus Chochlik <chochlik_at_[hidden]> wrote:

> On Sun, Jan 11, 2015 at 2:05 AM, Klaim - Joël Lamotte <mjklaim_at_[hidden]>
> wrote:
>
> > On Sat, Jan 10, 2015 at 8:46 PM, Vicente J. Botet Escriba <
> > vicente.botet_at_[hidden]> wrote:
> >
> > >
> >
>
> [8<]
>
>
> > Basically allow very flexible composition even at runtime (which helps
> > tools dev too).
> > It's also have been mentionned in the documentation after these
> > discussions. (the doc is actually wrong in thinking that all engines
> > component systems rely on inheritance by the way).
> >
> > Last months I have seen mentionned several implemetnations of this
> pattern
> > in C++11/14 on github but was not pleased with any design so far.
> > The design of Boost.Mixin is close to what I want but don't reach my
> needs
> > yet (or at least last time I looked at it).
> >
>
> I've been playing with some ECS designs lately and tried to implement two
> of my own [1],[2] (maybe those are among those you've already seen) (and
> sorry for the shameless plug). Based on what I've seen, if the ECS is to be
> used according to the usage patterns you usually see in a game (or
> rendering) engine, I believe it is better for the component instances to be
> stored together, outside of the entities (for locality of reference,
> efficient (re-)allocation, etc.).
>
>
I violently agree.

> The entity should IMO be just an unique identifier

My experiments so far reach to the same conclusion: it's the most flexible
and potentially efficient approach.

> and in both of my
> implementations there is a `manager` class that can be used to
> store/modify/query/remove/etc. the components of an entity. This way
> operations that are common, like execute this function (every iteration of
> the update loop) on all entities with this set of components can be
> implemented more efficiently.
>

In my current implementation I call the object
holding all components a "cluster". The Cluster hold one "pool"
of component by type of components.
Currently all the pools are the same type and basically are
augmented flat_maps but I recently realized that a more flexible system
could be implemented by letting the cluster user insert different kinds of
polls
depending on how he wants the component type to be memory managed (
like a vector or like an actual pool or with allocated nodes?), how
"updates" are processed (in parallel, concurrent, jsut a loop?).
I plan to try this design in the coming months.

I didn't solve the component-inter-requirements problem though, I'm not sure
if I should implement this at all, and if yes should it be compile-time
checked
as Vincente suggests? In which case the cluster would have to know
the types it can manage at compile time too, because I see no way for
an entity to be able to be checked at compile time except for a construct
like
the suggested "subject".

>
> From what I've seen in `Mixin` sources (quite some time ago, maybe it has
> changed in the meantime) it does not do this. But the Mixin docs state that
> it is not exactly an ECS and maybe its usage patterns are different.
>
>
> >
> >
> > > * Respect to subjective programming: it would be great to be able to
> > > create subject from an entity so that only the mixins of the subject
> > would
> > > play when a reference to this subject is addressed.
> > >
> > > subject<Mix_1, .... Mix_n> s (o);
> > >
> > > o.get<Mix_k>() works as expected.
> > >
> > > o.get<Other>() compile fails if not equal to any Mix_k
> > >
> > >
> > Interesting.
> >
>
> In the [1] implementation you can do this by creating a `manager` that has
> a statically assigned group of component types.
> The usage is then close to the following:
>
>
> struct cmpnt_1 { };
> struct cmpnt_2 { };
> struct cmpnt_3 { };
> struct cmpnt_4 { };
>
> //declare group_x to contain component types cmpnt_1, cmpnt_2, cmpnt_3.
>
> manager<group_x> m;
>
> entity e;
>
> m.add(e, cmpnt_1(...), cmpnt_2(...));
> use(m.get<cmpnt_2>(e).whatever);
> m.add<cmpnt_3>(e);
> m.for_each<cmpnt_1, cmpnt_3>(func);
> m.remove<cmpnt_1, cmpnt_2>(e);
>
> m.add(e, cmpnt_4()); // compilation fails
> m.get<cmpnt_4>(e); // compilation fails
> m.remove<cmpnt_4>(e); // compilation fails
>
> But having implemented several apps using this approach I find it quite
> limiting in some situations that the group of components is static.
> Sometimes it is useful (for example for debugging) to have the ability to
> add/remove component *types* on-the-fly. [2] allows this but its
> unfinished.
>
> [8<]
>
>
I can do that in my implementation indeed, it is helpful.
As said before I think it can be improved by allowing the user to provide
the
container of component for a type, making him chose how to manage them
as long as the container match a specific set of requirement (concept?).

>
> >
> >
> > > * Can a mixin D inherit from another mixin B? Could the mixing D be
> > > retrieved when getting the mixing B?
> > >
> > > mutate(o).add<D>;
> > >
> > > o.get<B>()->f() // f been a virtual function on B?
> > >
> > >
> > I am failing to see the point or usefulness of this?
> >
>
> Most of the literature I've seen on ECS warns against trying too hard to
> combine OOP and the data-driven programming style used by E/C systems. Such
> logic should be encapsulated in the `systems` that work on the entity's
> components. But again maybe Mixin tries to fill a different niche than
> 'typical'/'traditional' ECS's do.
>
> [8<]
>
> >
>
>
> [1] https://github.com/matus-chochlik/exces
> [2]
> https://github.com/matus-chochlik/eagine/tree/develop/include/eagine/ecs
>
> BR
>
> Matus
>
> _______________________________________________
> Unsubscribe & other changes:
> http://lists.boost.org/mailman/listinfo.cgi/boost
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk