Recherche…


Remarques

Ashley Entity System est une bibliothèque Entity System gérée sous l' organisation LibGDX et parfaitement adaptée au développement de jeux. Cela dépend des classes d'utilitaires LibGDX, mais peut être utilisé avec d'autres frameworks de jeu Java non basés sur LibGDX.

Les systèmes d'entités offrent une manière différente de gérer les données et les fonctionnalités vers de grands ensembles d'objets sans avoir à rendre les classes d'objets riches en héritage.

Utiliser Ashley pourrait être une approche utile pour ceux qui recherchent une approche de modélisation d’objets comme celle fournie par Unity, mais avec la portée d’un framework au lieu d’un moteur de jeu.

Créer un composant

Les composants sont simplement des instances qui implémentent la classe de composants 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;
}

Les mappes de composants permettent d'accéder rapidement aux composants des entités. Deux méthodes courantes pour gérer vos mappes de composants consistent à conserver une instance statique dans la classe de votre composant ou à avoir une classe / enum contenant tous les mappeurs de tous vos composants.

Il n'est pas nécessaire de déclarer un mappeur pour un type de composant plus d'une fois dans votre application.

Création d'un système d'entités

Les systèmes d'entités sont la manière dont vous effectuez des opérations fonctionnelles sur des ensembles d'entités. Les composants ne doivent généralement pas être associés à une logique impliquant la connaissance des données ou de l'état des autres instances du composant, car cela est la tâche d'un système d'entités. Un système d'entités ne peut pas être enregistré sur plusieurs moteurs à la fois.

Les systèmes d'entités ne doivent pas effectuer plus d'un type de fonction. Un MovementSystem ne devrait gérer que le positionnement, etc., tandis que quelque chose comme RenderSystem devrait gérer le dessin des entités.

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

Il est parfois utile d'étendre votre EntitySystems avec des fonctionnalités supplémentaires telles que celles trouvées dans EntityListeners, afin de ne garder en mémoire que les types d'entités sur lesquelles vous souhaitez travailler, au lieu de les parcourir tous les cycles. Les EntityListeners sont déclenchés à chaque fois qu'une entité est ajoutée au même moteur que celui sur lequel le système est enregistré.

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

Le suivi d'un sous-ensemble d'entités que le système traite à tout moment peut également être optimal, car vous pouvez supprimer une entité particulière du traitement de ce système sans avoir à supprimer le composant associé ou à le retirer du moteur dans son ensemble.

Création d'un système d'entités triées

Un EntitySystem simple qui traite chaque entité d'une famille donnée dans l'ordre spécifié par un comparator et appelle processEntity() pour chaque entité à chaque mise à jour d' EntitySystem . Ce n'est vraiment qu'une classe de commodité, car les systèmes de rendu ont tendance à parcourir une liste d'entités de manière triée. L'ajout d'entités entraînera le recours à la liste d'entités. Appelez forceSort() si vous avez modifié vos critères de tri. Pour plus d'informations, voir SortedIteratingSystem

Dans l'exemple de code ci-dessous, la meilleure utilisation pour cela est le rendu de vos images-objets dans un ordre trié par 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);
        }
    }

}

Création d'un système d'itération d'intervalle

Un EntitySystem simple qui traite une famille d'entités non pas une fois par image, mais après un intervalle donné. La logique de traitement des entités doit être placée dans processEntity(Entity) . Pour plus d'informations, voir IntervalIteratingSystem

Dans l'exemple de code ci-dessous, la meilleure utilisation est l'étape du monde de la physique.

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow