state_scoped/
state_scoped.rs1use bevy::prelude::*;
8
9fn main() {
10 App::new()
11 .add_plugins(DefaultPlugins)
12 .init_state::<GameState>()
13 .add_systems(Startup, setup_camera)
14 .add_systems(OnEnter(GameState::A), on_a_enter)
15 .add_systems(OnEnter(GameState::B), on_b_enter)
16 .add_systems(OnExit(GameState::A), on_a_exit)
17 .add_systems(OnExit(GameState::B), on_b_exit)
18 .add_systems(Update, toggle)
19 .insert_resource(TickTock(Timer::from_seconds(1.0, TimerMode::Repeating)))
20 .run();
21}
22
23#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, States)]
24enum GameState {
25 #[default]
26 A,
27 B,
28}
29
30#[derive(Resource)]
31struct TickTock(Timer);
32
33fn on_a_enter(mut commands: Commands) {
34 info!("on_a_enter");
35 commands.spawn((
36 DespawnOnExit(GameState::A),
37 Text::new("Game is in state 'A'"),
38 TextFont {
39 font_size: 33.0,
40 ..default()
41 },
42 TextColor(Color::srgb(0.5, 0.5, 1.0)),
43 Node {
44 position_type: PositionType::Absolute,
45 top: px(0),
46 left: px(0),
47 ..default()
48 },
49 ));
50}
51
52fn on_a_exit(mut commands: Commands) {
53 info!("on_a_exit");
54 commands.spawn((
55 DespawnOnEnter(GameState::A),
56 Text::new("Game state 'A' will be back in 1 second"),
57 TextFont {
58 font_size: 33.0,
59 ..default()
60 },
61 TextColor(Color::srgb(0.5, 0.5, 1.0)),
62 Node {
63 position_type: PositionType::Absolute,
64 top: px(0),
65 left: px(500),
66 ..default()
67 },
68 ));
69}
70
71fn on_b_enter(mut commands: Commands) {
72 info!("on_b_enter");
73 commands.spawn((
74 DespawnOnExit(GameState::B),
75 Text::new("Game is in state 'B'"),
76 TextFont {
77 font_size: 33.0,
78 ..default()
79 },
80 TextColor(Color::srgb(0.5, 0.5, 1.0)),
81 Node {
82 position_type: PositionType::Absolute,
83 top: px(50),
84 left: px(0),
85 ..default()
86 },
87 ));
88}
89
90fn on_b_exit(mut commands: Commands) {
91 info!("on_b_exit");
92 commands.spawn((
93 DespawnOnEnter(GameState::B),
94 Text::new("Game state 'B' will be back in 1 second"),
95 TextFont {
96 font_size: 33.0,
97 ..default()
98 },
99 TextColor(Color::srgb(0.5, 0.5, 1.0)),
100 Node {
101 position_type: PositionType::Absolute,
102 top: px(50),
103 left: px(500),
104 ..default()
105 },
106 ));
107}
108
109fn setup_camera(mut commands: Commands) {
110 commands.spawn(Camera3d::default());
111}
112
113fn toggle(
114 time: Res<Time>,
115 mut timer: ResMut<TickTock>,
116 state: Res<State<GameState>>,
117 mut next_state: ResMut<NextState<GameState>>,
118) {
119 if !timer.0.tick(time.delta()).is_finished() {
120 return;
121 }
122 *next_state = match state.get() {
123 GameState::A => NextState::Pending(GameState::B),
124 GameState::B => NextState::Pending(GameState::A),
125 }
126}