Sök…


Anmärkningar

Ashley Entity System är ett Entity System-bibliotek som hanteras under LibGDX-organisationen och är och väl lämpad för spelutveckling. Det beror på LibGDX-hjälpklasser, men kan användas med andra Java-spelramar som inte är baserade på LibGDX med något arbete.

Enhetssystem ger ett annat sätt att hantera data och funktionalitet gentemot stora uppsättningar objekt utan att behöva göra objektklasserna rika med arv.

Att använda Ashley kan vara ett användbart tillvägagångssätt för dem som söker ett objektmodelleringssätt som Unity tillhandahåller, men med omfattningen av ett ramverk istället för spelmotor.

Skapa en komponent

Komponenter är helt enkelt fall som implementerar Ashley-komponentklassen.

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

Komponentkartor ger ett snabbt sätt att komma åt komponenter på enheter. Två vanliga sätt att hantera dina komponentkartor är att antingen behålla en statisk instans inom komponentens klass, eller att ha en klass / enum som innehåller alla kartläggningar för alla dina komponenter.

Det finns ingen anledning att deklarera en mapper för en komponenttyp mer än en gång i din ansökan.

Skapa ett enhetssystem

Enhetssystem är hur du utför funktionella operationer på uppsättningar av enheter. Komponenter bör vanligtvis inte ha logik förknippad med dem som innebär medvetenhet om data eller tillstånd för andra komponentfall, eftersom det är jobbet för ett enhetssystem. Ett enhetssystem kan inte registreras på mer än en motor åt gången.

Enhetssystem ska inte utföra mer än en typ av funktion. Ett MovementSystem ska bara hantera positionering och liknande, medan något som ett RenderSystem ska hantera ritningen av enheter.

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

Ibland är det bra att utöka dina EntitySystems med ytterligare funktionalitet som den som finns i EntityListeners så att du bara håller reda på vilka typer av enheter du vill arbeta med, istället för att iterera över alla enheter i motorn varje cykel. EntityListeners utlöses varje gång en enhet läggs till i samma motor som systemet är registrerat till.

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

Att hålla reda på en delmängd av enheter som systemet bearbetar hela tiden kan också vara optimalt, eftersom du kan ta bort en viss enhet från systemets bearbetning utan att behöva ta bort den associerande komponenten eller ta bort dem från motorn i sin helhet om så önskas.

Skapa ett sorterat enhetssystem

Ett enkelt EntitySystem som behandlar varje enhet i en viss familj i den ordning som specificeras av en comparator och kallar processEntity() för varje enhet varje gång EntitySystem uppdateras. Detta är egentligen bara en bekvämlighetsklass eftersom återgivningssystem tenderar att iterera över en lista över enheter på ett sorterat sätt. Lägga till enheter kommer att leda till att entitetslistan används. Ring forceSort() om du ändrade dina sorteringskriterier. För mer information, se SortedIteratingSystem

I kodexemplet nedan är den bästa användningen för detta rendering av dina sprites i en sorterad ordning efter 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);
        }
    }

}

Skapa ett intervallterteringssystem

Ett enkelt EntitySystem som behandlar en familj med enheter inte en gång per ram, men efter ett givet intervall. Enhetsbehandlingslogik ska placeras i processEntity(Entity) . För mer information, se IntervalIteratingSystem

I nedanstående kodexempel är den bästa användningen för fysik världen steg.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow