diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index e595f93..28dc98e 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -211,6 +211,9 @@ Director::Director() { #else Cheevos::init(Resource::List::get()->get("cheevos.bin")); #endif + + // Construeix la primera escena (LOGO per defecte, o la que digui Debug) + switchToActiveScene(); } Director::~Director() { @@ -311,118 +314,90 @@ void Director::setFileList() { // NOLINT(readability-convert-member-functions-t Resource::List::get()->loadFromFile(config_path, PREFIX, system_folder_); } -// Ejecuta la seccion de juego con el logo -void Director::runLogo() { - auto logo = std::make_unique(); - logo->run(); -} - -// Ejecuta la seccion de juego de la pantalla de carga -void Director::runLoadingScreen() { - auto loading_screen = std::make_unique(); - loading_screen->run(); -} - -// Ejecuta la seccion de juego con el titulo y los menus -void Director::runTitle() { - auto title = std::make_unique(); - title->run(); -} - -// Ejecuta la seccion de los creditos del juego -void Director::runCredits() { - auto credits = std::make_unique<Credits>(); - credits->run(); -} - -// Ejecuta la seccion de la demo, donde se ven pantallas del juego -void Director::runDemo() { - auto game = std::make_unique<Game>(Game::Mode::DEMO); - game->run(); -} - -// Ejecuta la seccion del final del juego -void Director::runEnding() { - auto ending = std::make_unique<Ending>(); - ending->run(); -} - -// Ejecuta la seccion del final del juego -void Director::runEnding2() { - auto ending2 = std::make_unique<Ending2>(); - ending2->run(); -} - -// Ejecuta la seccion del final de la partida -void Director::runGameOver() { - auto game_over = std::make_unique<GameOver>(); - game_over->run(); -} - -// Ejecuta la seccion de juego donde se juega -void Director::runGame() { - Audio::get()->stopMusic(); - auto game = std::make_unique<Game>(Game::Mode::GAME); - game->run(); -} - -auto Director::run() -> int { - // Bucle principal - while (SceneManager::current != SceneManager::Scene::QUIT) { - const SceneManager::Scene ACTIVE = SceneManager::current; - - switch (SceneManager::current) { - case SceneManager::Scene::LOGO: - runLogo(); - break; - - case SceneManager::Scene::LOADING_SCREEN: - runLoadingScreen(); - break; - - case SceneManager::Scene::TITLE: - runTitle(); - break; - - case SceneManager::Scene::CREDITS: - runCredits(); - break; - - case SceneManager::Scene::DEMO: - runDemo(); - break; - - case SceneManager::Scene::GAME: - runGame(); - break; - - case SceneManager::Scene::GAME_OVER: - runGameOver(); - break; - - case SceneManager::Scene::ENDING: - runEnding(); - break; - - case SceneManager::Scene::ENDING2: - runEnding2(); - break; - - case SceneManager::Scene::RESTART_CURRENT: - // La escena salió por RESTART_CURRENT → relanzar la escena guardada - SceneManager::current = SceneManager::scene_before_restart; - break; - - default: - break; - } - - // Si la escena que acaba de correr dejó RESTART_CURRENT pendiente, - // restaurar la escena que estaba activa para relanzarla en la próxima iteración - if (SceneManager::current == SceneManager::Scene::RESTART_CURRENT) { - SceneManager::current = ACTIVE; - } +// Construeix l'escena segons SceneManager::current i la deixa en active_scene_. +// Substitueix els vells runLogo(), runTitle(), runGame(), etc. +void Director::switchToActiveScene() { + // Si la escena anterior va demanar RESTART_CURRENT, restaurem la que estava activa + if (SceneManager::current == SceneManager::Scene::RESTART_CURRENT) { + SceneManager::current = SceneManager::scene_before_restart; } - return 0; + // Destrueix l'escena anterior (pot parar música, etc. al seu destructor) + active_scene_.reset(); + + switch (SceneManager::current) { + case SceneManager::Scene::LOGO: + active_scene_ = std::make_unique<Logo>(); + break; + + case SceneManager::Scene::LOADING_SCREEN: + active_scene_ = std::make_unique<LoadingScreen>(); + break; + + case SceneManager::Scene::TITLE: + active_scene_ = std::make_unique<Title>(); + break; + + case SceneManager::Scene::CREDITS: + active_scene_ = std::make_unique<Credits>(); + break; + + case SceneManager::Scene::DEMO: + active_scene_ = std::make_unique<Game>(Game::Mode::DEMO); + break; + + case SceneManager::Scene::GAME: + Audio::get()->stopMusic(); + active_scene_ = std::make_unique<Game>(Game::Mode::GAME); + break; + + case SceneManager::Scene::GAME_OVER: + active_scene_ = std::make_unique<GameOver>(); + break; + + case SceneManager::Scene::ENDING: + active_scene_ = std::make_unique<Ending>(); + break; + + case SceneManager::Scene::ENDING2: + active_scene_ = std::make_unique<Ending2>(); + break; + + default: + break; + } + + current_scene_ = SceneManager::current; +} + +// SDL_AppIterate: executa un frame de l'escena activa +auto Director::iterate() -> SDL_AppResult { + if (SceneManager::current == SceneManager::Scene::QUIT) { + return SDL_APP_SUCCESS; + } + + // Si l'escena ha canviat (o s'ha demanat RESTART_CURRENT), canviar-la abans del frame + if (SceneManager::current != current_scene_ || SceneManager::current == SceneManager::Scene::RESTART_CURRENT) { + switchToActiveScene(); + } + + if (active_scene_) { + active_scene_->iterate(); + } + + return SDL_APP_CONTINUE; +} + +// SDL_AppEvent: despatxa un event a l'escena activa +auto Director::handleEvent(const SDL_Event& event) -> SDL_AppResult { + if (event.type == SDL_EVENT_QUIT) { + SceneManager::current = SceneManager::Scene::QUIT; + return SDL_APP_SUCCESS; + } + + if (active_scene_) { + active_scene_->handleEvent(event); + } + + return SDL_APP_CONTINUE; } \ No newline at end of file diff --git a/source/core/system/director.hpp b/source/core/system/director.hpp index 33c8c5e..92b47a4 100644 --- a/source/core/system/director.hpp +++ b/source/core/system/director.hpp @@ -2,29 +2,31 @@ #include <SDL3/SDL.h> +#include <memory> // Para unique_ptr #include <string> // Para string +#include "game/scene_manager.hpp" // Para SceneManager::Scene +#include "game/scenes/scene.hpp" // Para Scene base + class Director { public: - Director(); // Constructor - ~Director(); // Destructor - static auto run() -> int; // Bucle principal + Director(); // Constructor: inicialitza sistemes i crea l'escena inicial + ~Director(); // Destructor + + // SDL3 Callback API: un frame i un event + auto iterate() -> SDL_AppResult; + auto handleEvent(const SDL_Event& event) -> SDL_AppResult; private: // --- Variables --- std::string executable_path_; // Path del ejecutable std::string system_folder_; // Carpeta del sistema donde guardar datos + std::unique_ptr<Scene> active_scene_; // Escena activa + SceneManager::Scene current_scene_{SceneManager::Scene::LOGO}; // Tipus d'escena activa + // --- Funciones --- void createSystemFolder(const std::string& folder); // Crea la carpeta del sistema donde guardar datos void setFileList(); // Carga la configuración de assets desde assets.yaml - static void runLogo(); // Ejecuta la seccion de juego con el logo - static void runLoadingScreen(); // Ejecuta la seccion de juego de la pantalla de carga - static void runTitle(); // Ejecuta la seccion de juego con el titulo y los menus - static void runCredits(); // Ejecuta la seccion de los creditos del juego - static void runDemo(); // Ejecuta la seccion de la demo, donde se ven pantallas del juego - static void runEnding(); // Ejecuta la seccion del final del juego - static void runEnding2(); // Ejecuta la seccion del final del juego - static void runGameOver(); // Ejecuta la seccion del final de la partida - static void runGame(); // Ejecuta la seccion de juego donde se juega -}; \ No newline at end of file + void switchToActiveScene(); // Construeix l'escena segons SceneManager::current +}; diff --git a/source/core/system/global_events.cpp b/source/core/system/global_events.cpp index 6376b50..b9b7a74 100644 --- a/source/core/system/global_events.cpp +++ b/source/core/system/global_events.cpp @@ -1,19 +1,13 @@ #include "core/system/global_events.hpp" #include "core/input/mouse.hpp" -#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio -#include "game/scene_manager.hpp" // Para SceneManager -#include "game/ui/console.hpp" // Para Console +#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio +#include "game/ui/console.hpp" // Para Console namespace GlobalEvents { - // Comprueba los eventos que se pueden producir en cualquier sección del juego + // Comprueba los eventos que se pueden producir en cualquier sección del juego. + // Nota: SDL_EVENT_QUIT el gestiona Director::handleEvent() directament. void handle(const SDL_Event& event) { - // Evento de salida de la aplicación - if (event.type == SDL_EVENT_QUIT) { - SceneManager::current = SceneManager::Scene::QUIT; - return; - } - if (event.type == SDL_EVENT_RENDER_DEVICE_RESET || event.type == SDL_EVENT_RENDER_TARGETS_RESET) { // reLoadTextures(); } diff --git a/source/game/scenes/credits.cpp b/source/game/scenes/credits.cpp index 388f3f0..0feac46 100644 --- a/source/game/scenes/credits.cpp +++ b/source/game/scenes/credits.cpp @@ -37,12 +37,9 @@ Credits::Credits() Audio::get()->playMusic("title.ogg"); // Inicia la musica } -// Comprueba el manejador de eventos -void Credits::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void Credits::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -124,8 +121,7 @@ void Credits::update() { const float DELTA_TIME = delta_timer_->tick(); total_time_ += DELTA_TIME; // Actualiza el tiempo total - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza la máquina de estados @@ -238,10 +234,8 @@ void Credits::render() { Screen::get()->render(); } -// Bucle para el logo del juego -void Credits::run() { - while (SceneManager::current == SceneManager::Scene::CREDITS) { - update(); - render(); - } +// Un frame de l'escena (SDL3 Callback API) +void Credits::iterate() { + update(); + render(); } \ No newline at end of file diff --git a/source/game/scenes/credits.hpp b/source/game/scenes/credits.hpp index ade576f..482a91e 100644 --- a/source/game/scenes/credits.hpp +++ b/source/game/scenes/credits.hpp @@ -5,19 +5,22 @@ #include <memory> // Para shared_ptr #include <string> // Para string #include <vector> // Para vector + +#include "game/scenes/scene.hpp" // Para Scene class AnimatedSprite; // lines 11-11 class Surface; class PixelReveal; class DeltaTimer; -class Credits { +class Credits : public Scene { public: // --- Constructor y Destructor --- Credits(); - ~Credits(); // NOLINT(modernize-use-equals-default, performance-trivially-destructible) -- defined in .cpp for unique_ptr with forward declarations + ~Credits() override; // NOLINT(modernize-use-equals-default, performance-trivially-destructible) -- defined in .cpp for unique_ptr with forward declarations - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Tipos anidados --- @@ -55,7 +58,6 @@ class Credits { // --- Métodos privados --- void update(); // Actualiza las variables void render(); // Dibuja en pantalla - static void handleEvents(); // Comprueba el manejador de eventos static void handleInput(); // Comprueba las entradas void updateState(float delta_time); // Actualiza la máquina de estados void transitionToState(State new_state); // Transición entre estados diff --git a/source/game/scenes/ending.cpp b/source/game/scenes/ending.cpp index 029c56b..d09a499 100644 --- a/source/game/scenes/ending.cpp +++ b/source/game/scenes/ending.cpp @@ -19,7 +19,9 @@ #include "utils/utils.hpp" // Para PaletteColor // Destructor -Ending::~Ending() = default; +Ending::~Ending() { + Audio::get()->stopMusic(); +} // Constructor Ending::Ending() @@ -32,6 +34,7 @@ Ending::Ending() iniScenes(); // Inicializa las escenas Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); // Cambia el color del borde + Audio::get()->playMusic("ending1.ogg"); } // Actualiza el objeto @@ -39,8 +42,7 @@ void Ending::update() { const float DELTA_TIME = delta_timer_->tick(); total_time_ += DELTA_TIME; // Actualiza el tiempo total - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza la máquina de estados updateSpriteCovers(); // Actualiza las cortinillas de los elementos @@ -86,12 +88,9 @@ void Ending::render() { Screen::get()->render(); } -// Comprueba el manejador de eventos -void Ending::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void Ending::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -355,16 +354,10 @@ void Ending::iniScenes() { // NOLINT(readability-convert-member-functions-to-st scenes_.push_back(sc); } -// Bucle principal -void Ending::run() { - Audio::get()->playMusic("ending1.ogg"); - - while (SceneManager::current == SceneManager::Scene::ENDING) { - update(); - render(); - } - - Audio::get()->stopMusic(); +// Un frame de l'escena (SDL3 Callback API) +void Ending::iterate() { + update(); + render(); } // Actualiza las cortinillas de los elementos diff --git a/source/game/scenes/ending.hpp b/source/game/scenes/ending.hpp index b071084..ee097e0 100644 --- a/source/game/scenes/ending.hpp +++ b/source/game/scenes/ending.hpp @@ -5,19 +5,22 @@ #include <memory> // Para shared_ptr #include <string> // Para string #include <vector> // Para vector + +#include "game/scenes/scene.hpp" // Para Scene class Sprite; // lines 8-8 class Surface; // lines 9-9 class PixelReveal; class DeltaTimer; -class Ending { +class Ending : public Scene { public: // --- Constructor y Destructor --- Ending(); - ~Ending(); // NOLINT(modernize-use-equals-default, performance-trivially-destructible) -- defined in .cpp for unique_ptr with forward declarations + ~Ending() override; // NOLINT(modernize-use-equals-default, performance-trivially-destructible) -- defined in .cpp for unique_ptr with forward declarations - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Enumeraciones --- @@ -77,7 +80,6 @@ class Ending { // --- Métodos --- void update(); // Actualiza el objeto void render(); // Dibuja el final en pantalla - static void handleEvents(); // Comprueba el manejador de eventos static void handleInput(); // Comprueba las entradas void iniTexts(); // Inicializa los textos void iniPics(); // Inicializa las imágenes diff --git a/source/game/scenes/ending2.cpp b/source/game/scenes/ending2.cpp index 888a518..507adb9 100644 --- a/source/game/scenes/ending2.cpp +++ b/source/game/scenes/ending2.cpp @@ -41,14 +41,20 @@ Ending2::Ending2() placeSprites(); // Coloca los sprites en su sito createSpriteTexts(); // Crea los sprites con las texturas con los textos createTexts(); // Crea los sprites con las texturas con los textos del final + + Audio::get()->playMusic("ending2.ogg"); +} + +// Destructor +Ending2::~Ending2() { + Audio::get()->stopMusic(); } // Actualiza el objeto void Ending2::update() { const float DELTA_TIME = delta_timer_->tick(); - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza el estado @@ -95,12 +101,9 @@ void Ending2::render() { Screen::get()->render(); } -// Comprueba el manejador de eventos -void Ending2::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void Ending2::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -109,16 +112,10 @@ void Ending2::handleInput() { GlobalInputs::handle(); } -// Bucle principal -void Ending2::run() { - Audio::get()->playMusic("ending2.ogg"); - - while (SceneManager::current == SceneManager::Scene::ENDING2) { - update(); - render(); - } - - Audio::get()->stopMusic(); +// Un frame de l'escena (SDL3 Callback API) +void Ending2::iterate() { + update(); + render(); } // Actualiza el estado diff --git a/source/game/scenes/ending2.hpp b/source/game/scenes/ending2.hpp index ff8da99..0e2580d 100644 --- a/source/game/scenes/ending2.hpp +++ b/source/game/scenes/ending2.hpp @@ -7,19 +7,21 @@ #include <vector> // Para vector #include "core/rendering/sprite/dissolve_sprite.hpp" // Para SurfaceDissolveSprite +#include "game/scenes/scene.hpp" // Para Scene #include "utils/defines.hpp" // Para GameCanvas::WIDTH, GameCanvas::FIRST_QUAR... class MovingSprite; class DeltaTimer; -class Ending2 { +class Ending2 : public Scene { public: // --- Constructor y Destructor --- Ending2(); - ~Ending2() = default; + ~Ending2() override; - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Enumeraciones --- @@ -58,7 +60,6 @@ class Ending2 { // --- Métodos --- void update(); // Actualiza el objeto void render(); // Dibuja el final en pantalla - static void handleEvents(); // Comprueba el manejador de eventos static void handleInput(); // Comprueba las entradas void updateState(float delta_time); // Actualiza el estado void transitionToState(EndingState new_state); // Transición entre estados diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index 03fee35..0fc72d9 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -163,9 +163,19 @@ Game::Game(Mode mode) SceneManager::current = (mode_ == Mode::GAME) ? SceneManager::Scene::GAME : SceneManager::Scene::DEMO; SceneManager::options = SceneManager::Options::NONE; + + // Arranca la música del juego (abans a run()) + keepMusicPlaying(); + if (!scoreboard_data_->music && mode_ == Mode::GAME) { + Audio::get()->pauseMusic(); + } } Game::~Game() { + if (mode_ == Mode::GAME) { + Audio::get()->stopMusic(); + } + ItemTracker::destroy(); GameControl::change_player_skin = nullptr; @@ -188,38 +198,35 @@ Game::~Game() { #endif } -// Comprueba los eventos de la cola -void Game::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); +// Despatx d'un event (SDL3 Callback API) +void Game::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); #ifdef _DEBUG - // En modo editor: click del ratón cierra la consola - if (Console::get()->isActive() && MapEditor::get()->isActive() && - event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { - Console::get()->toggle(); - } - - if (!Console::get()->isActive()) { - // Tecla 9: toggle editor (funciona tanto dentro como fuera del editor) - if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_9 && static_cast<int>(event.key.repeat) == 0) { - if (MapEditor::get()->isActive()) { - GameControl::exit_editor(); - Notifier::get()->show({Locale::get()->get("game.editor_disabled")}); // NOLINT(readability-static-accessed-through-instance) - } else { - GameControl::enter_editor(); - Notifier::get()->show({Locale::get()->get("game.editor_enabled")}); // NOLINT(readability-static-accessed-through-instance) - } - } else if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_8 && static_cast<int>(event.key.repeat) == 0 && MapEditor::get()->isActive()) { - MapEditor::get()->showGrid(!MapEditor::get()->isGridEnabled()); - } else if (MapEditor::get()->isActive()) { - MapEditor::get()->handleEvent(event); - } else { - handleDebugEvents(event); - } - } -#endif + // En modo editor: click del ratón cierra la consola + if (Console::get()->isActive() && MapEditor::get()->isActive() && + event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { + Console::get()->toggle(); } + + if (!Console::get()->isActive()) { + // Tecla 9: toggle editor (funciona tanto dentro como fuera del editor) + if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_9 && static_cast<int>(event.key.repeat) == 0) { + if (MapEditor::get()->isActive()) { + GameControl::exit_editor(); + Notifier::get()->show({Locale::get()->get("game.editor_disabled")}); // NOLINT(readability-static-accessed-through-instance) + } else { + GameControl::enter_editor(); + Notifier::get()->show({Locale::get()->get("game.editor_enabled")}); // NOLINT(readability-static-accessed-through-instance) + } + } else if (event.type == SDL_EVENT_KEY_DOWN && event.key.key == SDLK_8 && static_cast<int>(event.key.repeat) == 0 && MapEditor::get()->isActive()) { + MapEditor::get()->showGrid(!MapEditor::get()->isGridEnabled()); + } else if (MapEditor::get()->isActive()) { + MapEditor::get()->handleEvent(event); + } else { + handleDebugEvents(event); + } + } +#endif } // Comprueba el teclado @@ -262,29 +269,17 @@ void Game::handleInput() { GlobalInputs::handle(); } -// Bucle para el juego -void Game::run() { - keepMusicPlaying(); - if (!scoreboard_data_->music && mode_ == Mode::GAME) { - Audio::get()->pauseMusic(); - } - - while (SceneManager::current == SceneManager::Scene::GAME || SceneManager::current == SceneManager::Scene::DEMO) { - update(); - render(); - } - - if (mode_ == Mode::GAME) { - Audio::get()->stopMusic(); - } +// Un frame de l'escena (SDL3 Callback API) +void Game::iterate() { + update(); + render(); } // Actualiza el juego, las variables, comprueba la entrada, etc. void Game::update() { const float DELTA_TIME = delta_timer_.tick(); - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas #ifdef _DEBUG Debug::get()->clear(); diff --git a/source/game/scenes/game.hpp b/source/game/scenes/game.hpp index ce42bbc..6c29525 100644 --- a/source/game/scenes/game.hpp +++ b/source/game/scenes/game.hpp @@ -8,6 +8,7 @@ #include <vector> // Para vector #include "game/entities/player.hpp" // Para PlayerSpawn +#include "game/scenes/scene.hpp" // Para Scene #include "utils/delta_timer.hpp" // Para DeltaTimer class Room; // lines 12-12 class RoomTracker; // lines 13-13 @@ -15,7 +16,7 @@ class Scoreboard; // lines 14-14 class Stats; // lines 15-15 class Surface; -class Game { +class Game : public Scene { public: // --- Estructuras --- enum class Mode { @@ -33,10 +34,11 @@ class Game { // --- Constructor y Destructor --- explicit Game(Mode mode); - ~Game(); + ~Game() override; - // --- Bucle para el juego --- - void run(); + // --- Bucle para el juego (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Constantes de tiempo --- @@ -57,7 +59,6 @@ class Game { // --- Métodos --- void update(); // Actualiza el juego, las variables, comprueba la entrada, etc. void render(); // Pinta los objetos en pantalla - void handleEvents(); // Comprueba los eventos de la cola void renderRoomName(); // Escribe el nombre de la pantalla void transitionToState(State new_state); // Cambia al estado especificado y resetea los timers void updatePlaying(float delta_time); // Actualiza el juego en estado PLAYING diff --git a/source/game/scenes/game_over.cpp b/source/game/scenes/game_over.cpp index 5c1eb07..6b74d96 100644 --- a/source/game/scenes/game_over.cpp +++ b/source/game/scenes/game_over.cpp @@ -49,8 +49,7 @@ void GameOver::update() { const float DELTA_TIME = delta_timer_->tick(); elapsed_time_ += DELTA_TIME; - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(); // Actualiza el estado de la escena updateColor(); // Actualiza el color usado para renderizar los textos e imagenes @@ -91,12 +90,9 @@ void GameOver::render() { Screen::get()->render(); } -// Comprueba el manejador de eventos -void GameOver::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void GameOver::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -105,12 +101,10 @@ void GameOver::handleInput() { GlobalInputs::handle(); } -// Bucle principal -void GameOver::run() { - while (SceneManager::current == SceneManager::Scene::GAME_OVER) { - update(); - render(); - } +// Un frame de l'escena (SDL3 Callback API) +void GameOver::iterate() { + update(); + render(); } // Actualiza el color usado para renderizar los textos e imagenes diff --git a/source/game/scenes/game_over.hpp b/source/game/scenes/game_over.hpp index b541fdd..b96337b 100644 --- a/source/game/scenes/game_over.hpp +++ b/source/game/scenes/game_over.hpp @@ -4,17 +4,20 @@ #include <memory> // Para shared_ptr #include <vector> // Para vector + +#include "game/scenes/scene.hpp" // Para Scene class AnimatedSprite; // lines 7-7 class DeltaTimer; // Forward declaration -class GameOver { +class GameOver : public Scene { public: // Constructor y Destructor GameOver(); - ~GameOver() = default; + ~GameOver() override = default; - // Bucle principal - void run(); + // Bucle principal (SDL3 Callback API) + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Enumeraciones --- @@ -45,10 +48,9 @@ class GameOver { static constexpr int NIGHTMARE_TEXT_Y_OFFSET = 120; // Offset Y del texto nightmare desde TEXT_Y // --- Métodos --- - void update(); // Actualiza el objeto - void render(); // Dibuja el final en pantalla - static void handleEvents(); // Comprueba el manejador de eventos - static void handleInput(); // Comprueba las entradas + void update(); // Actualiza el objeto + void render(); // Dibuja el final en pantalla + static void handleInput(); // Comprueba las entradas void updateState(); // Actualiza el estado y transiciones void updateColor(); // Actualiza el color usado para renderizar void renderSprites(); // Dibuja los sprites diff --git a/source/game/scenes/loading_screen.cpp b/source/game/scenes/loading_screen.cpp index 9e9897a..20f5d30 100644 --- a/source/game/scenes/loading_screen.cpp +++ b/source/game/scenes/loading_screen.cpp @@ -41,19 +41,23 @@ LoadingScreen::LoadingScreen() // Cambia el color del borde Screen::get()->setBorderColor(stringToColor("white")); transitionToState(State::SILENT1); + + // Ajusta el volumen i neteja la pantalla (abans a run()) + Audio::get()->setMusicVolume(50); + Screen::get()->start(); + Screen::get()->clearRenderer(); + Screen::get()->render(); } // Destructor LoadingScreen::~LoadingScreen() { Audio::get()->stopMusic(); + Audio::get()->setMusicVolume(100); } -// Comprueba el manejador de eventos -void LoadingScreen::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void LoadingScreen::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -347,8 +351,7 @@ void LoadingScreen::renderColoredBorder(PaletteColor color) { void LoadingScreen::update() { const float DELTA_TIME = delta_timer_->tick(); - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza el estado y gestiona transiciones @@ -400,22 +403,10 @@ void LoadingScreen::render() { Screen::get()->render(); } -// Bucle para el logo del juego -void LoadingScreen::run() { - // Ajusta el volumen - Audio::get()->setMusicVolume(50); - - // Limpia la pantalla - Screen::get()->start(); - Screen::get()->clearRenderer(); - Screen::get()->render(); - - while (SceneManager::current == SceneManager::Scene::LOADING_SCREEN) { - update(); - render(); - } - - Audio::get()->setMusicVolume(100); +// Un frame de l'escena (SDL3 Callback API) +void LoadingScreen::iterate() { + update(); + render(); } // Pinta el borde diff --git a/source/game/scenes/loading_screen.hpp b/source/game/scenes/loading_screen.hpp index 1cf2275..4dcb68d 100644 --- a/source/game/scenes/loading_screen.hpp +++ b/source/game/scenes/loading_screen.hpp @@ -5,19 +5,21 @@ #include <array> // Para std::array #include <memory> // Para shared_ptr +#include "game/scenes/scene.hpp" // Para Scene #include "utils/delta_timer.hpp" // Para DeltaTimer #include "utils/utils.hpp" // Para PaletteColor class Sprite; // Forward declaration class Surface; // Forward declaration -class LoadingScreen { +class LoadingScreen : public Scene { public: // --- Constructor y Destructor --- LoadingScreen(); - ~LoadingScreen(); + ~LoadingScreen() override; - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Enumeraciones --- @@ -81,7 +83,6 @@ class LoadingScreen { // --- Métodos --- void update(); // Actualiza las variables void render(); // Dibuja en pantalla - static void handleEvents(); // Comprueba el manejador de eventos static void handleInput(); // Comprueba las entradas void updateState(float delta_time); // Actualiza el estado actual void transitionToState(State new_state); // Transiciona a un nuevo estado diff --git a/source/game/scenes/logo.cpp b/source/game/scenes/logo.cpp index e64fb47..e8cc14b 100644 --- a/source/game/scenes/logo.cpp +++ b/source/game/scenes/logo.cpp @@ -54,12 +54,9 @@ Logo::Logo() Screen::get()->setBorderColor(static_cast<Uint8>(PaletteColor::BLACK)); } -// Comprueba el manejador de eventos -void Logo::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); - } +// Despatx d'un event (SDL3 Callback API) +void Logo::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); } // Comprueba las entradas @@ -201,8 +198,7 @@ void Logo::updateState(float delta_time) { void Logo::update() { const float DELTA_TIME = delta_timer_->tick(); - handleEvents(); // Comprueba los eventos - handleInput(); // Comprueba las entradas + handleInput(); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza el estado y gestiona transiciones updateJAILGAMES(DELTA_TIME); // Gestiona el logo de JAILGAME @@ -228,12 +224,10 @@ void Logo::render() { // NOLINT(readability-convert-member-functions-to-static) Screen::get()->render(); } -// Bucle para el logo del juego -void Logo::run() { - while (SceneManager::current == SceneManager::Scene::LOGO) { - update(); - render(); - } +// Un frame de l'escena (SDL3 Callback API) +void Logo::iterate() { + update(); + render(); } // Termina la sección diff --git a/source/game/scenes/logo.hpp b/source/game/scenes/logo.hpp index d9839c3..d334ca5 100644 --- a/source/game/scenes/logo.hpp +++ b/source/game/scenes/logo.hpp @@ -6,11 +6,12 @@ #include <memory> // Para shared_ptr #include <vector> // Para vector +#include "game/scenes/scene.hpp" // Para Scene #include "utils/delta_timer.hpp" // Para DeltaTimer class Sprite; // Forward declaration class Surface; // Forward declaration -class Logo { +class Logo : public Scene { public: // --- Tipos --- using EasingFunction = std::function<float(float)>; // Función de easing (permite lambdas) @@ -28,10 +29,11 @@ class Logo { // --- Constructor y Destructor --- Logo(); - ~Logo() = default; + ~Logo() override = default; - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Constantes de tiempo (en segundos) --- @@ -48,7 +50,6 @@ class Logo { // --- Métodos --- void update(); // Actualiza las variables void render(); // Dibuja en pantalla - static void handleEvents(); // Comprueba el manejador de eventos static void handleInput(); // Comprueba las entradas void updateJAILGAMES(float delta_time); // Gestiona el logo de JAILGAME (time-based) void updateTextureColors(); // Gestiona el color de las texturas diff --git a/source/game/scenes/scene.hpp b/source/game/scenes/scene.hpp new file mode 100644 index 0000000..bf2a7ff --- /dev/null +++ b/source/game/scenes/scene.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <SDL3/SDL.h> + +// Interfície base per a totes les escenes del joc. +// Cada escena concreta implementa iterate() (un frame) i handleEvent() (un event). +// Director crida aquests mètodes des de SDL_AppIterate / SDL_AppEvent. +class Scene { + public: + virtual ~Scene() = default; + virtual void iterate() = 0; + virtual void handleEvent(const SDL_Event& event) = 0; +}; diff --git a/source/game/scenes/title.cpp b/source/game/scenes/title.cpp index 1d033a9..59e0ba7 100644 --- a/source/game/scenes/title.cpp +++ b/source/game/scenes/title.cpp @@ -81,28 +81,25 @@ void Title::initMarquee() { last_active_letter_ = 0; } -// Comprueba el manejador de eventos -void Title::handleEvents() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - GlobalEvents::handle(event); +// Despatx d'un event (SDL3 Callback API) +void Title::handleEvent(const SDL_Event& event) { + GlobalEvents::handle(event); - // Manejo especial para captura de botones de gamepad - if (is_remapping_joystick_ && !remap_completed_ && - (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION)) { - handleJoystickRemap(event); - continue; // No procesar más este evento + // Manejo especial para captura de botones de gamepad + if (is_remapping_joystick_ && !remap_completed_ && + (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN || event.type == SDL_EVENT_GAMEPAD_AXIS_MOTION)) { + handleJoystickRemap(event); + return; // No procesar más este evento + } + + if (event.type == SDL_EVENT_KEY_DOWN && !Console::get()->isActive()) { + // Si estamos en modo remap de teclado, capturar tecla + if (is_remapping_keyboard_ && !remap_completed_) { + handleKeyboardRemap(event); } - - if (event.type == SDL_EVENT_KEY_DOWN && !Console::get()->isActive()) { - // Si estamos en modo remap de teclado, capturar tecla - if (is_remapping_keyboard_ && !remap_completed_) { - handleKeyboardRemap(event); - } - // Si estamos en el menú principal normal - else if (state_ == State::MAIN_MENU && !is_remapping_keyboard_ && !is_remapping_joystick_) { - handleMainMenuKeyPress(event.key.key); - } + // Si estamos en el menú principal normal + else if (state_ == State::MAIN_MENU && !is_remapping_keyboard_ && !is_remapping_joystick_) { + handleMainMenuKeyPress(event.key.key); } } } @@ -242,7 +239,6 @@ void Title::renderMarquee() const { void Title::update() { const float DELTA_TIME = delta_timer_->tick(); - handleEvents(); // Comprueba los eventos handleInput(DELTA_TIME); // Comprueba las entradas updateState(DELTA_TIME); // Actualiza el estado actual @@ -434,12 +430,10 @@ void Title::render() { Screen::get()->render(); } -// Bucle para el logo del juego -void Title::run() { - while (SceneManager::current == SceneManager::Scene::TITLE) { - update(); - render(); - } +// Un frame de l'escena (SDL3 Callback API) +void Title::iterate() { + update(); + render(); } // Crea y rellena la textura para mostrar los logros diff --git a/source/game/scenes/title.hpp b/source/game/scenes/title.hpp index d05b1d0..5fc1211 100644 --- a/source/game/scenes/title.hpp +++ b/source/game/scenes/title.hpp @@ -8,19 +8,21 @@ #include <vector> // Para vector #include "game/scene_manager.hpp" // Para SceneManager::Scene +#include "game/scenes/scene.hpp" // Para Scene #include "utils/delta_timer.hpp" // Para DeltaTimer class Sprite; // Forward declaration class Surface; // Forward declaration class Text; // Forward declaration -class Title { +class Title : public Scene { public: // --- Constructor y Destructor --- Title(); - ~Title(); + ~Title() override; - // --- Bucle principal --- - void run(); + // --- Bucle principal (SDL3 Callback API) --- + void iterate() override; + void handleEvent(const SDL_Event& event) override; private: // --- Estructuras y enumeraciones --- @@ -61,7 +63,6 @@ class Title { // --- Métodos --- void update(); // Actualiza las variables void render(); // Dibuja en pantalla - void handleEvents(); // Comprueba el manejador de eventos void handleMainMenuKeyPress(SDL_Keycode key); // Maneja las teclas del menu principal void handleInput(float delta_time); // Comprueba las entradas void updateState(float delta_time); // Actualiza el estado actual diff --git a/source/main.cpp b/source/main.cpp index 1659f45..c2b1c92 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -5,14 +5,24 @@ Empezado en Castalla el 01/07/2022. */ -#include <memory> +#define SDL_MAIN_USE_CALLBACKS 1 +#include <SDL3/SDL_main.h> #include "core/system/director.hpp" -auto main() -> int { - // Crea el objeto Director - auto director = std::make_unique<Director>(); - - // Bucle principal - return Director::run(); +SDL_AppResult SDL_AppInit(void** appstate, int /*argc*/, char* /*argv*/[]) { + *appstate = new Director(); + return SDL_APP_CONTINUE; +} + +SDL_AppResult SDL_AppIterate(void* appstate) { + return static_cast<Director*>(appstate)->iterate(); +} + +SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) { + return static_cast<Director*>(appstate)->handleEvent(*event); +} + +void SDL_AppQuit(void* appstate, SDL_AppResult /*result*/) { + delete static_cast<Director*>(appstate); }