libgdx(Ashley Framework ECS) - 与其他系统交谈系统的正确方式是什么?

问题描述:

SystemSystemlibgdx(Ashley Framework ECS) - 与其他系统交谈系统的正确方式是什么?

目前我使用阿什利框架开发CharacterSystemGunSystemBulletSystem。我的问题是我不知道这是否是system与其他system的正确方式。

CharacterSystem方法onProcessEntitycharacterattack被触发我用getEngine().getSystem(GunSystem.class).trigger(true)GunSystem里面我有一个方法Bullet的生成实体。当在摄像机外部时,BulletSystem处理身体的释放。

sub-question用ECS框架创建Bulletclass的正确方法是什么?

我从未使用过Ashley作为ECS,但通常Systems不应该彼此沟通。

原因:当Systems会沟通时,它们不会彼此独立。独立Systems允许您*添加和删除它们,而不必担心代码中断。当重要的Systems丢失时,游戏逻辑可能会中断。

有一个Factory(类),它创建子弹实体。然后在每个System中使用Factory,它可以构建新的子弹实体。

+0

我使用libgdx,你推荐ECS框架与libgdx一起使用? – ronscript

+0

Ashley或artemis-odb。不知道任何其他ECS。 –

我在游戏和最近的项目中使用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); 
    } 

} 

接下来,我GameWorld类,它加载阿什利Engine,并与系统填充它的人,我有一个这是我的事件队列中的主要骨干。在这里,如Listener<T>,Signal<T>已经是阿什利的一部分。

有些系统需要能够触发这个信号/从它接收事件,所以他们把这个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); 
     } 
    } 
} 

希望这是有道理的,也觉得免费阅读我的项目的代码更用法示例。