diff --git a/source/core/rendering/overlay.cpp b/source/core/rendering/overlay.cpp index 25a0234..187b570 100644 --- a/source/core/rendering/overlay.cpp +++ b/source/core/rendering/overlay.cpp @@ -7,6 +7,7 @@ #include "core/rendering/menu.hpp" #include "core/rendering/text.hpp" +#include "core/system/director.hpp" #include "game/options.hpp" namespace Overlay { @@ -151,6 +152,18 @@ namespace Overlay { esc_waiting_ = false; } + // Indicador de pausa persistent (cantó superior dret) + if (Director::get() && Director::get()->isPaused()) { + const char* pause_text = "PAUSA"; + int w = font_->width(pause_text); + int x = SCREEN_W - w - 4; + int y = 4; + // Ombra + font_->draw(pixel_data, x + 1, y + 1, pause_text, 0xFF000000); + // Text en roig + font_->draw(pixel_data, x, y, pause_text, 0xFF0000FF); + } + // Menú flotant per damunt de tot if (Menu::isOpen()) { Menu::render(pixel_data); diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 07ef265..2394fc0 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -7,6 +7,7 @@ #include "core/input/global_inputs.hpp" #include "core/input/key_remap.hpp" #include "core/input/mouse.hpp" +#include "core/jail/jail_audio.hpp" #include "core/jail/jgame.hpp" #include "core/jail/jinput.hpp" #include "core/rendering/menu.hpp" @@ -37,6 +38,15 @@ auto Director::get() -> Director* { return instance_; } +void Director::togglePause() { + paused_ = !paused_; + if (paused_) { + JA_PauseMusic(); + } else { + JA_ResumeMusic(); + } +} + void Director::run() { // Llança el game thread game_thread_ = std::thread(&Director::gameThreadFunc, this); @@ -64,9 +74,10 @@ void Director::run() { esc_blocked_ = false; } - // Consumeix un frame nou si n'hi ha un disponible (no bloqueja) + // Consumeix un frame nou si n'hi ha un disponible (no bloqueja). + // Si estem en pausa, no consumim: el game thread es queda bloquejat a publishFrame. bool new_frame = false; - { + if (!paused_) { std::lock_guard lock(mutex_); if (frame_ready_ && latest_frame_ != nullptr) { memcpy(game_frame, latest_frame_, sizeof(game_frame)); @@ -131,6 +142,14 @@ void Director::handleEvents() { menu_keys_held_[event.key.scancode] = true; continue; } + // Pausa: F11 (o tecla configurada) pausa/reprén la simulació + if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat && + event.key.scancode == Options::keys_gui.pause_toggle) { + togglePause(); + Overlay::showNotification(paused_ ? "PAUSA" : "REPRES"); + menu_keys_held_[event.key.scancode] = true; + continue; + } // Menú: F12 (o tecla configurada) obre/tanca el menú flotant if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat && event.key.scancode == Options::keys_gui.menu_toggle) { diff --git a/source/core/system/director.hpp b/source/core/system/director.hpp index bc7e2bd..a72dc7b 100644 --- a/source/core/system/director.hpp +++ b/source/core/system/director.hpp @@ -34,6 +34,10 @@ class Director { // Indica si ESC està bloquejada (el joc no l'ha de veure) auto isEscBlocked() const -> bool { return esc_blocked_ || esc_swallow_until_release_; } + // Pausa: bloqueja el consum de frames del game thread + pausa la música + void togglePause(); + auto isPaused() const -> bool { return paused_; } + private: Director() = default; ~Director() = default; @@ -56,6 +60,7 @@ class Director { std::atomic game_thread_done_{false}; std::atomic key_pressed_{false}; std::atomic esc_blocked_{false}; + std::atomic paused_{false}; // Quan el menú tanca amb ESC, empassem-nos l'ESC fins que l'usuari la deixe anar, // per no fer eixir el joc al proper poll de JI_KeyPressed. std::atomic esc_swallow_until_release_{false}; diff --git a/source/game/defaults.hpp b/source/game/defaults.hpp index cdb5cb7..ce94699 100644 --- a/source/game/defaults.hpp +++ b/source/game/defaults.hpp @@ -14,6 +14,7 @@ namespace Defaults::KeysGUI { constexpr SDL_Scancode NEXT_SHADER_PRESET = SDL_SCANCODE_F8; constexpr SDL_Scancode TOGGLE_STRETCH_FILTER = SDL_SCANCODE_F9; constexpr SDL_Scancode TOGGLE_RENDER_INFO = SDL_SCANCODE_F10; + constexpr SDL_Scancode PAUSE_TOGGLE = SDL_SCANCODE_F11; constexpr SDL_Scancode MENU_TOGGLE = SDL_SCANCODE_F12; } // namespace Defaults::KeysGUI diff --git a/source/game/options.cpp b/source/game/options.cpp index 0a4e71f..0b3023b 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -126,6 +126,7 @@ namespace Options { loadScancodeField(node, "left", keys_game.left); loadScancodeField(node, "right", keys_game.right); loadScancodeField(node, "menu_toggle", keys_gui.menu_toggle); + loadScancodeField(node, "pause_toggle", keys_gui.pause_toggle); } } @@ -277,6 +278,7 @@ namespace Options { file << " left: \"" << SDL_GetScancodeName(keys_game.left) << "\"\n"; file << " right: \"" << SDL_GetScancodeName(keys_game.right) << "\"\n"; file << " menu_toggle: \"" << SDL_GetScancodeName(keys_gui.menu_toggle) << "\"\n"; + file << " pause_toggle: \"" << SDL_GetScancodeName(keys_gui.pause_toggle) << "\"\n"; file.close(); diff --git a/source/game/options.hpp b/source/game/options.hpp index 83863ba..6b732cb 100644 --- a/source/game/options.hpp +++ b/source/game/options.hpp @@ -20,6 +20,7 @@ namespace Options { SDL_Scancode next_shader_preset{Defaults::KeysGUI::NEXT_SHADER_PRESET}; SDL_Scancode toggle_stretch_filter{Defaults::KeysGUI::TOGGLE_STRETCH_FILTER}; SDL_Scancode toggle_render_info{Defaults::KeysGUI::TOGGLE_RENDER_INFO}; + SDL_Scancode pause_toggle{Defaults::KeysGUI::PAUSE_TOGGLE}; SDL_Scancode menu_toggle{Defaults::KeysGUI::MENU_TOGGLE}; };