From 7626aee1f8c2a79d6d8aab226104da9e28459300 Mon Sep 17 00:00:00 2001 From: Thom Bruce Date: Tue, 14 Nov 2023 07:51:32 +0000 Subject: [PATCH 1/4] add pause menu --- CHANGELOG.md | 1 + Cargo.lock | 1 + Cargo.toml | 1 + assets/locales/en/en-US/start_menu.ftl | 2 + src/systems/mod.rs | 15 +++++- src/systems/states/mod.rs | 7 ++- src/systems/states/transitions.rs | 19 +++++++ src/ui/menus/pause.rs | 74 ++++++++++++++++++++++++-- src/ui/menus/start_menu.rs | 2 + 9 files changed, 115 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ee41d0..37f4bbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Actual values for semi-major axes of planetary orbits (scaled down after calculations) +- Pause menu with Continue and Exit Game buttons ### Changed diff --git a/Cargo.lock b/Cargo.lock index 91bc261..aefb78f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4468,6 +4468,7 @@ dependencies = [ "bevy_asset_loader", "bevy_common_assets", "bevy_fluent", + "bevy_picking_core", "bevy_rapier2d", "bevy_spatial", "fluent_content", diff --git a/Cargo.toml b/Cargo.toml index 4c9c18a..12d2911 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ bevy-ui-navigation = "0.33.0" bevy_asset_loader = { version = "0.18.0", features = ["2d"] } bevy_common_assets = { version = "0.8.0", features = ["ron"] } bevy_fluent = "0.8.0" +bevy_picking_core = "0.17.0" bevy_rapier2d = "0.23.0" bevy_spatial = "0.7.0" fluent_content = "0.0.5" diff --git a/assets/locales/en/en-US/start_menu.ftl b/assets/locales/en/en-US/start_menu.ftl index 9a26ffb..e5f423c 100644 --- a/assets/locales/en/en-US/start_menu.ftl +++ b/assets/locales/en/en-US/start_menu.ftl @@ -2,3 +2,5 @@ new-game = New Game settings = Settings credits = Credits quit = Quit +continue = Continue +exit-game = Exit Game diff --git a/src/systems/mod.rs b/src/systems/mod.rs index 2745497..a61962e 100644 --- a/src/systems/mod.rs +++ b/src/systems/mod.rs @@ -88,8 +88,14 @@ impl Plugin for SystemsPlugin { ), ); + // - Reset + app.add_systems(OnEnter(GameState::Reset), states::transitions::game_reset); + // - Paused - app.add_systems(OnEnter(GameState::Paused), pause::pause_screen); + app.add_systems( + OnEnter(GameState::Paused), + (pause::pause_screen, pause::toggle_physics_off), + ); // OnTransition app.add_systems( @@ -113,6 +119,7 @@ impl Plugin for SystemsPlugin { OnExit(GameState::GameCreate), hud::indicator::spawn_indicators, ); + app.add_systems(OnExit(GameState::Paused), pause::toggle_physics_on); // FixedUpdate // app.insert_resource(FixedTime::new_from_secs(1.0 / 60.0)); @@ -134,6 +141,12 @@ impl Plugin for SystemsPlugin { Update, start_menu::menu_input_system.run_if(is_in_menu_state), ); + + app.add_systems( + Update, + pause::pause_input_system.run_if(in_state(GameState::Paused)), + ); + app.add_systems( Update, start_menu::menu_focus_system diff --git a/src/systems/states/mod.rs b/src/systems/states/mod.rs index c743be7..442ebea 100644 --- a/src/systems/states/mod.rs +++ b/src/systems/states/mod.rs @@ -14,9 +14,10 @@ pub enum GameState { GameCreate, Active, Paused, + Reset, } impl GameState { - pub const IN_ANY_STATE: &[GameState; 7] = &[ + pub const IN_ANY_STATE: &[GameState; 8] = &[ GameState::Loading, GameState::LoadingTranslations, GameState::StartMenu, @@ -24,8 +25,10 @@ impl GameState { GameState::GameCreate, GameState::Active, GameState::Paused, + GameState::Reset, ]; - pub const IN_MENU_STATE: &[GameState; 2] = &[GameState::StartMenu, GameState::Credits]; + pub const IN_MENU_STATE: &[GameState; 3] = + &[GameState::StartMenu, GameState::Credits, GameState::Paused]; pub const IN_GAME_STATE: &[GameState; 3] = &[GameState::GameCreate, GameState::Active, GameState::Paused]; } diff --git a/src/systems/states/transitions.rs b/src/systems/states/transitions.rs index e74ac4b..e14b9f4 100644 --- a/src/systems/states/transitions.rs +++ b/src/systems/states/transitions.rs @@ -3,6 +3,7 @@ use bevy::{ prelude::*, window::Cursor, }; +use bevy_picking_core::pointer::PointerId; use crate::core::resources::assets::AudioAssets; @@ -38,6 +39,24 @@ pub(crate) fn game_setup( next_state.set(GameState::Active); } +pub(crate) fn game_reset( + mut commands: Commands, + entities: Query, Without, Without)>, + mut next_state: ResMut>, + mut window: Query<&mut Window>, +) { + for entity in entities.iter() { + commands.entity(entity).despawn_recursive(); + } + + window.single_mut().cursor = Cursor { + visible: true, + ..default() + }; + + next_state.set(GameState::Loading); +} + pub(crate) fn state_enter_despawn( mut commands: Commands, state: ResMut>, diff --git a/src/ui/menus/pause.rs b/src/ui/menus/pause.rs index 1034066..d8e62e9 100644 --- a/src/ui/menus/pause.rs +++ b/src/ui/menus/pause.rs @@ -1,12 +1,16 @@ use bevy::prelude::*; use bevy_rapier2d::prelude::RapierConfiguration; +use bevy_ui_navigation::prelude::*; use fluent_content::Content; use leafwing_input_manager::prelude::{ActionState, InputManagerPlugin}; use crate::{ core::{effects::blink::DrawBlinkTimer, resources::assets::UiAssets}, i18n::I18n, - inputs::pause::{pause_input_map, PauseAction}, + inputs::{ + menu::MenuAction, + pause::{pause_input_map, PauseAction}, + }, systems::states::{ForState, GameState}, }; @@ -17,6 +21,12 @@ impl Plugin for PausePlugin { } } +#[derive(Component)] +pub enum MenuButton { + Continue, + ExitGame, +} + pub(crate) fn setup_pause_systems(mut commands: Commands) { commands.insert_resource(pause_input_map()); commands.insert_resource(ActionState::::default()); @@ -26,23 +36,28 @@ pub(crate) fn pause_system( state: Res>, mut next_state: ResMut>, pause_action_state: Res>, - mut rapier_configuration: ResMut, ) { if pause_action_state.just_pressed(PauseAction::Pause) { match state.get() { GameState::Active => { next_state.set(GameState::Paused); - rapier_configuration.physics_pipeline_active = false; } GameState::Paused => { next_state.set(GameState::Active); - rapier_configuration.physics_pipeline_active = true; } _ => {} } } } +pub(crate) fn toggle_physics_on(mut rapier_configuration: ResMut) { + rapier_configuration.physics_pipeline_active = true; +} + +pub(crate) fn toggle_physics_off(mut rapier_configuration: ResMut) { + rapier_configuration.physics_pipeline_active = false; +} + pub(crate) fn pause_screen(mut commands: Commands, ui: Res, i18n: Res) { commands .spawn(( @@ -78,5 +93,56 @@ pub(crate) fn pause_screen(mut commands: Commands, ui: Res, i18n: Res< }, DrawBlinkTimer(Timer::from_seconds(0.65, TimerMode::Repeating)), )); + + for (string, marker) in [ + ("continue", MenuButton::Continue), + ("exit-game", MenuButton::ExitGame), + ] { + parent.spawn(( + TextBundle { + text: Text::from_section( + i18n.content(string).unwrap().to_ascii_uppercase(), + TextStyle { + font: ui.font.clone(), + font_size: 25.0, + color: Color::rgb_u8(0x00, 0x88, 0x88), + }, + ), + style: Style { + margin: UiRect::top(Val::Px(25.)), + justify_content: JustifyContent::Center, + align_items: AlignItems::Center, + ..default() + }, + ..default() + }, // DrawBlinkTimer(Timer::from_seconds(0.65, TimerMode::Repeating)), + Focusable::default(), + marker, + )); + } }); } + +pub(crate) fn pause_input_system( + mut next_state: ResMut>, + inputs: Res>, + mut requests: EventWriter, + mut buttons: Query<&mut MenuButton>, + mut events: EventReader, +) { + events.nav_iter().activated_in_query_foreach_mut( + &mut buttons, + |mut button| match &mut *button { + MenuButton::Continue => { + next_state.set(GameState::Active); + } + MenuButton::ExitGame => { + next_state.set(GameState::Reset); + } + }, + ); + + if inputs.just_pressed(MenuAction::Select) { + requests.send(NavRequest::Action); + } +} diff --git a/src/ui/menus/start_menu.rs b/src/ui/menus/start_menu.rs index 5abe802..9689444 100644 --- a/src/ui/menus/start_menu.rs +++ b/src/ui/menus/start_menu.rs @@ -156,6 +156,8 @@ pub(crate) fn menu_input_system( if inputs.just_pressed(MenuAction::Start) { next_state.set(GameState::GameCreate); } + + // TODO: We shouldn't be able to access credits from pause state if inputs.just_released(MenuAction::Credits) { match state.get() { GameState::StartMenu => { From abab0c40c10d8d48e5dacffbb8dfb9f1dd3e9755 Mon Sep 17 00:00:00 2001 From: Thom Bruce Date: Tue, 14 Nov 2023 08:45:48 +0000 Subject: [PATCH 2/4] add sub-dependency note --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 12d2911..4214b5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ bevy-ui-navigation = "0.33.0" bevy_asset_loader = { version = "0.18.0", features = ["2d"] } bevy_common_assets = { version = "0.8.0", features = ["ron"] } bevy_fluent = "0.8.0" -bevy_picking_core = "0.17.0" +bevy_picking_core = "0.17.0" # Sub-dependency of bevy-ui-navigation; we need to access one of its components bevy_rapier2d = "0.23.0" bevy_spatial = "0.7.0" fluent_content = "0.0.5" From af452ce56277fa59fe442ec9139c5ce267f84cb7 Mon Sep 17 00:00:00 2001 From: Thom Bruce Date: Tue, 14 Nov 2023 08:49:16 +0000 Subject: [PATCH 3/4] add pause menu translations --- CHANGELOG.md | 3 +++ assets/locales/de/de-DE/start_menu.ftl | 2 ++ assets/locales/ru/ru-RU/start_menu.ftl | 2 ++ 3 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f4bbe..22321c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Actual values for semi-major axes of planetary orbits (scaled down after calculations) - Pause menu with Continue and Exit Game buttons +- Added basic English (US) translations for pause menu +- Added basic Russian (RU) translations for pause menu +- Added basic German (DE) translations for pause menu ### Changed diff --git a/assets/locales/de/de-DE/start_menu.ftl b/assets/locales/de/de-DE/start_menu.ftl index 13b4345..fd3b199 100644 --- a/assets/locales/de/de-DE/start_menu.ftl +++ b/assets/locales/de/de-DE/start_menu.ftl @@ -2,3 +2,5 @@ new-game = Neues Spiel settings = Einstellungen credits = Credits quit = Aufhören +continue = Weitermachen +exit-game = Spiel verlassen diff --git a/assets/locales/ru/ru-RU/start_menu.ftl b/assets/locales/ru/ru-RU/start_menu.ftl index a1e1197..24babd2 100644 --- a/assets/locales/ru/ru-RU/start_menu.ftl +++ b/assets/locales/ru/ru-RU/start_menu.ftl @@ -2,3 +2,5 @@ new-game = Новая игра settings = Настройки credits = Кредиты quit = Покидать +continue = Продолжать +exit-game = Выйти из игры From 6cfaf44e5a43b78038839fa2d61dad908816529c Mon Sep 17 00:00:00 2001 From: Thom Bruce Date: Tue, 14 Nov 2023 09:02:36 +0000 Subject: [PATCH 4/4] reset GameTime on game reset --- src/core/resources/game_time.rs | 2 +- src/systems/states/transitions.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/resources/game_time.rs b/src/core/resources/game_time.rs index e733f23..779cd2c 100644 --- a/src/core/resources/game_time.rs +++ b/src/core/resources/game_time.rs @@ -1,7 +1,7 @@ use bevy::{prelude::*, time::Stopwatch}; #[derive(Resource, Deref)] -pub struct GameTime(Stopwatch); +pub struct GameTime(pub Stopwatch); pub struct GameTimePlugin; impl Plugin for GameTimePlugin { diff --git a/src/systems/states/transitions.rs b/src/systems/states/transitions.rs index e14b9f4..6d05a37 100644 --- a/src/systems/states/transitions.rs +++ b/src/systems/states/transitions.rs @@ -5,7 +5,7 @@ use bevy::{ }; use bevy_picking_core::pointer::PointerId; -use crate::core::resources::assets::AudioAssets; +use crate::core::resources::{assets::AudioAssets, game_time::GameTime}; use super::{ForState, GameState}; @@ -44,6 +44,7 @@ pub(crate) fn game_reset( entities: Query, Without, Without)>, mut next_state: ResMut>, mut window: Query<&mut Window>, + mut game_time: ResMut, ) { for entity in entities.iter() { commands.entity(entity).despawn_recursive(); @@ -54,6 +55,8 @@ pub(crate) fn game_reset( ..default() }; + game_time.0.reset(); + next_state.set(GameState::Loading); }