junkdog / artemis-odb

A continuation of the popular Artemis ECS framework
BSD 2-Clause "Simplified" License
776 stars 111 forks source link

Allow Extending Entities #491

Closed xaguzman closed 6 years ago

xaguzman commented 7 years ago

Hello, been using your framework for a while now.

I have always had this small problem that Entitiy is pretty limited up (and never useful for my uses, just really need the Id).

What I know I always need is having a "default" Entity, with a transfom for example. I know not everybody needs this kind of functionality, but for the few of us who need it, it could save a lot of time.

Is it possible to make World Generic and accept just a subclass of Entity? Maybe just replacing the EntityManager inside world could do the trick.

I find myself repeating a lot of composition which I think could be avoided (as I said, Transform is a component which my current game has in every entity...just checked) by a more "complex" Entity.

Please consider this option

piotr-j commented 7 years ago

I think removal of Entity entirely is more likely then this. If you build entities manually a lot, create few static methods that will insert common components. Something like int createAt(float x, float y, float r)

mrcdnk commented 7 years ago

For me grouping similiar entities into EntityTypes helped a lot. I have implemented my own abstract EntityBuilder, which I can extend for each EntityType. If there are entities which share a lot of components, I will put the creation into a parent EntityBuilder and then create specific builders for each type. This also saves me code because all of my EntityBuilders share their mappers and an abstract method which is used to "fill" the components with content. (Getting/Creating the components is handled automatically) I use them like this:

EntityABuilder entityABuilder = new EntityABuilder();
int entity = entityABuilder.build()

I'm not sure if this also saves some memory, processing time or GC cycles because of shared mappers and component Memory, but it works well if you have many entities with similiar components.

Namek commented 7 years ago

as I said, Transform is a component which my current game has in every entity...just checked

@xaguzman is that still true? In my experience such things are true until development grows. It may end up no one will ever need this feature. Reconsider closing the issue.

xaguzman commented 7 years ago

It still holds true until today.

You can always go around it, I just think that having a convenience way to work even if it has a penalty could benefit a lot of people

El 15 abr. 2017 4:45 PM, "Namek" notifications@github.com escribió:

as I said, Transform is a component which my current game has in every entity...just checked

@xaguzman https://github.com/xaguzman is that still true? In my experience such things are true until development grows. It may end up no one will ever need this feature. Reconsider closing.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/junkdog/artemis-odb/issues/491#issuecomment-294319601, or mute the thread https://github.com/notifications/unsubscribe-auth/AAGZ21OmotsV3j-gLGBp72y9YI5I4YQjks5rwTqFgaJpZM4MUoN2 .

Namek commented 7 years ago

It would be worth to ask on gitter channel whether you're the only one that would feel the benefit. I'm not sure about hardness/performance of this and I'm not against it.

DaanVanYperen commented 7 years ago

There's something to say both against and for allowing logic in entity. Performance, purism, API focus, etc.

Entity is more of a legacy thing right now, for short term probably best to build something on top of the ints. The fluid API has similar requirements; add convenience methods to interact with an entity.

Example solution could be decorating your entities with a wrapper, and using custom systems:

public abstract class MyEntityIteratingSystem extends IteratingSystem {

    public FluidIteratingSystem(Aspect.Builder aspect) {
        super(aspect);
    }

    @Override
    protected void process(int id) {
        process(MyEntityHelper.AsMyEntity(id));
    }

    protected abstract void process(AsMyEntity e);
}

Example factory:

class MyEntityHelper {
protected Bag es = new Bag(128);
public static MyEntity AsMyEntity(int entityId) {
    MyEntity  e = (MyEntity ) es.safeGet(entityId);
    if ( e == null ) { e = new MyEntity ().init(this,entityId); es.set(entityId, e); };
    return e;
  }
}

It can lead to calls to MyEntityHelper.MyEntity spread throughout your code, but with a static import and a short name the convenience wins it imo E(id).pos(10,10).anim("dog");

Check out E.java and SuperMapper.java generated while compiling any fluid game for a more in depth example (for example https://github.com/DaanVanYperen/odb-icleantoilet). More about fluid API here https://github.com/junkdog/artemis-odb/wiki/Fluid-Entities

DaanVanYperen commented 7 years ago

@junkdog i'm still looking for a way to gracefully integrate fluid entities into things like system class hierarchy without watering down artemis-odb performance goals.

What about converting odb-core in int only, and providing an extra module with generic typed world/systems and a entity producer strategy? Would allow some sugar like what @xaguzman is looking for and deal with multi threading issues as well.

Edit: Working on PoC :p

DaanVanYperen commented 7 years ago

@junkdog proposal here: https://github.com/junkdog/artemis-odb/pull/499

DaanVanYperen commented 6 years ago

Closing as 'per design' for now. If we ever revisit #499 could serve as a launchpad.