www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - ArtemisD: A D port of Artemis Entity System Framework for games.

reply "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
ArtemisD: A D port of Artemis Entity System Framework

About Artemis

   Artemis is a high performance Entity System framework for 
games, written in Java,
and is a framework to manage entities in a game world. It is 
inspired by
Entity Systems are the future of MMORPG blog series by Adam 
Martin.
http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

   We also borrowed ideas from Ted Brown who implemented a simple 
high-performance
Entity System in Processing based on Adam Martin's blog.
http://www.openprocessing.org/sketch/18023

   The framework is based on the concept that entities in a game 
world exist as pure
identifiers,their components contain only data, and systems 
process entities based
on their aspects.This promotes separation of concern and 
simplifies game design tremendously.

ArtemisD:
https://github.com/elvisxzhou/artemisd
http://code.dlang.org

Refer to http://gamadu.com/artemis for more info about Artemis.

Any suggestion or PR is welcome!

Elvis
Oct 07 2013
next sibling parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 07.10.2013 11:18, schrieb Elvis Zhou:
 ArtemisD: A D port of Artemis Entity System Framework

 About Artemis

     Artemis is a high performance Entity System framework for
 games, written in Java,
 and is a framework to manage entities in a game world. It is
 inspired by
 Entity Systems are the future of MMORPG blog series by Adam
 Martin.
 http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

     We also borrowed ideas from Ted Brown who implemented a simple
 high-performance
 Entity System in Processing based on Adam Martin's blog.
 http://www.openprocessing.org/sketch/18023

     The framework is based on the concept that entities in a game
 world exist as pure
 identifiers,their components contain only data, and systems
 process entities based
 on their aspects.This promotes separation of concern and
 simplifies game design tremendously.

 ArtemisD:
 https://github.com/elvisxzhou/artemisd
 http://code.dlang.org

 Refer to http://gamadu.com/artemis for more info about Artemis.

 Any suggestion or PR is welcome!

 Elvis
seem nice - BUT it seems too java oop like and very ungeneric, is there a real need to derive from component?
Oct 07 2013
parent reply "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
On Monday, 7 October 2013 at 09:31:15 UTC, dennis luehring wrote:
 Am 07.10.2013 11:18, schrieb Elvis Zhou:
 ArtemisD: A D port of Artemis Entity System Framework

 About Artemis

    Artemis is a high performance Entity System framework for
 games, written in Java,
 and is a framework to manage entities in a game world. It is
 inspired by
 Entity Systems are the future of MMORPG blog series by Adam
 Martin.
 http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/

    We also borrowed ideas from Ted Brown who implemented a 
 simple
 high-performance
 Entity System in Processing based on Adam Martin's blog.
 http://www.openprocessing.org/sketch/18023

    The framework is based on the concept that entities in a 
 game
 world exist as pure
 identifiers,their components contain only data, and systems
 process entities based
 on their aspects.This promotes separation of concern and
 simplifies game design tremendously.

 ArtemisD:
 https://github.com/elvisxzhou/artemisd
 http://code.dlang.org

 Refer to http://gamadu.com/artemis for more info about Artemis.

 Any suggestion or PR is welcome!

 Elvis
seem nice - BUT it seems too java oop like and very ungeneric, is there a real need to derive from component?
It's simple enough without over design IMO.
Oct 07 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 07.10.2013 11:57, schrieb Elvis Zhou:
 seem nice - BUT it seems too java oop like and very ungeneric,
 is there a real need to derive from component?
It's simple enough without over design IMO.
yes - if the need of beeing part of the hierachy is not a problem :) most D libraries try to be more generic and not that strong coupled - but that comes from the java background of the project still nice
Oct 07 2013
parent "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
On Monday, 7 October 2013 at 10:35:32 UTC, dennis luehring wrote:
 Am 07.10.2013 11:57, schrieb Elvis Zhou:
 seem nice - BUT it seems too java oop like and very ungeneric,
 is there a real need to derive from component?
It's simple enough without over design IMO.
yes - if the need of beeing part of the hierachy is not a problem :) most D libraries try to be more generic and not that strong coupled - but that comes from the java background of the project still nice
Really, generic programming in D is easy and fun, ArtemisD also benefits from it with original design retained.
Oct 07 2013
prev sibling next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Oct 07 2013
parent reply "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
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!
Oct 07 2013
parent reply "Kiith-Sa" <kiithsacmp gmail.com> writes:
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 )
Oct 07 2013
next sibling parent "Kiith-Sa" <kiithsacmp gmail.com> writes:
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 )
*look over the code, not comment
Oct 07 2013
prev sibling parent reply "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
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?
Oct 07 2013
parent reply "Kiith-Sa" <kiithsacmp gmail.com> writes:
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).
Oct 08 2013
next sibling parent "Hannes Steffenhagen" <cubicentertain gmail.com> writes:
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]?
Oct 08 2013
prev sibling parent reply "develop32" <develop32 gmail.com> writes:
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
Oct 08 2013
parent reply "Agustin" <agustin.l.alvarez hotmail.com> writes:
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.
Oct 11 2013
next sibling parent reply "Kiith-Sa" <kiithsacmp gmail.com> writes:
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))
Oct 11 2013
parent "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
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.
Oct 11 2013
prev sibling parent "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
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.
Oct 11 2013
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
Oct 07 2013
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
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
Oct 07 2013
prev sibling parent "Elvis Zhou" <elvis.x.zhou gmail.com> writes:
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!
Oct 07 2013