libgdx(Ashley Framework ECS) - 与其他系统交谈系统的正确方式是什么?
System
到System
libgdx(Ashley Framework ECS) - 与其他系统交谈系统的正确方式是什么?
目前我使用阿什利框架开发CharacterSystem
,GunSystem
,BulletSystem
。我的问题是我不知道这是否是system
与其他system
的正确方式。
我CharacterSystem
方法onProcessEntity
当character
attack
被触发我用getEngine().getSystem(GunSystem.class).trigger(true)
和GunSystem
里面我有一个方法Bullet
的生成实体。当在摄像机外部时,BulletSystem
处理身体的释放。
sub-question用ECS框架创建Bullet
class
的正确方法是什么?
我从未使用过Ashley作为ECS,但通常Systems
不应该彼此沟通。
原因:当Systems
会沟通时,它们不会彼此独立。独立Systems
允许您*添加和删除它们,而不必担心代码中断。当重要的Systems
丢失时,游戏逻辑可能会中断。
有一个Factory
(类),它创建子弹实体。然后在每个System
中使用Factory
,它可以构建新的子弹实体。
我在游戏和最近的项目中使用Ashley ECS相当多(https://github.com/basimkhajwal/LSD)我遇到过类似的情况。我的方法可能不是标准的,它可能会在不同的项目设置中发生,但使用事件队列对我来说是一个很好的解决方案。
从本质上说,你有一个enum
(在我的情况GameEvent
)负责处理所有不同的事件需要传递周围像PLAYER_DIED
,LAUNCH_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);
}
}
}
希望这是有道理的,也觉得免费阅读我的项目的代码更用法示例。
我使用libgdx,你推荐ECS框架与libgdx一起使用? – ronscript
Ashley或artemis-odb。不知道任何其他ECS。 –