System
至System
目前,我正在使用ashley框架开发CharacterSystem
,GunSystem
,BulletSystem
。我的问题是我不知道这是否是system
与其他system
对话的正确方式。
我的CharacterSystem
方法onProcessEntity
在character
attack
被触发后我使用了getEngine().getSystem(GunSystem.class).trigger(true)
而在GunSystem
内我有一个方法生成Bullet
的实体。虽然BulletSystem
可以在镜头外处理身体的释放。
子问题使用ECS框架创建Bullet
class
的正确方法是什么?
答案 0 :(得分:2)
我从未将Ashley用作ECS,但通常Systems
不应该相互通信。
原因:当Systems
进行通信时,它们不会相互独立。独立Systems
允许您自由添加和删除它们,而不必担心代码中断。当缺少重要的Systems
时,游戏逻辑可能会中断。
有Factory
(类)确实创建了子弹实体。然后在每个Factory
中使用System
,这可以构建新的子弹实体。
答案 1 :(得分:2)
我在游戏和最近的项目(https://github.com/basimkhajwal/LSD)中使用了Ashley ECS,我遇到了类似的情况。我的方法可能不是标准的,它可能会在不同的项目设置中出现问题,但使用事件队列对我来说是一个很好的解决方案。
从本质上讲,您有一个enum
(在我的情况下为GameEvent
),可以处理需要传递的所有不同事件,例如PLAYER_DIED
,LAUNCH_PLAYER
等等。我使用Ashley的signals
接口创建了一个简单的排队事件存储库,系统可以在每个tick上进行轮询。如下:
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
类中,加载Ashley Engine
并用系统填充它的那个,我有一个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);
}
}
}
希望这是有道理的,也可以随意阅读我的项目代码以获得更多示例用法。