libgdx
Ashley Entity System
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 uncomparator
y llama aprocessEntity()
para cada entidad cada vez que se actualiza elEntitySystem
. 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 aforceSort()
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 enprocessEntity(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();
}
}