aplanat sub-bucles anidats de pausa, game over, instruccions i demo (milestone 2)

- Game::runPausedGame() convertit a enterPausedGame() + despatx directe en run()
- Game::runGameOverScreen() convertit a enterGameOverScreen() + despatx directe
- Eliminada variable static postFade, convertida a membre gameOverPostFade
- Extret SDL_PollEvent de updateGameOverScreen() a checkGameOverEvents()
- Game::run() refactoritzat amb iterate() + hasFinished() per preparar callbacks
- Title::runInstructions() i runDemoGame() convertits a no-bloquejants
- Instructions ara usa finished/quitRequested en lloc de modificar section directament
- Instructions exposa start(), update(), checkEvents(), render(), hasFinished()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 19:15:54 +02:00
parent 9365f80e8b
commit 18c4d6032d
7 changed files with 252 additions and 124 deletions

View File

@@ -305,6 +305,9 @@ void Game::init() {
coffeeMachineEnabled = false;
pauseCounter = 0;
leavingPauseMenu = false;
pauseInitialized = false;
gameOverInitialized = false;
gameOverPostFade = 0;
if (demo.enabled) {
const int num = rand() % 2;
@@ -2939,45 +2942,69 @@ bool Game::isDeathShaking() {
return deathShake.active;
}
// Bucle para el juego
void Game::run() {
while (section->name == SECTION_PROG_GAME) {
// Sección juego en pausa
if (section->subsection == SUBSECTION_GAME_PAUSE) {
runPausedGame();
// Ejecuta un frame del juego
void Game::iterate() {
// Sección juego en pausa
if (section->subsection == SUBSECTION_GAME_PAUSE) {
if (!pauseInitialized) {
enterPausedGame();
}
updatePausedGame();
checkEvents();
renderPausedGame();
}
// Sección Game Over
if (section->subsection == SUBSECTION_GAME_GAMEOVER) {
runGameOverScreen();
// Sección Game Over
else if (section->subsection == SUBSECTION_GAME_GAMEOVER) {
if (!gameOverInitialized) {
enterGameOverScreen();
}
updateGameOverScreen();
checkGameOverEvents();
renderGameOverScreen();
}
// Sección juego jugando
if ((section->subsection == SUBSECTION_GAME_PLAY_1P) || (section->subsection == SUBSECTION_GAME_PLAY_2P)) {
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) {
// Reproduce la música
if (!gameCompleted) {
if (players[0]->isAlive()) {
JA_PlayMusic(gameMusic);
}
// Sección juego jugando
else if ((section->subsection == SUBSECTION_GAME_PLAY_1P) || (section->subsection == SUBSECTION_GAME_PLAY_2P)) {
// Resetea los flags de inicialización de sub-estados
pauseInitialized = false;
gameOverInitialized = false;
// Si la música no está sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) {
// Reproduce la música
if (!gameCompleted) {
if (players[0]->isAlive()) {
JA_PlayMusic(gameMusic);
}
}
}
#ifdef PAUSE
if (!pause)
update();
#else
// Actualiza la lógica del juego
if (!pause)
update();
#else
// Actualiza la lógica del juego
update();
#endif
// Comprueba los eventos que hay en cola
checkEvents();
// Comprueba los eventos que hay en cola
checkEvents();
// Dibuja los objetos
render();
}
// Dibuja los objetos
render();
}
}
// Indica si el juego ha terminado
bool Game::hasFinished() const {
return section->name != SECTION_PROG_GAME;
}
// Bucle para el juego
void Game::run() {
while (!hasFinished()) {
iterate();
}
}
@@ -3078,8 +3105,8 @@ void Game::renderPausedGame() {
screen->blit();
}
// Bucle para el menu de pausa del juego
void Game::runPausedGame() {
// Inicializa el estado de pausa del juego
void Game::enterPausedGame() {
// Pone en pausa la música
if (JA_GetMusicState() == JA_MUSIC_PLAYING) {
JA_PauseMusic();
@@ -3091,19 +3118,11 @@ void Game::runPausedGame() {
// Inicializa variables
pauseCounter = 90;
while ((section->subsection == SUBSECTION_GAME_PAUSE) && (section->name == SECTION_PROG_GAME)) {
updatePausedGame();
checkEvents();
renderPausedGame();
}
pauseInitialized = true;
}
// Actualiza los elementos de la pantalla de game over
void Game::updateGameOverScreen() {
// Variables
static int postFade = 0;
// Calcula la lógica de los objetos
if (SDL_GetTicks() - ticks > ticksSpeed) {
// Actualiza el contador de ticks
@@ -3117,7 +3136,7 @@ void Game::updateGameOverScreen() {
// Si ha terminado el fade, actua segun se haya operado
if (fade->hasEnded()) {
switch (postFade) {
switch (gameOverPostFade) {
case 0: // YES
section->name = SECTION_PROG_GAME;
deleteAllVectorObjects();
@@ -3142,12 +3161,12 @@ void Game::updateGameOverScreen() {
// Comprueba si se ha seleccionado algún item del menú
switch (gameOverMenu->getItemSelected()) {
case 0: // YES
postFade = 0;
gameOverPostFade = 0;
fade->activateFade();
break;
case 1: // NO
postFade = 1;
gameOverPostFade = 1;
fade->activateFade();
break;
@@ -3156,8 +3175,10 @@ void Game::updateGameOverScreen() {
}
}
}
}
// Comprueba los eventos que hay en la cola
// Comprueba los eventos de la pantalla de game over
void Game::checkGameOverEvents() {
while (SDL_PollEvent(eventHandler) != 0) {
// Evento de salida de la aplicación
if (eventHandler->type == SDL_EVENT_QUIT) {
@@ -3165,7 +3186,7 @@ void Game::updateGameOverScreen() {
break;
} else if (eventHandler->type == SDL_EVENT_KEY_DOWN && eventHandler->key.repeat == 0) {
if (gameCompleted) {
postFade = 1;
gameOverPostFade = 1;
fade->activateFade();
JA_PlaySound(itemPickUpSound);
}
@@ -3229,18 +3250,15 @@ void Game::renderGameOverScreen() {
screen->blit();
}
// Bucle para la pantalla de game over
void Game::runGameOverScreen() {
// Inicializa el estado de game over
void Game::enterGameOverScreen() {
// Guarda los puntos
saveScoreFile();
// Reinicia el menu
gameOverMenu->reset();
while ((section->subsection == SUBSECTION_GAME_GAMEOVER) && (section->name == SECTION_PROG_GAME)) {
updateGameOverScreen();
renderGameOverScreen();
}
gameOverPostFade = 0;
gameOverInitialized = true;
}
// Indica si se puede crear una powerball