diff --git a/CREDITS.md b/CREDITS.md index cefd08df93ad4..b646a0662dbf7 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -16,3 +16,7 @@ * Generic RPG Pack (CC0 license) by [Bakudas](https://twitter.com/bakudas) and [Gabe Fern](https://twitter.com/_Gabrielfer) * Environment maps (`.hdr` files) from [HDRIHaven](https://hdrihaven.com) (CC0 license) +* Alien from [Kenney's Space Kit](https://www.kenney.nl/assets/space-kit) (CC0 1.0 Universal) +* Cake from [Kenney's Food Kit](https://www.kenney.nl/assets/food-kit) (CC0 1.0 Universal) +* Ground tile from [Kenney's Tower Defense Kit](https://www.kenney.nl/assets/tower-defense-kit) (CC0 1.0 Universal) +* Game icons from [Kenney's Game Icons](https://www.kenney.nl/assets/game-icons) (CC0 1.0 Universal) diff --git a/Cargo.toml b/Cargo.toml index dd9e585c39fbf..c451e83f06f57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -359,6 +359,10 @@ path = "examples/game/alien_cake_addict.rs" name = "breakout" path = "examples/game/breakout.rs" +[[example]] +name = "game_menu" +path = "examples/game/game_menu.rs" + # Input [[example]] name = "char_input_events" diff --git a/assets/models/AlienCake/README.md b/assets/models/AlienCake/README.md deleted file mode 100644 index 2cf86d3d8bd0d..0000000000000 --- a/assets/models/AlienCake/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Assets are from [Kenney](https://www.kenney.nl) - -- alien from [Space Kit](https://www.kenney.nl/assets/space-kit) -- cake from [Food Kit](https://www.kenney.nl/assets/food-kit) -- ground tile from [Tower Defense Kit](https://www.kenney.nl/assets/tower-defense-kit) diff --git a/assets/textures/Game Icons/exitRight.png b/assets/textures/Game Icons/exitRight.png new file mode 100644 index 0000000000000..de78ab6f0f025 Binary files /dev/null and b/assets/textures/Game Icons/exitRight.png differ diff --git a/assets/textures/Game Icons/right.png b/assets/textures/Game Icons/right.png new file mode 100644 index 0000000000000..3f2480f9a5465 Binary files /dev/null and b/assets/textures/Game Icons/right.png differ diff --git a/assets/textures/Game Icons/wrench.png b/assets/textures/Game Icons/wrench.png new file mode 100644 index 0000000000000..440e7edc41af9 Binary files /dev/null and b/assets/textures/Game Icons/wrench.png differ diff --git a/examples/README.md b/examples/README.md index 81190f58866e4..02a10eabb4062 100644 --- a/examples/README.md +++ b/examples/README.md @@ -182,6 +182,7 @@ Example | File | Description --- | --- | --- `alien_cake_addict` | [`game/alien_cake_addict.rs`](./game/alien_cake_addict.rs) | Eat the cakes. Eat them all. An example 3D game `breakout` | [`game/breakout.rs`](./game/breakout.rs) | An implementation of the classic game "Breakout" +`game_menu` | [`game/game_menu.rs`](./game/game_menu.rs) | A simple game menu ## Input diff --git a/examples/game/game_menu.rs b/examples/game/game_menu.rs new file mode 100644 index 0000000000000..8bc0a155b31f5 --- /dev/null +++ b/examples/game/game_menu.rs @@ -0,0 +1,820 @@ +use bevy::prelude::*; + +// 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. + +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(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(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(); +} + +// As there isn't an actual game, setup is just adding a `UiCameraBundle` +fn setup(mut commands: Commands) { + commands.spawn_bundle(UiCameraBundle::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 bevy::prelude::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 + 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_bundle(ImageBundle { + style: Style { + // This will center the logo + margin: Rect::all(Val::Auto), + // This will set the logo to be 200px wide, and auto adjust its height + size: Size::new(Val::Px(200.0), Val::Auto), + ..Default::default() + }, + image: UiImage(icon), + ..Default::default() + }) + .insert(OnSplashScreen); + // Insert the timer as a resource + commands.insert_resource(SplashTimer(Timer::from_seconds(1.0, false))); + } + + // Tick the timer, and change state when finished + fn countdown( + mut game_state: ResMut>, + time: Res