//! This example will display a simple menu using Bevy UI where you can start a new game, //! change some settings or quit. There is no actual game, it will just display the current //! settings for 5 seconds before going back to the menu. use bevy::prelude::*; const TEXT_COLOR: Color = Color::rgb(0.9, 0.9, 0.9); // Enum that will be used as a global state for the game #[derive(Clone, Eq, PartialEq, Debug, Hash)] enum GameState { Splash, Menu, Game, } // One of the two settings that can be set through the menu. It will be a resource in the app #[derive(Resource, Debug, Component, PartialEq, Eq, Clone, Copy)] enum DisplayQuality { Low, Medium, High, } // One of the two settings that can be set through the menu. It will be a resource in the app #[derive(Resource, Debug, Component, PartialEq, Eq, Clone, Copy)] struct Volume(u32); fn main() { App::new() .add_plugins(DefaultPlugins) // Insert as resource the initial value for the settings resources .insert_resource(DisplayQuality::Medium) .insert_resource(Volume(7)) .add_startup_system(setup) // Declare the game state, and set its startup value .add_state(GameState::Splash) // Adds the plugins for each state .add_plugin(splash::SplashPlugin) .add_plugin(menu::MenuPlugin) .add_plugin(game::GamePlugin) .run(); } fn setup(mut commands: Commands) { commands.spawn(Camera2dBundle::default()); } mod splash { use bevy::prelude::*; use super::{despawn_screen, GameState}; // This plugin will display a splash screen with Bevy logo for 1 second before switching to the menu pub struct SplashPlugin; impl Plugin for SplashPlugin { fn build(&self, app: &mut App) { // As this plugin is managing the splash screen, it will focus on the state `GameState::Splash` app // When entering the state, spawn everything needed for this screen .add_system_set(SystemSet::on_enter(GameState::Splash).with_system(splash_setup)) // While in this state, run the `countdown` system .add_system_set(SystemSet::on_update(GameState::Splash).with_system(countdown)) // When exiting the state, despawn everything that was spawned for this screen .add_system_set( SystemSet::on_exit(GameState::Splash) .with_system(despawn_screen::), ); } } // Tag component used to tag entities added on the splash screen #[derive(Component)] struct OnSplashScreen; // Newtype to use a `Timer` for this screen as a resource #[derive(Resource, Deref, DerefMut)] struct SplashTimer(Timer); fn splash_setup(mut commands: Commands, asset_server: Res) { let icon = asset_server.load("branding/icon.png"); // Display the logo commands .spawn(( NodeBundle { style: Style { align_items: AlignItems::Center, justify_content: JustifyContent::Center, size: Size::new(Val::Percent(100.0), Val::Percent(100.0)), ..default() }, ..default() }, OnSplashScreen, )) .with_children(|parent| { parent.spawn(ImageBundle { style: Style { // This will set the logo to be 200px wide, and auto adjust its height size: Size::new(Val::Px(200.0), Val::Auto), ..default() }, image: UiImage::new(icon), ..default() }); }); // Insert the timer as a resource commands.insert_resource(SplashTimer(Timer::from_seconds(1.0, TimerMode::Once))); } // Tick the timer, and change state when finished fn countdown( mut game_state: ResMut>, time: Res