Suche…


Bemerkungen

Ashley Entity System ist eine Entity System-Bibliothek, die unter der LibGDX-Organisation verwaltet wird und sich für die Entwicklung von Spielen eignet. Dies hängt von den LibGDX-Dienstprogrammklassen ab, kann jedoch mit einigen anderen Java-Game-Frameworks verwendet werden, die nicht auf LibGDX basieren.

Entitätssysteme bieten eine andere Möglichkeit zum Verwalten von Daten und Funktionen für große Objektgruppen, ohne dass die Objektklassen mit Vererbung reich gemacht werden müssen.

Die Verwendung von Ashley kann für diejenigen hilfreich sein, die nach einem Objektmodellierungsansatz suchen, der von Unity bereitgestellt wird, jedoch mit dem Rahmen eines Frameworks anstelle einer Spiel-Engine.

Eine Komponente erstellen

Komponenten sind einfach Instanzen, die die Ashley-Komponentenklasse implementieren.

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

Komponentenkarten bieten eine schnelle Möglichkeit, auf Komponenten in Entitäten zuzugreifen. Es gibt zwei gängige Methoden zum Verwalten Ihrer Komponentenzuordnungen, indem Sie entweder eine statische Instanz in der Klasse Ihrer Komponente behalten oder über eine Klasse / ein Enum verfügen, die alle Mapper für alle Komponenten enthält.

Es ist nicht erforderlich, einen Mapper für einen Komponententyp mehr als einmal in Ihrer Anwendung zu deklarieren.

Erstellen eines Entitätssystems

Entitätssysteme führen Sie aus, um funktionale Operationen für Entitätsgruppen durchzuführen. Komponenten sollte normalerweise keine Logik zugeordnet sein, die die Kenntnis der Daten oder des Zustands anderer Komponenteninstanzen erfordert, da dies die Aufgabe eines Entitätssystems ist. Ein Entitätssystem kann nicht für mehr als eine Engine gleichzeitig registriert werden.

Entitätssysteme sollten nicht mehr als eine Art von Funktion ausführen. Ein MovementSystem sollte nur die Positionierung und dergleichen behandeln, während ein RenderSystem etwa das Zeichnen von Entitäten übernehmen sollte.

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

In manchen Fällen ist es hilfreich, EntitySystems um zusätzliche Funktionen wie die in EntityListener vorhandenen zu erweitern, sodass Sie nur die Entitätstypen nachverfolgen können, mit denen Sie arbeiten möchten, anstatt alle Entitäten in der Engine in jedem Zyklus zu durchlaufen. EntityListener werden immer dann ausgelöst, wenn eine Entität derselben Engine hinzugefügt wird, bei der das System registriert ist.

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

Das Verfolgen einer Untergruppe von Entitäten, die das System zu jeder Zeit verarbeitet, kann auch optimal sein, da Sie eine bestimmte Entität aus der Verarbeitung dieses Systems entfernen können, ohne die zugehörige Komponente entfernen zu müssen oder sie ganz aus der Engine insgesamt zu entfernen.

Sortiertes Entitätssystem erstellen

Eine einfache EntitySystem , das jede Einheit aus einer Familie in der Größenordnung von einem bestimmten verarbeitet comparator und ruft processEntity() für jede Einheit die jedes Mal EntitySystem aktualisiert wird. Dies ist wirklich nur eine Convenience-Klasse, da Rendering-Systeme dazu neigen, eine Liste von Entitäten in einer sortierten Weise zu durchlaufen. Durch das Hinzufügen von Entitäten wird die Entitätsliste neu sortiert. Rufen Sie forceSort() wenn Sie Ihre Sortierkriterien geändert haben. Weitere Informationen finden Sie unter SortedIteratingSystem

In dem folgenden Codebeispiel wird die Wiedergabe Ihrer Sprites in einer sortierten Reihenfolge nach zindex am besten verwendet.

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);
        }
    }

}

Erstellen eines Intervalliterationssystems

Ein einfaches EntitySystem , das eine EntitySystem nicht pro Frame, sondern nach einem bestimmten Intervall verarbeitet. Die Entity-Verarbeitungslogik sollte in processEntity(Entity) . Weitere Informationen finden Sie unter IntervalIteratingSystem

Im folgenden Codebeispiel ist die beste Verwendung für das der Physik Welt Schritt.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow