sdl_callbacks

This commit is contained in:
2026-04-14 12:21:00 +02:00
parent c0accd25e2
commit f5da35bfb2
20 changed files with 406 additions and 177 deletions

View File

@@ -16,6 +16,7 @@
#include "asset.hpp" // Para Asset
#include "audio.hpp" // Para Audio
#include "external/fkyaml_node.hpp" // Para fkyaml::node
#include "global_events.hpp" // Para GlobalEvents::handle
#include "input.hpp" // Para Input
#include "lang.hpp" // Para setLanguage
#include "manage_hiscore_table.hpp" // Para ManageHiScoreTable
@@ -75,6 +76,9 @@ Director::Director(int argc, std::span<char*> argv) {
}
Director::~Director() {
// Libera las secciones primero: sus destructores pueden tocar Audio/Resource/Screen,
// que close() destruye a continuación.
resetActiveSection();
close();
Logger::put("\nBye!");
}
@@ -335,75 +339,96 @@ void Director::createSystemFolder(const std::string& folder) {
}
}
// Ejecuta la sección con el logo
void Director::runLogo() {
auto logo = std::make_unique<Logo>();
logo->run();
// Libera todos los unique_ptr de sección (solo uno tiene propiedad a la vez)
void Director::resetActiveSection() {
logo_.reset();
intro_.reset();
title_.reset();
game_.reset();
instructions_.reset();
hi_score_table_.reset();
credits_.reset();
}
// Ejecuta la sección con la secuencia de introducción
void Director::runIntro() {
auto intro = std::make_unique<Intro>();
intro->run();
}
// Destruye la sección anterior y construye la nueva cuando Section::name cambia
void Director::handleSectionTransition() {
// RESET: recarga recursos y vuelve a LOGO (el propio reset() cambia Section::name)
if (Section::name == Section::Name::RESET) {
resetActiveSection(); // libera recursos actuales antes del reload
reset();
}
// Ejecuta la sección con el título del juego
void Director::runTitle() {
auto title = std::make_unique<Title>();
title->run();
}
if (Section::name == last_built_section_name_) {
return; // ya tenemos la sección correcta viva
}
// Ejecuta la sección donde se juega al juego
void Director::runGame() {
Player::Id player_id = Player::Id::PLAYER1;
// Destruye la sección anterior
resetActiveSection();
switch (Section::options) {
case Section::Options::GAME_PLAY_1P:
player_id = Player::Id::PLAYER1;
// Construye la nueva
switch (Section::name) {
case Section::Name::LOGO:
logo_ = std::make_unique<Logo>();
break;
case Section::Options::GAME_PLAY_2P:
player_id = Player::Id::PLAYER2;
case Section::Name::INTRO:
intro_ = std::make_unique<Intro>();
break;
case Section::Options::GAME_PLAY_BOTH:
player_id = Player::Id::BOTH_PLAYERS;
case Section::Name::TITLE:
title_ = std::make_unique<Title>();
break;
case Section::Name::GAME: {
Player::Id player_id = Player::Id::PLAYER1;
switch (Section::options) {
case Section::Options::GAME_PLAY_1P:
player_id = Player::Id::PLAYER1;
break;
case Section::Options::GAME_PLAY_2P:
player_id = Player::Id::PLAYER2;
break;
case Section::Options::GAME_PLAY_BOTH:
player_id = Player::Id::BOTH_PLAYERS;
break;
default:
break;
}
#ifdef _DEBUG
const int CURRENT_STAGE = debug_config.initial_stage;
#else
constexpr int CURRENT_STAGE = 0;
#endif
game_ = std::make_unique<Game>(player_id, CURRENT_STAGE, Game::DEMO_OFF);
break;
}
case Section::Name::GAME_DEMO: {
const auto PLAYER_ID = static_cast<Player::Id>((rand() % 2) + 1);
constexpr auto CURRENT_STAGE = 0;
game_ = std::make_unique<Game>(PLAYER_ID, CURRENT_STAGE, Game::DEMO_ON);
break;
}
case Section::Name::INSTRUCTIONS:
instructions_ = std::make_unique<Instructions>();
break;
case Section::Name::CREDITS:
credits_ = std::make_unique<Credits>();
break;
case Section::Name::HI_SCORE_TABLE:
hi_score_table_ = std::make_unique<HiScoreTable>();
break;
case Section::Name::RESET:
case Section::Name::QUIT:
default:
break;
}
#ifdef _DEBUG
const int CURRENT_STAGE = debug_config.initial_stage;
#else
constexpr int CURRENT_STAGE = 0;
#endif
auto game = std::make_unique<Game>(player_id, CURRENT_STAGE, Game::DEMO_OFF);
game->run();
}
// Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions() {
auto instructions = std::make_unique<Instructions>();
instructions->run();
}
// Ejecuta la sección donde se muestran los creditos del programa
void Director::runCredits() {
auto credits = std::make_unique<Credits>();
credits->run();
}
// Ejecuta la sección donde se muestra la tabla de puntuaciones
void Director::runHiScoreTable() {
auto hi_score_table = std::make_unique<HiScoreTable>();
hi_score_table->run();
}
// Ejecuta el juego en modo demo
void Director::runDemoGame() {
const auto PLAYER_ID = static_cast<Player::Id>((rand() % 2) + 1);
constexpr auto CURRENT_STAGE = 0;
auto game = std::make_unique<Game>(PLAYER_ID, CURRENT_STAGE, Game::DEMO_ON);
game->run();
last_built_section_name_ = Section::name;
}
// Reinicia objetos y vuelve a la sección inicial
@@ -418,43 +443,58 @@ void Director::reset() {
Section::name = Section::Name::LOGO;
}
auto Director::run() -> int {
// Bucle principal
while (Section::name != Section::Name::QUIT) {
switch (Section::name) {
case Section::Name::RESET:
reset();
break;
case Section::Name::LOGO:
runLogo();
break;
case Section::Name::INTRO:
runIntro();
break;
case Section::Name::TITLE:
runTitle();
break;
case Section::Name::GAME:
runGame();
break;
case Section::Name::HI_SCORE_TABLE:
runHiScoreTable();
break;
case Section::Name::GAME_DEMO:
runDemoGame();
break;
case Section::Name::INSTRUCTIONS:
runInstructions();
break;
case Section::Name::CREDITS:
runCredits();
break;
default:
break;
}
// Avanza un frame de la sección activa (llamado desde SDL_AppIterate)
auto Director::iterate() -> SDL_AppResult {
if (Section::name == Section::Name::QUIT) {
return SDL_APP_SUCCESS;
}
return 0;
// Gestiona las transiciones entre secciones (destruye la anterior y construye la nueva)
handleSectionTransition();
// Ejecuta un frame de la sección activa
if (logo_) {
logo_->iterate();
} else if (intro_) {
intro_->iterate();
} else if (title_) {
title_->iterate();
} else if (game_) {
game_->iterate();
} else if (instructions_) {
instructions_->iterate();
} else if (hi_score_table_) {
hi_score_table_->iterate();
} else if (credits_) {
credits_->iterate();
}
return (Section::name == Section::Name::QUIT) ? SDL_APP_SUCCESS : SDL_APP_CONTINUE;
}
// Procesa un evento SDL (llamado desde SDL_AppEvent)
auto Director::handleEvent(SDL_Event& event) -> SDL_AppResult {
// Eventos globales (SDL_EVENT_QUIT, resize, render target reset, hotplug, service menu, ratón)
GlobalEvents::handle(event);
// Reenvía a la sección activa
if (logo_) {
logo_->handleEvent(event);
} else if (intro_) {
intro_->handleEvent(event);
} else if (title_) {
title_->handleEvent(event);
} else if (game_) {
game_->handleEvent(event);
} else if (instructions_) {
instructions_->handleEvent(event);
} else if (hi_score_table_) {
hi_score_table_->handleEvent(event);
} else if (credits_) {
credits_->handleEvent(event);
}
return (Section::name == Section::Name::QUIT) ? SDL_APP_SUCCESS : SDL_APP_CONTINUE;
}
// Apaga el sistema de forma segura