Skip to main content

delayed_commands/
delayed_commands.rs

1//! This example demonstrates how to send commands which will take effect after a period of time.
2//!
3//! We've chosen to demonstrate this effect through the creation of a grid of clickable,
4//! with "ripples" created when you click.
5
6use bevy::prelude::*;
7
8fn main() {
9    App::new()
10        .add_plugins(DefaultPlugins)
11        .add_systems(Startup, spawn)
12        .add_observer(click)
13        .run();
14}
15
16#[derive(Component)]
17struct BlinkySquare;
18
19const SQUARE_SIZE: Vec2 = Vec2::splat(45.0);
20
21fn spawn(mut commands: Commands) {
22    commands.spawn(Camera2d);
23    for x in -5..=5 {
24        for y in -5..=5 {
25            commands.spawn((
26                BlinkySquare,
27                Transform::from_xyz(x as f32 * 50.0, y as f32 * 50.0, 0.0),
28                Sprite::from_color(Color::BLACK, SQUARE_SIZE),
29            ));
30        }
31    }
32}
33
34fn click(
35    click: On<Pointer<Click>>,
36    mut commands: Commands,
37    squares: Query<(Entity, &Transform), With<BlinkySquare>>,
38    cameras: Query<(&Camera, &GlobalTransform)>,
39) {
40    let (camera, camera_transform) = cameras.single().unwrap();
41    let mut delayed = commands.delayed();
42    for (entity, transform) in squares.iter() {
43        // convert the pointer position to world position
44        let mouse_world_pos = camera
45            .viewport_to_world_2d(camera_transform, click.pointer_location.position)
46            .unwrap();
47
48        // delay the blinkiness by distance to cursor
49        let dist = mouse_world_pos.distance(transform.translation.truncate());
50        let delay = dist / 1000.0;
51        delayed
52            .secs(delay)
53            .entity(entity)
54            .insert(Sprite::from_color(Color::WHITE, SQUARE_SIZE));
55        delayed
56            .secs(delay + 0.1)
57            .entity(entity)
58            .insert(Sprite::from_color(Color::BLACK, SQUARE_SIZE));
59    }
60}