Buscar..


Observaciones

Ashley Entity System es una biblioteca de Entity System que se administra bajo la organización LibGDX y es adecuada para el desarrollo de juegos. Depende de las clases de utilidad LibGDX, pero puede usarse con otros marcos de juegos Java que no estén basados ​​en LibGDX con algo de trabajo.

Los sistemas de entidades proporcionan una forma diferente de administrar los datos y la funcionalidad hacia grandes conjuntos de objetos sin tener que enriquecer las clases de objetos con herencia.

Utilizar a Ashley podría ser un enfoque útil para aquellos que buscan un enfoque de modelado de objetos como el que proporciona Unity, pero con el alcance de un marco en lugar de un motor de juego.

Creando un componente

Los componentes son simplemente instancias que implementan la clase de componente Ashley.

import com.badlogic.ashley.core.Component;
import com.badlogic.ashley.core.ComponentMapper;

public class Position implements Component {
    public static final ComponentMapper<Position> Map = 
                                 ComponentMapper.getFor(Position.class);

    public float x = 0f, 
                 y = 0f;
}

Los mapas de componentes proporcionan una forma rápida de acceder a los componentes de las entidades. Dos formas comunes de administrar sus mapas de componentes es mantener una instancia estática dentro de la clase de su componente o tener una clase / enumeración que contenga todos los mapeadores para todos sus componentes.

No es necesario declarar un asignador para un tipo de componente más de una vez en su aplicación.

Creación de un sistema de entidades

Los sistemas de entidades son la forma en que realiza operaciones funcionales en conjuntos de entidades. Normalmente, los componentes no deben tener una lógica asociada que involucre el conocimiento de los datos o el estado de otras instancias de componentes, ya que ese es el trabajo de un sistema de entidades. Un sistema de entidad no se puede registrar en más de un motor a la vez.

Los sistemas de entidades no deben realizar más de un tipo de función. Un MovementSystem solo debería manejar el posicionamiento y similares, mientras que algo como un RenderSystem debería manejar el dibujo de entidades.

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
            ...
        }
    }

A veces es útil extender sus EntitySystems con una funcionalidad adicional como la que se encuentra en los EntityListeners para que solo haga un seguimiento de los tipos de entidades en las que desea operar, en lugar de iterar sobre todas las entidades en el motor en cada ciclo. Los EntityListeners se activan cada vez que se agrega una entidad al mismo motor en el que está registrado el sistema.

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
            ...
        }
    }
}

El seguimiento de un subconjunto de entidades que el sistema procesa en todo momento también puede ser óptimo, ya que puede eliminar una entidad particular del procesamiento de ese sistema sin tener que eliminar el componente asociado o eliminarlos del motor en su totalidad si así lo desea.

Creación de un sistema de entidades ordenadas

Un EntitySystem simple que procesa cada entidad de una familia dada en el orden especificado por un comparator y llama a processEntity() para cada entidad cada vez que se actualiza el EntitySystem . Esto es realmente solo una clase de conveniencia ya que los sistemas de representación tienden a iterar sobre una lista de entidades de una manera ordenada. Agregar entidades hará que la lista de entidades se vuelva a ordenar. Llame a forceSort() si cambió sus criterios de clasificación. Para obtener más información, consulte Sistema de ordenación

En el ejemplo de código a continuación, el mejor uso para esto es la representación de sus sprites en un orden ordenado por zindex.

public class SpriteComponent implements Component {
     public TextureRegion region;
     public int z = 0;
}

public class Mapper {
     public static ComponentMapper<SpriteComponent> sprite = ComponentMapper.getFor(SpriteComponent.class);
}

public class RenderingSystem extends SortedIteratingSystem {

    public RenderingSystem () {
         super(Familly.all(SpriteComponent.class).get(), new ZComparator())
    }

    public void processEntity(Entity entity, float deltaTime) {
         if(checkZIndexHasChangeValue()) {
              forceSort();
         }
    }

    private static class ZComparator implements Comparator<Entity> {
        @Override
        public int compare(Entity entityA, Entity entityB) {
            return (int)Math.signum(Mapper.sprite.get(entityA).z - Mapper.sprite.get(entityB).z);
        }
    }

}

Creación de un sistema de iteración de intervalos

Un EntitySystem simple que procesa una Familia de entidades no una vez por trama, sino después de un intervalo dado. La lógica de procesamiento de la entidad se debe colocar en processEntity(Entity) . Para obtener más información, consulte IntervalIteratingSystem

En el ejemplo de código a continuación, el mejor uso para esto es el paso del mundo de la física.

public class Constants {
     public final static float TIME_STEP = 1 / 60.0f; // 60 fps
     public final static int VELOCITY_ITERATIONS = 6;
     public final static int POSITION_ITERATIONS = 2;
}

public class PhysicsSystem extends IntervalIteratingSystem {
    public PhysicsSystem () {
         super(Family.all(PhysicsComponent.class), Constants.TIME_STEP);
    }

    @Override
    protected void processEntity(Entity entity) {
         // process the physics component here with an interval of 60fps
    }

    @Override
    protected void updateInterval() {
        WorldManager.world.step(Constants.TIME_STEP, Constants.VELOCITY_ITERATIONS, Constants.POSITION_ITERATIONS);
        super.updateInterval();
    }

}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow