libgdx (Ashley Framework ECS) - 将系统与另一个系统对话的正确方法是什么?

ron*_*ipt 2 java box2d libgdx

SystemSystem

目前我正在开发CharacterSystem, GunSystem,BulletSystem使用 ashley 框架。我的问题是我不知道这是否是与system其他人交谈的正确方式system

我使用的CharacterSystem方法onProcessEntitycharacter attack触发时使用,getEngine().getSystem(GunSystem.class).trigger(true)并且在里面GunSystem我有一个方法是Bullet. 当BulletSystem手柄在相机外时释放身体。

子问题Bullet class使用 ECS 框架创建的正确方法是什么?

小智 5

我在游戏中经常使用 Ashley ECS,在最近的一个项目 ( https://github.com/basimkhajwal/LSD ) 中,我遇到了类似的情况。我的方法可能不是标准的,它可能会出现在不同的项目设置中但使用事件队列的问题对我来说是一个很好的解决方案。

本质上,您有一个enum(在我的情况下GameEvent)处理需要传递的所有不同事件,例如PLAYER_DIEDLAUNCH_PLAYER等等。我使用 Ashley 的signals界面创建了一个简单的事件队列存储,系统可以在每个滴答声上轮询这些事件。如下:

public class EventQueue implements Listener<GameEvent> {

    private PriorityQueue<GameEvent> eventQueue;

    public EventQueue() {
        eventQueue = new PriorityQueue<GameEvent>();
    }

    public GameEvent[] getEvents() {
        GameEvent[] events = eventQueue.toArray(new GameEvent[0]);
        eventQueue.clear();
        return events;
    }

    public GameEvent poll() {
        return eventQueue.poll();
    }

    @Override
    public void receive(Signal<GameEvent> signal, GameEvent event) { 
        eventQueue.add(event);
    }

}
Run Code Online (Sandbox Code Playgroud)

接下来,在我的GameWorld班级中,加载 AshleyEngine并用系统填充它的班级,我有一个单曲Signal<GameEvent>,它是我的事件队列的主要支柱。在这里,像Listener<T>Signal<T>已经是 Ashley 的一部分。

然后,某些系统需要能够触发此信号/从中接收事件,以便它们Signal在构造函数中使用此类。然后EntitySystem可以绑定一个侦听器或触发事件,然后将这些事件传递给其他侦听器。例如我的LaserSystem班级(简化):

public class LaserSystem extends IteratingSystem implements Disposable, ContactListener {

    ...    

    private Signal<GameEvent> gameEventSignal;
    private EventQueue eventQueue;

    public LaserSystem(Signal<GameEvent> gameEventSignal) {
        super(Family.all(LaserComponent.class).get(), Constants.SYSTEM_PRIORITIES.LASER);

        this.gameEventSignal = gameEventSignal;

        eventQueue = new EventQueue();
        gameEventSignal.add(eventQueue);
    }

    ...

    @Override
    public void beginContact(Contact contact) {

        ....

        LaserComponent laserComponent = laserMapper.get(laser);
        laserComponent.updateLaser = true;

        if (other.getComponent(PlayerComponent.class) != null) {
            gameEventSignal.dispatch(GameEvent.LASER_COLLISION);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这是有道理的,也可以随意阅读我的项目代码以获取更多示例用法。