Ricerca…


Osservazioni

Ashley Entity System è una libreria di sistemi Entity gestita dall'organizzazione LibGDX, adatta per lo sviluppo di giochi. Dipende dalle classi di utilità LibGDX, ma può essere utilizzato con altri framework di giochi Java non basati su LibGDX con un po 'di lavoro.

I sistemi Entity forniscono un modo diverso di gestire dati e funzionalità verso insiemi di oggetti di grandi dimensioni senza dover rendere le classi oggetto ricche di ereditarietà.

Utilizzare Ashley potrebbe essere un approccio utile per chi cerca un approccio di modellazione di oggetti come fornisce Unity, ma con l'ambito di un framework al posto del motore di gioco.

Creazione di un componente

I componenti sono semplicemente istanze che implementano la classe del 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;
}

Le mappe dei componenti forniscono un modo rapido per accedere ai componenti sulle entità. Due modi comuni per gestire le mappe dei componenti consiste nel mantenere un'istanza statica all'interno della classe del componente o in una classe / enum che contiene tutti i programmi di definizione per tutti i componenti.

Non è necessario dichiarare un mapper per un tipo di componente più di una volta nell'applicazione.

Creazione di un sistema di entità

I sistemi di entità sono il modo in cui si eseguono operazioni funzionali su gruppi di entità. I componenti in genere non dovrebbero avere una logica associata a essi che implichi la consapevolezza dei dati o dello stato di altre istanze del componente, poiché questo è il lavoro di un sistema di entità. Un sistema di entità non può essere registrato su più di un motore alla volta.

I sistemi di entità non devono eseguire più di un tipo di funzione. Un MovementSystem dovrebbe gestire solo il posizionamento e simili, mentre qualcosa come un RenderSystem dovrebbe gestire il disegno di entità.

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 volte è utile estendere il tuo EntitySystems con funzionalità aggiuntive come quelle che si trovano in EntityListeners in modo da tenere traccia solo dei tipi di entità su cui desideri operare, invece di iterare su tutte le entità nel motore ogni ciclo. EntityListeners vengono attivati ​​ogni volta che un'entità viene aggiunta allo stesso motore su cui è registrato il 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
            ...
        }
    }
}

Anche tenere traccia di un sottoinsieme di entità che il sistema elabora in ogni momento può essere ottimale, in quanto è possibile rimuovere una particolare entità dall'elaborazione di quel sistema senza dover rimuovere il componente di associazione o rimuoverle dal motore nel suo insieme se lo si desidera.

Creazione di un sistema di entità ordinate

Un EntitySystem semplice che elabora ciascuna entità di una determinata famiglia nell'ordine specificato da un comparator e chiama processEntity() per ogni entità ogni volta che EntitySystem viene aggiornato. Questa è davvero solo una classe di convenienza in quanto i sistemi di rendering tendono a scorrere su un elenco di entità in modo ordinato. L'aggiunta di entità farà ricorrere alla lista delle entità. Chiama forceSort() se hai modificato i criteri di ordinamento. Per maggiori informazioni, vedere SortedIteratingSystem

Nell'esempio di codice seguente, il miglior utilizzo per questo il rendering dei tuoi sprite in un ordine ordinato da 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);
        }
    }

}

Creazione di un sistema di iterazione a intervalli

Un semplice EntitySystem che elabora una famiglia di entità non una sola volta per fotogramma, ma dopo un dato intervallo. La logica di elaborazione delle entità deve essere inserita in processEntity(Entity) . Per maggiori informazioni, vedere IntervalIteratingSystem

Nell'esempio di codice seguente, il miglior utilizzo per questo è il passo del mondo fisico.

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow