Description
What problem does this solve or what need does it fill?
- The problem of system responses to ongoing events (the system will not respond if it was triggered at stages before the event was generated).
- Systems are now dealing with the events themselves.
What solution would you like?
Each event has a set of components, systems waiting for events are transferred to the class of event handlers and are called only when there is an event with a suitable set of components.
For example, the event when the user pressed a key on the keyboard can have the components KeyPress(usize)
, UserInput
, the cursor movement event UserInput
, Cursor
, Position(usize, usize)
, and an event generated by some system, for example, the player "jumped" - PlayerEvent
, Jump{vector: Vec2}
Naturally, this can be connected to an existing ecs and the system will be called with a set of components from the world and a set of components from an event.
Here is an example of pseudocode (as I see it), I think those who read this perfectly understand the capabilities of ecs
without this example, but still
/// This system will only be called when there are events with KeyPress, or periodically called with an empty iterator
fn jump_handler(event_server: &mut EventServer, events: EventQuery<KeyPress>, player_pos: Query<&mut Position, Player>)
{
for event in events.iter()
{
// ASCII `Space` code is 32
if event.0 == 32
{
event_server.spawn().insert(PlayerEvent::default()).insert(Jump{ vector: Vec2::new(0.0, 1.0, 0.0)});
player_pos.iter().next().unwrap().add(Vec2::new(0.0, 1.0, 0.0));
}
}
}
/// This system will only be called when there are jump events or periodically called with an empty iterator
fn jumper_achievment(jump_counter: ResMut<JumpCounter>, events: EventQuery<Jump>, event_server: &mut EventServer)
{
jump_counter.add(events.iter().len())
if jump_counter >= 100 { event_server.spawn().insert(Achievment::Jumper) }
}
What alternative(s) have you considered?
The current alternatives with signal and receiver systems look good, but ecs
will give flexibility in my opinion
I also considered two options for calling systems:
- immediate call of associated systems when an event occurs
- accumulation of events and their postponed call (current system with stages)
While I'm thinking about it, and it seems to me the option with the accumulation of events is safer and easier to implement.
Additional context
I wrote a small python example (as a prototype). You can see the link