diff --git a/Cargo.lock b/Cargo.lock index 9bff8b2..14f62a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -711,7 +711,7 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pacman" -version = "0.80.0" +version = "0.80.1" dependencies = [ "anyhow", "bevy_ecs", diff --git a/Cargo.toml b/Cargo.toml index 6d7417a..9feb66f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pacman" -version = "0.80.0" +version = "0.80.1" authors = ["Xevion"] edition = "2021" rust-version = "1.86.0" diff --git a/README.md b/README.md index 8baa575..691a9a5 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The game includes all the original features you'd expect from Pac-Man: - [x] Classic maze navigation with tunnels and dot collection - [ ] Four ghosts with their unique AI behaviors (Blinky, Pinky, Inky, and Clyde) - [x] Power pellets that allow Pac-Man to eat ghosts -- [ ] Fruit bonuses that appear periodically +- [x] Fruit bonuses that appear periodically - [ ] Progressive difficulty with faster ghosts and shorter power pellet duration - [x] Authentic sound effects and sprites diff --git a/src/events.rs b/src/events.rs index 57f7cac..6dada3f 100644 --- a/src/events.rs +++ b/src/events.rs @@ -19,7 +19,10 @@ pub enum GameCommand { /// Restart the current level with fresh entity positions and items ResetLevel, /// Pause or resume game ticking logic + /// TODO: Display pause state, fix debug rendering pause distress TogglePause, + /// Toggle fullscreen mode (desktop only) + ToggleFullscreen, } /// Global events that flow through the ECS event system to coordinate game behavior. diff --git a/src/game.rs b/src/game.rs index e89ec5a..445a0eb 100644 --- a/src/game.rs +++ b/src/game.rs @@ -489,6 +489,8 @@ impl Game { }), player_control_system, pause_system, + #[cfg(not(target_os = "emscripten"))] + profile(SystemId::Input, systems::handle_fullscreen_command), ) .chain(); diff --git a/src/systems/input.rs b/src/systems/input.rs index 912f78b..9903e26 100644 --- a/src/systems/input.rs +++ b/src/systems/input.rs @@ -90,6 +90,8 @@ impl Default for Bindings { { key_bindings.insert(Keycode::Escape, GameCommand::Exit); key_bindings.insert(Keycode::Q, GameCommand::Exit); + // Desktop-only fullscreen toggle + key_bindings.insert(Keycode::F, GameCommand::ToggleFullscreen); } let movement_keys = HashSet::from([ diff --git a/src/systems/state.rs b/src/systems/state.rs index 151285f..b1af2a6 100644 --- a/src/systems/state.rs +++ b/src/systems/state.rs @@ -21,6 +21,12 @@ use bevy_ecs::{ }; use crate::events::{GameCommand, GameEvent}; +#[cfg(not(target_os = "emscripten"))] +use bevy_ecs::system::NonSendMut; +#[cfg(not(target_os = "emscripten"))] +use sdl2::render::Canvas; +#[cfg(not(target_os = "emscripten"))] +use sdl2::video::{FullscreenType, Window}; #[derive(Resource, Clone)] pub struct PlayerAnimation(pub DirectionalAnimation); @@ -73,6 +79,27 @@ pub fn handle_pause_command( } } +#[cfg(not(target_os = "emscripten"))] +pub fn handle_fullscreen_command(mut events: EventReader, mut canvas: NonSendMut<&mut Canvas>) { + for event in events.read() { + if let GameEvent::Command(GameCommand::ToggleFullscreen) = event { + let window = canvas.window_mut(); + let current = window.fullscreen_state(); + let target = match current { + FullscreenType::Off => FullscreenType::Desktop, + _ => FullscreenType::Off, + }; + + if let Err(e) = window.set_fullscreen(target) { + tracing::warn!(error = ?e, "Failed to toggle fullscreen"); + } else { + let on = matches!(target, FullscreenType::Desktop | FullscreenType::True); + info!(fullscreen = on, "Toggled fullscreen"); + } + } + } +} + pub trait TooSimilar { fn too_similar(&self, other: &Self) -> bool; }