October 08, 2013
On Monday, 7 October 2013 at 20:31:27 UTC, Andrei Alexandrescu wrote:
> On 10/7/13 2:18 AM, Elvis Zhou wrote:
>> ArtemisD: A D port of Artemis Entity System Framework
> [snip]
>
> Limelight on! http://www.reddit.com/r/programming/comments/1nxlxt/artemisd_a_d_port_of_artemis_entity_system/
>
>
> Andrei

Alexandroid did its job :D
October 08, 2013
On Monday, 7 October 2013 at 20:31:27 UTC, Andrei Alexandrescu wrote:
> On 10/7/13 2:18 AM, Elvis Zhou wrote:
>> ArtemisD: A D port of Artemis Entity System Framework
> [snip]
>
> Limelight on! http://www.reddit.com/r/programming/comments/1nxlxt/artemisd_a_d_port_of_artemis_entity_system/
>
>
> Andrei

Thank you very much!
October 08, 2013
On Monday, 7 October 2013 at 17:06:40 UTC, Kiith-Sa wrote:
> On Monday, 7 October 2013 at 15:21:00 UTC, Elvis Zhou wrote:
>> On Monday, 7 October 2013 at 14:19:20 UTC, Ali Çehreli wrote:
>>> On 10/07/2013 02:18 AM, Elvis Zhou wrote:
>>>
>>>> ArtemisD:
>>>> https://github.com/elvisxzhou/artemisd
>>>
>>> Just a little note: As it's more readable, you may want to use 1000.msecs instead of dur!("msecs")(1000) in the example program. 1000.msecs is the equivalent of the msecs(1000) function call, which returns dur!("msecs")(1000).
>>>
>>> Ali
>>
>> Done, thank you!
>
> I'm implementing pretty much the same thing in my project, although I'm probably
> more in line with the original blog post (e.g. every system can only access
> specific components of an entity, which are statically determined, entities are more lightweight, etc.). I'm using much less OOP and more of a generic/metaprogramming approach. Currently I'm trying to rewrite the code to add a concept of "past" and "future" state; a System processes past Components and outputs a future Component, past Components are const, and no two systems may write to the same future Component. This should allow very simple threading
> with little synchronization.
>
> I'll look at your code if there are interesting ideas.
>
> The previous version of my entity system is used in my ICE game:
>
> https://github.com/kiith-sa/ICE
>
> It's quite messy, though; which is why I'm rewriting it.
> The new version doesn't even compile at the moment, I'm working on it slowly as I'm studying and working at the same time right now.
>
> I'll look over the comment and post if I have any further feedback. The only thing I can say right now is that there is inconsistent tab-space indentation in some parts of the code (e.g. https://github.com/elvisxzhou/artemisd/blob/master/source/artemisd/entity.d )

I'll give it a try, thank you!

My main concern in the D port is, since getComponent is the
most important and most used function, often in every frame,
but caching it is not a good idea cause any component may
be removed or added at any time, with an additional
mixin TypeId in component definition, component then can be
get with its TypeId(index of component list) in zero cost.
In other ports, like Java or C#, even in C++, a ComponentMapper
like stuff is used to hash a component type to find a registered
index before you can get it efficiently.

What do you think?
October 08, 2013
On Tuesday, 8 October 2013 at 05:24:13 UTC, Elvis Zhou wrote:
> On Monday, 7 October 2013 at 17:06:40 UTC, Kiith-Sa wrote:
>> On Monday, 7 October 2013 at 15:21:00 UTC, Elvis Zhou wrote:
>>> On Monday, 7 October 2013 at 14:19:20 UTC, Ali Çehreli wrote:
>>>> On 10/07/2013 02:18 AM, Elvis Zhou wrote:
>>>>
>>>>> ArtemisD:
>>>>> https://github.com/elvisxzhou/artemisd
>>>>
>>>> Just a little note: As it's more readable, you may want to use 1000.msecs instead of dur!("msecs")(1000) in the example program. 1000.msecs is the equivalent of the msecs(1000) function call, which returns dur!("msecs")(1000).
>>>>
>>>> Ali
>>>
>>> Done, thank you!
>>
>> I'm implementing pretty much the same thing in my project, although I'm probably
>> more in line with the original blog post (e.g. every system can only access
>> specific components of an entity, which are statically determined, entities are more lightweight, etc.). I'm using much less OOP and more of a generic/metaprogramming approach. Currently I'm trying to rewrite the code to add a concept of "past" and "future" state; a System processes past Components and outputs a future Component, past Components are const, and no two systems may write to the same future Component. This should allow very simple threading
>> with little synchronization.
>>
>> I'll look at your code if there are interesting ideas.
>>
>> The previous version of my entity system is used in my ICE game:
>>
>> https://github.com/kiith-sa/ICE
>>
>> It's quite messy, though; which is why I'm rewriting it.
>> The new version doesn't even compile at the moment, I'm working on it slowly as I'm studying and working at the same time right now.
>>
>> I'll look over the comment and post if I have any further feedback. The only thing I can say right now is that there is inconsistent tab-space indentation in some parts of the code (e.g. https://github.com/elvisxzhou/artemisd/blob/master/source/artemisd/entity.d )
>
> I'll give it a try, thank you!
>
> My main concern in the D port is, since getComponent is the
> most important and most used function, often in every frame,
> but caching it is not a good idea cause any component may
> be removed or added at any time, with an additional
> mixin TypeId in component definition, component then can be
> get with its TypeId(index of component list) in zero cost.
> In other ports, like Java or C#, even in C++, a ComponentMapper
> like stuff is used to hash a component type to find a registered
> index before you can get it efficiently.
>
> What do you think?


In my implementation I don't even use a getComponent equivalent; a process()
(or opApply() in the older version I linked) function directly takes component
references, and all components are in plain arrays. Processing of a System
is done (in generated code) by iterating over the components the System specifies in its signature, which is cache-friendly, and means the components needed are always available directly to the process() function without any lookup. However, this is a less flexible approach than what you're doing (although intentional, again, to eventually enable very easy threading).

That said, in my code, entities can only be added/removed between frames
(a System might create a new entity but it will only start to exist with the next frame), and components cannot be changed once the entity is created (although the new past/future design I'm working on now might enable that).


October 08, 2013
Thanks, for the work, new libraries are always nice.

Though, I have to agree that, at least at first glance, it seems a bit heavyweight. Is there really a need for Entity to be its own class, rather than, say, [code]alias Entity = Typedef!UUID;[/code]?

October 08, 2013
On Tuesday, 8 October 2013 at 10:35:53 UTC, Kiith-Sa wrote:
> In my implementation I don't even use a getComponent equivalent; a process()
> (or opApply() in the older version I linked) function directly takes component
> references, and all components are in plain arrays. Processing of a System
> is done (in generated code) by iterating over the components the System specifies in its signature, which is cache-friendly, and means the components needed are always available directly to the process() function without any lookup. However, this is a less flexible approach than what you're doing (although intentional, again, to eventually enable very easy threading).

Looks similar to what I do in my engine, although entities and components are not classes.

Basic example:

struct State2D
{
    Vector2 position;
    float rotation;
}

struct BoundKill {} // Acts as a tag

class BoundManager : Manager!(State2D, BoundKill)
{
    override void process(Entity entity, State2D state, BoundKill tag)
    {
        if (state.y < 0)
            world.remove(entity);
    }
}

And entity is just a struct containing size_t id
October 11, 2013
Correct me if i'm wrong, but isn't the whole point of Artemis design to take advantage of CPU cache levels by storing every component of the same type contignously?

In your example, the components are stored non contignous, using the GC

    Entity e = world.createEntity();
    e.addComponent(new Position(0,0));
    e.addComponent(new Velocity(10,0));
    e.addToWorld();

I think a good optimization will be implementing a non GC vector class to store every component contignous, and changing it to this

    Entity e = world.createEntity();
    e.addComponent!Position(0, 0); // Forwarding. Just like emplace for C++
    e.addComponent!Velocity(10, 0); // Forwarding.
    e.addToWorld();

Position and Velocity are stored in an object pool vector that will take advantage of the CPU cache when iterating.
October 11, 2013
A component-entity architecture has two main advantages;
one of them is efficiency/cache locality (which this project doesn't have at all). Another is the ability to quickly define new types without the clusterfuck that happens if you try to use OOP to design game entities (and also to define them in plain data types).

This thing is ported from Java where performance didn't seem to be a concern (even though they're calling it 'lightweight' for some reason). There are even component-entity frameworks for Ruby, Actionscript, etc, where there is no way at all to utilize cache locality.

I think this might be useful if you're creating a game that doesn't need the best graphics and when a little latency isn't a problem (e.g. turn-based strategy, adventure, etc.).


(I'm not the developer of artemisd, but I'm working on a similar design, although with a bit more compile time, cache-aware and hopefully auto-threadable; but also much less flexible, more 'purist' (not likely to be released as a separate library, either))
October 12, 2013
On Friday, 11 October 2013 at 19:29:52 UTC, Agustin wrote:
> Correct me if i'm wrong, but isn't the whole point of Artemis design to take advantage of CPU cache levels by storing every component of the same type contignously?
>
> In your example, the components are stored non contignous, using the GC
>
>     Entity e = world.createEntity();
>     e.addComponent(new Position(0,0));
>     e.addComponent(new Velocity(10,0));
>     e.addToWorld();
>
> I think a good optimization will be implementing a non GC vector class to store every component contignous, and changing it to this
>
>     Entity e = world.createEntity();
>     e.addComponent!Position(0, 0); // Forwarding. Just like emplace for C++
>     e.addComponent!Velocity(10, 0); // Forwarding.
>     e.addToWorld();
>
> Position and Velocity are stored in an object pool vector that will take advantage of the CPU cache when iterating.

Thank you, I'm going to improve ArtemisD with more D idioms and generic after this very first and straightforward port.
October 12, 2013
On Friday, 11 October 2013 at 19:50:42 UTC, Kiith-Sa wrote:
> A component-entity architecture has two main advantages;
> one of them is efficiency/cache locality (which this project doesn't have at all). Another is the ability to quickly define new types without the clusterfuck that happens if you try to use OOP to design game entities (and also to define them in plain data types).
>
> This thing is ported from Java where performance didn't seem to be a concern (even though they're calling it 'lightweight' for some reason). There are even component-entity frameworks for Ruby, Actionscript, etc, where there is no way at all to utilize cache locality.
>
> I think this might be useful if you're creating a game that doesn't need the best graphics and when a little latency isn't a problem (e.g. turn-based strategy, adventure, etc.).
>
>
> (I'm not the developer of artemisd, but I'm working on a similar design, although with a bit more compile time, cache-aware and hopefully auto-threadable; but also much less flexible, more 'purist' (not likely to be released as a separate library, either))

The second advantage is far more important IMO, I've been using Unity3D for my work for several years and I think its component based design play a significant role to its success technically,(refer to its assets store, so many third party components developed and can be easily reused).
OTOH, given its C#/Mono nature, performance is not that important in reality in an app layer which an entity system is supposed to reside in. However, as a C programmer I also cann't ignore it if there be any performance loss by design.
1 2
Next ›   Last »