Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause Menu #102

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,10 @@ 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
- 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

1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" # 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"
2 changes: 2 additions & 0 deletions assets/locales/de/de-DE/start_menu.ftl
Original file line number Diff line number Diff line change
@@ -2,3 +2,5 @@ new-game = Neues Spiel
settings = Einstellungen
credits = Credits
quit = Aufhören
continue = Weitermachen
exit-game = Spiel verlassen
2 changes: 2 additions & 0 deletions assets/locales/en/en-US/start_menu.ftl
Original file line number Diff line number Diff line change
@@ -2,3 +2,5 @@ new-game = New Game
settings = Settings
credits = Credits
quit = Quit
continue = Continue
exit-game = Exit Game
2 changes: 2 additions & 0 deletions assets/locales/ru/ru-RU/start_menu.ftl
Original file line number Diff line number Diff line change
@@ -2,3 +2,5 @@ new-game = Новая игра
settings = Настройки
credits = Кредиты
quit = Покидать
continue = Продолжать
exit-game = Выйти из игры
2 changes: 1 addition & 1 deletion src/core/resources/game_time.rs
Original file line number Diff line number Diff line change
@@ -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 {
15 changes: 14 additions & 1 deletion src/systems/mod.rs
Original file line number Diff line number Diff line change
@@ -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
7 changes: 5 additions & 2 deletions src/systems/states/mod.rs
Original file line number Diff line number Diff line change
@@ -14,18 +14,21 @@ 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,
GameState::Credits,
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];
}
24 changes: 23 additions & 1 deletion src/systems/states/transitions.rs
Original file line number Diff line number Diff line change
@@ -3,8 +3,9 @@ use bevy::{
prelude::*,
window::Cursor,
};
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};

@@ -38,6 +39,27 @@ pub(crate) fn game_setup(
next_state.set(GameState::Active);
}

pub(crate) fn game_reset(
mut commands: Commands,
entities: Query<Entity, (Without<Window>, Without<Camera>, Without<PointerId>)>,
mut next_state: ResMut<NextState<GameState>>,
mut window: Query<&mut Window>,
mut game_time: ResMut<GameTime>,
) {
for entity in entities.iter() {
commands.entity(entity).despawn_recursive();
}

window.single_mut().cursor = Cursor {
visible: true,
..default()
};

game_time.0.reset();

next_state.set(GameState::Loading);
}

pub(crate) fn state_enter_despawn<T: States>(
mut commands: Commands,
state: ResMut<State<T>>,
74 changes: 70 additions & 4 deletions src/ui/menus/pause.rs
Original file line number Diff line number Diff line change
@@ -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::<PauseAction>::default());
@@ -26,23 +36,28 @@ pub(crate) fn pause_system(
state: Res<State<GameState>>,
mut next_state: ResMut<NextState<GameState>>,
pause_action_state: Res<ActionState<PauseAction>>,
mut rapier_configuration: ResMut<RapierConfiguration>,
) {
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<RapierConfiguration>) {
rapier_configuration.physics_pipeline_active = true;
}

pub(crate) fn toggle_physics_off(mut rapier_configuration: ResMut<RapierConfiguration>) {
rapier_configuration.physics_pipeline_active = false;
}

pub(crate) fn pause_screen(mut commands: Commands, ui: Res<UiAssets>, i18n: Res<I18n>) {
commands
.spawn((
@@ -78,5 +93,56 @@ pub(crate) fn pause_screen(mut commands: Commands, ui: Res<UiAssets>, 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<NextState<GameState>>,
inputs: Res<ActionState<MenuAction>>,
mut requests: EventWriter<NavRequest>,
mut buttons: Query<&mut MenuButton>,
mut events: EventReader<NavEvent>,
) {
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);
}
}
2 changes: 2 additions & 0 deletions src/ui/menus/start_menu.rs
Original file line number Diff line number Diff line change
@@ -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 => {