From 949899b03539514954e09cd6489b8680acbd2295 Mon Sep 17 00:00:00 2001 From: Xevion Date: Mon, 29 Dec 2025 01:03:06 -0600 Subject: [PATCH] feat(game): implement pause system with Escape key and visual overlay --- pacman/src/game.rs | 6 +++--- pacman/src/systems/hud/score.rs | 27 ++++++++++++++++++++++++++- pacman/src/systems/input.rs | 3 +-- pacman/src/systems/state.rs | 2 +- 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/pacman/src/game.rs b/pacman/src/game.rs index c348924..1c07f8f 100644 --- a/pacman/src/game.rs +++ b/pacman/src/game.rs @@ -541,9 +541,9 @@ impl Game { )) .configure_sets(( GameplaySet::Input, - GameplaySet::Update.run_if(|paused: Res| paused.active()), - GameplaySet::Respond.run_if(|paused: Res| paused.active()), - RenderSet::Animation.run_if(|paused: Res| paused.active()), + GameplaySet::Update.run_if(|paused: Res| !paused.active()), + GameplaySet::Respond.run_if(|paused: Res| !paused.active()), + RenderSet::Animation.run_if(|paused: Res| !paused.active()), RenderSet::Draw, RenderSet::Present, )); diff --git a/pacman/src/systems/hud/score.rs b/pacman/src/systems/hud/score.rs index 99e9531..c6cae88 100644 --- a/pacman/src/systems/hud/score.rs +++ b/pacman/src/systems/hud/score.rs @@ -1,11 +1,12 @@ use crate::constants; use crate::error::{GameError, TextureError}; -use crate::systems::{BackbufferResource, GameStage, ScoreResource, StartupSequence}; +use crate::systems::{BackbufferResource, GameStage, PauseState, ScoreResource, StartupSequence}; use crate::texture::sprite::SpriteAtlas; use crate::texture::text::TextTexture; use bevy_ecs::event::EventWriter; use bevy_ecs::system::{NonSendMut, Res}; use sdl2::pixels::Color; +use sdl2::rect::Rect; use sdl2::render::Canvas; use sdl2::video::Window; @@ -17,6 +18,7 @@ pub fn hud_render_system( mut atlas: NonSendMut, score: Res, stage: Res, + pause_state: Res, mut errors: EventWriter, ) { let _ = canvas.with_texture_canvas(&mut backbuffer.0, |canvas| { @@ -82,5 +84,28 @@ pub fn hud_render_system( } } } + + // Render pause overlay when game is paused (allowed during any stage) + if pause_state.active() { + // Enable blending for transparency + canvas.set_blend_mode(sdl2::render::BlendMode::Blend); + + // Draw semi-transparent black overlay + canvas.set_draw_color(Color::RGBA(0, 0, 0, 160)); + let _ = canvas.fill_rect(Rect::new(0, 0, constants::CANVAS_SIZE.x, constants::CANVAS_SIZE.y)); + + // Render "PAUSED" text centered and larger (2.5x scale) + let mut paused_renderer = TextTexture::new(2.5); + let paused_text = "PAUSED"; + let paused_width = paused_renderer.text_width(paused_text); + let paused_height = paused_renderer.text_height(); + let paused_position = glam::UVec2::new( + (constants::CANVAS_SIZE.x - paused_width) / 2, + (constants::CANVAS_SIZE.y - paused_height) / 2 + ); + if let Err(e) = paused_renderer.render_with_color(canvas, &mut atlas, paused_text, paused_position, Color::YELLOW) { + errors.write(TextureError::RenderFailed(format!("Failed to render PAUSED text: {}", e)).into()); + } + } }); } diff --git a/pacman/src/systems/input.rs b/pacman/src/systems/input.rs index b73a5e3..63788de 100644 --- a/pacman/src/systems/input.rs +++ b/pacman/src/systems/input.rs @@ -81,7 +81,7 @@ impl Default for Bindings { key_bindings.insert(Keycode::D, GameCommand::MovePlayer(Direction::Right)); // Game actions - key_bindings.insert(Keycode::P, GameCommand::TogglePause); + key_bindings.insert(Keycode::Escape, GameCommand::TogglePause); key_bindings.insert(Keycode::Space, GameCommand::ToggleDebug); key_bindings.insert(Keycode::M, GameCommand::MuteAudio); key_bindings.insert(Keycode::R, GameCommand::ResetLevel); @@ -89,7 +89,6 @@ impl Default for Bindings { #[cfg(not(target_os = "emscripten"))] { - 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); diff --git a/pacman/src/systems/state.rs b/pacman/src/systems/state.rs index ac9eac5..77a9bbe 100644 --- a/pacman/src/systems/state.rs +++ b/pacman/src/systems/state.rs @@ -68,7 +68,7 @@ pub enum PauseState { impl Default for PauseState { fn default() -> Self { - Self::Active { remaining_ticks: None } + Self::Inactive } }