libgdx Ashley Entity System Creating an Entity System


Example

Entity systems are how you perform functional operations on sets of entities. Components should typically not have logic associated with them that involves awareness of data or state of other component instances, as that is the job of an entity system. An entity system can not be registered to more than one engine at a time.

Entity systems should not perform more than one type of function. A MovementSystem should only handle positioning and the like, while something like a RenderSystem should handle the drawing of entities.

import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.EntitySystem;
import com.badlogic.ashley.core.Family;

public class MovementSystem extends EntitySystem {
    //the type of components necessary for entities to have to be operated on
    private static final Family FAMILY = Family.all(Position.class).get();

    public MovementSystem () {
        super();
    }

    /**
     * The update method called every tick.
     * @param deltaTime The time passed since last frame in seconds.
     */
    public void update (float deltaTime) {
        for (Entity e : this.getEngine().getEntitiesFor(FAMILY)) {
            Position pos = Position.Map.get(e);
            
            // do entity movement logic on component
            ...
        }
    }

Sometimes it's helpful to extend your EntitySystems with additional functionality like that found in EntityListeners so you keep track of only the types of entities you wish to operate on, instead of iterating over all entities in the engine every cycle. EntityListeners are triggered whenever an entity is added to the same engine that the system is registered to.

import com.badlogic.ashley.core.EntityListener;
import com.badlogic.gdx.utils.Array;

public class MovementSystem extends EntitySystem implements EntityListener {
    Array<Entity> moveables = new Array<>();
    ...

    @Override
    public void entityAdded(Entity entity) {
        if (FAMILY.matches(entity)) {
            moveables.add(entity);
        }
    }

    @Override
    public void entityRemoved(Entity entity) {
        if (FAMILY.matches(entity)) {
            moveables.removeValue(entity, true);
        }
    }

    public void update (float deltaTime) {
        for (Entity e : this.moveables) {
            Position pos = Position.Map.get(e);
            
            // do entity movement logic on component
            ...
        }
    }
}

Keeping track of a subset of entities that the system processes at all times can also be optimal, as you can remove a particular entity from that system's processing without having to remove the associating component or removing them from the engine as a whole if so desired.