Entreri 1.7 Released (Entity-Component Framework)

Hi guys!

It’s been quite a while since I’ve posted but I’ve been lurking regularly as I finished up my first year of grad school. The big news now is that I’ve released a significant update to my entity-component framework: http://entreri.lhkbob.com and https://bitbucket.org/mludwig/entreri. I posted previously about an earlier version of Entreri: http://www.java-gaming.org/index.php?topic=24962.0

You guys gave me some good feedback, mostly about scariness of strict component definition rules I had imposed. After some significant revisions, I’ve updated it to allow you to define your component types as Java bean interfaces, and then an annotation processor to generate the implementation that uses a mapped-object model for performance.

As an example, I could define two components as follows:


public interface Location extends Component {
   public float getX();
   public Location setX(float v); // automatically returns this component

   public float getY();
   public Location setY(float v); // ""
}

public interface Health extends Component {
   public int getHealth();
   public Health setHealth(int v);
}

Then using these components would look along these lines:


EntitySystem system = EntitySystem.Factory.create();
Entity player = system.addEntity();
player.add(Location.class).setX(0).setY(0);
player.add(Health.class).setHealth(250);

// .. later in your main loop ..
// this shows how to iterate over all entities with a single component type, 
// and it uses a flyweight instance for faster iteration over the underlying data
ComponentIterator checkForDead = system.fastIterator();
Health flyweightInstance = checkForDead.addRequired(Health.class);

while(checkForDead.next()) {
   if (flyweightInstance.getHealth() <= 0) {
      system.removeEntity(flyweightInstance.getEntity());
   }
}

Other new features include a parent-child hierarchy model that makes it easy to have one entity for the player, and another entity for its weapon and link them so that deleting the player entity will automatically delete the weapon. Another is a multi-threaded job/task API that tries to make simple parallelization easy to do without much thought, such as splitting the rendering and physics tasks onto separate threads with minimal synchronization.

I’d love to hear more feedback, and hopefully get people who have had experience with other libraries such as Artemis, or Ash, to give it a comparison.

Thanks!
Michael

This is really interesting. All those names for the Entity component frameworks are always so special: Artemis, Apollo, Entreri. What’s going on? :smiley:

Anyways, the example looks very cool, and - in contrast to other entity frameworks mentioned above - you have a very special iterating concept, which looks really cool and well designed. Good work!

Didn’t check it out completely yet, though.

Nice job!

I found new one on github called Ashley.

Hi

Your verbs should be at the 3rd person in your Java online documentation (“Gets” instead of “Get”, “Returns” instead of “Return”, …). I don’t clearly see the service(s) this kind of API provides. Is it still possible to pack all components into a primitive array?

Thanks for the comments; I know besides Ashley there is also another one called Ash. I think it’s a general library thing though because you’ve also got things like Kryo and Slick. Artemis was my original inspiration and has since diverged pretty heavily but there is a fiction character named Artemis Entreri that I used to like, also it sounds kind of like Entity.

Gousseg, this API still packs everything into primitive arrays, it just does it for you so it’s less error prone and your code looks much cleaner. In general, even entity libraries that don’t do this still get you to think about your code in a novel way that can improve it. I think this is like how learning a functional language can help your OO programming even when you don’t program functionally directly.

When I see Artemis and your framework, I just feel like they encourage the developers to use an object-oriented language not to respect the OOP principles, by separating the objects and their mutators the former as entities and the latter as “systems”.

OOP has evolved over time. It’s no longer acceptable to have giant inheritance trees, and composition is the name of the game now. Now it’s quite possible to have a nicely compositional design without the use of entity systems, but the chief advantage of such systems is that they force you into using composition over inheritance. This is a boon for novices who otherwise might not wander into such a design of their own volition. That a good entity system also provides for flexible ways to assemble components at runtime and optimizes for reference locality is a bonus.

I can’t help but think that the Location component shouldn’t be returning Player instances considering that that the Health component returns itself. Also, am I correct in assuming that the components you defined have automagically generated code or am I just being delusional? >.>

Oh yeah, that’s a typo, I was fussing back and forth about calling it Player or Location. Edited it to be correct. Yes, the interfaces get implementations generated by annotation processing such that every bean method pair defines a “property” which is backed by a primitive array. The component implementations just get an index into that, so iterating over the component data of a particular type is very efficient and cache friendly.

And I should mention that the annotation processor would raise an error if my mistake was made in the actual code base.

I’ve been using Artemis for a while and I’m quite happy with it.
Has anyone tried Entreri and would suggest it over Artemis?

For library like these trying is not enough. We need benchmark.

Although Artemis and Entreri originally started out having a similar API, Entreri has evolved in a significantly different direction. The reason for this is that underlying component data is packed efficiently into primitive arrays that provides better guarantees for cache locality if used carefully. Components are defined as interfaces, which IMO reduces the amount of boilerplate that you have to write and helps ensure the principles of data-only components are followed.

That being said, I haven’t performed any official benchmarks yet because I am interested more in real application performance. Often in micro-benchmarks, garbage collection doesn’t kick which means lists of objects haven’t been moved around in the heap and actually have quite good cache locality. Anecdotally when doing tests between an old version of entreri (that was structured more like artemis) and the new entreri, data packing seemed responsible for a 2-4X performance improvement. These performance advantages are less noticeable for small entity counts, but entreri scales very gracefully to tens of thousands while still giving very good performance (it won’t be the bottleneck at that point).