//! Animates a sprite in response to a keyboard event. //! //! See `sprite_sheet.rs` for an example where the sprite animation loops indefinitely. use std::time::Duration; use bevy::input::common_conditions::input_just_pressed; use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) // prevents blurry sprites .add_systems(Startup, setup) .add_systems(Update, execute_animations) .add_systems( Update, ( // press the right arrow key to animate the right sprite trigger_animation::.run_if(input_just_pressed(KeyCode::ArrowRight)), // press the left arrow key to animate the left sprite trigger_animation::.run_if(input_just_pressed(KeyCode::ArrowLeft)), ), ) .run(); } // This system runs when the user clicks the left arrow key or right arrow key fn trigger_animation(mut query: Query<&mut AnimationConfig, With>) { // we expect the Component of type S to be used as a marker Component by only a single entity let mut animation = query.single_mut(); // we create a new timer when the animation is triggered animation.frame_timer = AnimationConfig::timer_from_fps(animation.fps); } #[derive(Component)] struct AnimationConfig { first_sprite_index: usize, last_sprite_index: usize, fps: u8, frame_timer: Timer, } impl AnimationConfig { fn new(first: usize, last: usize, fps: u8) -> Self { Self { first_sprite_index: first, last_sprite_index: last, fps, frame_timer: Self::timer_from_fps(fps), } } fn timer_from_fps(fps: u8) -> Timer { Timer::new(Duration::from_secs_f32(1.0 / (fps as f32)), TimerMode::Once) } } // This system loops through all the sprites in the `TextureAtlas`, from `first_sprite_index` to // `last_sprite_index` (both defined in `AnimationConfig`). fn execute_animations( time: Res