//! This example illustrates how to use [`States`] for high-level app control flow. //! States are a powerful but intuitive tool for controlling which logic runs when. //! You can have multiple independent states, and the [`OnEnter`] and [`OnExit`] schedules //! can be used to great effect to ensure that you handle setup and teardown appropriately. //! //! In this case, we're transitioning from a `Menu` state to an `InGame` state. use bevy::{dev_tools::states::*, prelude::*}; fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::() // Alternatively we could use .insert_state(AppState::Menu) .add_systems(Startup, setup) // This system runs when we enter `AppState::Menu`, during the `StateTransition` schedule. // All systems from the exit schedule of the state we're leaving are run first, // and then all systems from the enter schedule of the state we're entering are run second. .add_systems(OnEnter(AppState::Menu), setup_menu) // By contrast, update systems are stored in the `Update` schedule. They simply // check the value of the `State` resource to see if they should run each frame. .add_systems(Update, menu.run_if(in_state(AppState::Menu))) .add_systems(OnExit(AppState::Menu), cleanup_menu) .add_systems(OnEnter(AppState::InGame), setup_game) .add_systems( Update, (movement, change_color).run_if(in_state(AppState::InGame)), ) .add_systems(Update, log_transitions::) .run(); } #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] enum AppState { #[default] Menu, InGame, } #[derive(Resource)] struct MenuData { button_entity: Entity, } const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15); const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25); const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35); fn setup(mut commands: Commands) { commands.spawn(Camera2d); } fn setup_menu(mut commands: Commands) { let button_entity = commands .spawn(( Node::default(), Style { // center button width: Val::Percent(100.), height: Val::Percent(100.), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..default() }, )) .with_children(|parent| { parent .spawn(( Button, Style { width: Val::Px(150.), height: Val::Px(65.), // horizontally center child text justify_content: JustifyContent::Center, // vertically center child text align_items: AlignItems::Center, ..default() }, BackgroundColor(NORMAL_BUTTON), )) .with_children(|parent| { parent.spawn(( Text::new("Play"), TextFont { font_size: 33.0, ..default() }, TextColor(Color::srgb(0.9, 0.9, 0.9)), )); }); }) .id(); commands.insert_resource(MenuData { button_entity }); } fn menu( mut next_state: ResMut>, mut interaction_query: Query< (&Interaction, &mut BackgroundColor), (Changed, With