Zoeken…


Opmerkingen

Ashley Entity System is een Entity System-bibliotheek die wordt beheerd door de LibGDX-organisatie en is zeer geschikt voor game-ontwikkeling. Het hangt af van LibGDX-nutsklassen, maar kan met wat werk worden gebruikt met andere Java-spelframeworks die niet op LibGDX zijn gebaseerd.

Entiteitssystemen bieden een andere manier om gegevens en functionaliteit voor grote sets objecten te beheren zonder de objectklassen rijk te maken aan overerving.

Het gebruik van Ashley kan een nuttige benadering zijn voor diegenen die op zoek zijn naar een objectmodelleringsbenadering zoals Unity biedt, maar met de scope van een framework in plaats van een game-engine.

Een component maken

Componenten zijn eenvoudigweg instanties die de Ashley-componentklasse implementeren.

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

Componentenkaarten bieden een snelle manier om componenten op entiteiten te benaderen. Twee veel voorkomende manieren om uw componentmappen te beheren is om een statische instantie binnen de klasse van uw component te houden of om een klasse / opsomming te hebben die alle mappers voor al uw componenten bevat.

Het is niet nodig om een mapper voor een componenttype meer dan één keer aan te geven in uw toepassing.

Een entiteitssysteem maken

Entiteitssystemen zijn hoe u functionele bewerkingen uitvoert op sets van entiteiten. Aan componenten zou doorgaans geen logica moeten worden gekoppeld die bewustzijn van gegevens of de status van andere componentinstanties inhoudt, aangezien dat de taak van een entiteitssysteem is. Een entiteitssysteem kan niet bij meer dan één motor tegelijk worden geregistreerd.

Entiteitssystemen mogen niet meer dan één type functie uitvoeren. Een MovementSystem moet alleen positionering en dergelijke verwerken, terwijl zoiets als een RenderSystem de tekening van entiteiten moet verwerken.

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

Soms is het handig om uw EntitySystems uit te breiden met extra functionaliteit zoals die in EntityListeners, zodat u alleen de soorten entiteiten bijhoudt waarop u wilt werken, in plaats van elke cyclus over alle entiteiten in de motor te itereren. EntityListeners worden geactiveerd wanneer een entiteit wordt toegevoegd aan dezelfde engine waarop het systeem is geregistreerd.

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

Het bijhouden van een subset van entiteiten die het systeem te allen tijde verwerkt, kan ook optimaal zijn, omdat u een bepaalde entiteit uit de verwerking van dat systeem kunt verwijderen zonder de bijbehorende component te verwijderen of desgewenst uit de motor als geheel te verwijderen.

Een gesorteerd entiteitssysteem creëren

Een eenvoudig EntitySystem dat elke entiteit van een bepaalde familie in de door een comparator opgegeven volgorde verwerkt en processEntity() voor elke entiteit EntitySystem telkens wanneer het EntitySystem wordt bijgewerkt. Dit is eigenlijk slechts een gemaksklasse omdat rendering-systemen de neiging hebben om een lijst van entiteiten op een gesorteerde manier te doorlopen. Als u entiteiten toevoegt, wordt de entiteitenlijst opnieuw gebruikt. Roep forceSort() als u uw sorteercriteria hebt gewijzigd. Zie SortedIteratingSystem voor meer informatie

In het onderstaande codevoorbeeld is het beste gebruik hiervoor het renderen van uw sprites in een gesorteerde volgorde door 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);
        }
    }

}

Creëren van een interval herhalend systeem

Een eenvoudig EntitySystem dat een familie van entiteiten niet één keer per frame, maar na een bepaald interval verwerkt. Entiteitsverwerkingslogica moet in processEntity(Entity) worden geplaatst. Zie IntervalIteratingSystem voor meer informatie

In de onderstaande code voorbeeld, de beste gebruik hiervoor is de fysica wereld stap.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow