I am currently trying to use events to signal when the character jumps in my Bevy game. I want the system that handles player inputs to send a JumpedEvent
which can then be received by other systems to perform the appropriate actions (set the correct player animations, velocity, sound, etc.) but the first system to read the event consumes it.
Does Bevy provide a way to read events without consuming them?
Here is my current code:
// Sends a JumpedEvent when the jump key is pressed
fn player_jump_event_system(
keyboard_input: Res<Input<KeyCode>>,
mut jump_events: ResMut<Events<JumpedEvent>>,
mut query: Query<(&Controlled, &mut Jumps)>,
) {
for (controlled, mut jumps) in &mut query.iter() {
if keyboard_input.just_pressed(controlled.jump)
&& jumps.jumps_remaining > 0
{
jumps.jumps_remaining -= 1;
jump_events.send(JumpedEvent {
jump_number: jumps.max_jumps - jumps.jumps_remaining,
});
}
}
}
// This system consumes the JumpedEvent that was sent
fn control_player_jump_system(
jump_events: ResMut<Events<JumpedEvent>>,
mut jump_event_listener: ResMut<JumpedEventListener>,
mut query: Query<(&Controlled, &mut Jumps, &mut Velocity)>,
) {
const PLAYER_JUMP_SPEED: f32 = 450.0;
const MULTI_JUMP_MODIFIER: f32 = 0.9;
// For every jump event, make player jump slightly less high
for jump_event in jump_event_listener.jumped_event_reader.iter(&jump_events)
{
for (_, _, mut velocity) in &mut query.iter() {
*velocity.0.y_mut() = PLAYER_JUMP_SPEED
* MULTI_JUMP_MODIFIER.powi(i32::from(jump_event.jump_number));
}
}
}
// This is the system that cannot receive the event because the above system consumes it
fn select_animation_system(
texture_atlases: Res<Assets<TextureAtlas>>,
jump_events: ResMut<Events<JumpedEvent>>,
mut jump_event_listener: ResMut<JumpedEventListener>,
mut query: Query<(
&Jumps,
&Velocity,
&AnimatedPlayer,
&mut TextureAtlasSprite,
&mut Handle<TextureAtlas>,
)>,
) {
for (_, velocity, animations, mut sprite, mut texture_atlas) in
&mut query.iter()
{
// Check if the player just jumped
let just_jumped = jump_event_listener
.jumped_event_reader
.iter(&jump_events)
.next()
.is_some();
// Omitting irrelevant details...
if just_jumped {
sprite.index = 0;
}
}
}