tots els singletons tornats a fer a la vieja y gorda usanza

This commit is contained in:
2025-05-30 10:17:41 +02:00
parent 64b6f66044
commit f661da5215
29 changed files with 322 additions and 379 deletions

View File

@@ -5,27 +5,17 @@
#include <string> // Para allocator, string, char_traits, operator+ #include <string> // Para allocator, string, char_traits, operator+
#include "utils.h" // Para getFileName #include "utils.h" // Para getFileName
// Instancia estática del singleton // Singleton
std::unique_ptr<Asset> Asset::instance_ = nullptr; Asset *Asset::instance_ = nullptr;
// Inicializa la instancia única del singleton // Inicializa la instancia única del singleton
void Asset::init(const std::string &executable_path) void Asset::init(const std::string &executable_path) { Asset::instance_ = new Asset(executable_path); }
{
if (!instance_)
instance_ = std::unique_ptr<Asset>(new Asset(executable_path));
}
// Libera la instancia única // Libera la instancia
void Asset::destroy() void Asset::destroy() { delete Asset::instance_; }
{
instance_.reset();
}
// Obtiene la instancia única // Obtiene la instancia
Asset *Asset::get() Asset *Asset::get() { return Asset::instance_; }
{
return instance_.get();
}
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute) void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)

View File

@@ -3,6 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <iostream>
#include "utils.h" #include "utils.h"
// Tipos de recursos gestionados por Asset // Tipos de recursos gestionados por Asset
@@ -24,31 +25,19 @@ enum class AssetType : int
class Asset class Asset
{ {
public: public:
// Inicializa la instancia única del singleton // --- Métodos de singleton ---
static void init(const std::string &executable_path); static void init(const std::string &executable_path); // Inicializa el objeto Asset
static void destroy(); // Libera el objeto Asset
static Asset *get(); // Obtiene el puntero al objeto Asset
// Libera la instancia única // --- Métodos para la gestión de recursos ---
static void destroy(); void add(const std::string &file, AssetType type, bool required = true, bool absolute = false); // Añade un recurso a la lista
std::string get(const std::string &text) const; // Obtiene la ruta completa de un recurso a partir de su nombre
// Obtiene la instancia única bool check() const; // Verifica la existencia de todos los recursos requeridos
static Asset *get(); std::vector<std::string> getListByType(AssetType type) const; // Devuelve una lista de archivos de un tipo concreto
// Añade un recurso a la lista
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);
// Obtiene la ruta completa de un recurso a partir de su nombre
std::string get(const std::string &text) const;
// Verifica la existencia de todos los recursos requeridos
bool check() const;
// Devuelve una lista de archivos de un tipo concreto
std::vector<std::string> getListByType(AssetType type) const;
private: private:
friend std::unique_ptr<Asset>::deleter_type; // --- Estructura interna para almacenar información de cada recurso ---
// Estructura interna para almacenar información de cada recurso
struct AssetItem struct AssetItem
{ {
std::string file; // Ruta del fichero desde la raíz del directorio std::string file; // Ruta del fichero desde la raíz del directorio
@@ -59,21 +48,22 @@ private:
: file(filePath), type(assetType), required(isRequired) {} : file(filePath), type(assetType), required(isRequired) {}
}; };
// Variables internas // --- Variables internas ---
int longest_name_ = 0; // Longitud del nombre más largo int longest_name_ = 0; // Longitud del nombre más largo
std::vector<AssetItem> file_list_; // Lista con todas las rutas de recursos std::vector<AssetItem> file_list_; // Lista con todas las rutas de recursos
std::string executable_path_; // Ruta del ejecutable std::string executable_path_; // Ruta del ejecutable
// Métodos internos // --- Métodos internos ---
bool checkFile(const std::string &path) const; // Verifica si un archivo existe bool checkFile(const std::string &path) const; // Verifica si un archivo existe
std::string getTypeName(AssetType type) const; // Devuelve el nombre textual del tipo de recurso std::string getTypeName(AssetType type) const; // Devuelve el nombre textual del tipo de recurso
// Patrón Singleton: constructor y destructor privados, sin copia ni asignación // --- Patrón Singleton ---
Asset(const std::string &executable_path) explicit Asset(const std::string &executable_path)
: executable_path_(executable_path) {}; : executable_path_(executable_path) {}
~Asset() = default; ~Asset() = default;
Asset(const Asset &) = delete; Asset(const Asset &) = delete;
Asset &operator=(const Asset &) = delete; Asset &operator=(const Asset &) = delete;
static std::unique_ptr<Asset> instance_; // --- Singleton ---
static Asset *instance_;
}; };

View File

@@ -4,6 +4,18 @@
#include "resource.h" #include "resource.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
// Singleton
Audio *Audio::instance_ = nullptr;
// Inicializa la instancia única del singleton
void Audio::init() { Audio::instance_ = new Audio(); }
// Libera la instancia
void Audio::destroy() { delete Audio::instance_; }
// Obtiene la instancia
Audio *Audio::get() { return Audio::instance_; }
// Constructor // Constructor
Audio::Audio() Audio::Audio()
{ {
@@ -26,10 +38,7 @@ Audio::Audio()
} }
// Destructor // Destructor
Audio::~Audio() Audio::~Audio() { JA_Quit(); }
{
JA_Quit();
}
// Reproduce la música // Reproduce la música
void Audio::playMusic(const std::string &name, const int loop) void Audio::playMusic(const std::string &name, const int loop)

View File

@@ -6,55 +6,55 @@
class Audio class Audio
{ {
public: public:
// === Singleton === // --- Métodos de singleton ---
// Obtención de la instancia única (Meyers Singleton) static void init(); // Inicializa el objeto Audio
static Audio &get() static void destroy(); // Libera el objeto Audio
{ static Audio *get(); // Obtiene el puntero al objeto Audio
static Audio instance;
return instance;
}
// === Control de Música === // --- Control de Música ---
void playMusic(const std::string &name, int loop = -1); // Reproducir música en bucle void playMusic(const std::string &name, int loop = -1); // Reproducir música en bucle
void pauseMusic(); // Pausar reproducción de música void pauseMusic(); // Pausar reproducción de música
void stopMusic(); // Detener completamente la música void stopMusic(); // Detener completamente la música
void fadeOutMusic(int milliseconds); // Fundido de salida de la música void fadeOutMusic(int milliseconds); // Fundido de salida de la música
// === Control de Sonidos === // --- Control de Sonidos ---
void playSound(const std::string &name); // Reproducir sonido puntual void playSound(const std::string &name); // Reproducir sonido puntual
void stopAllSounds(); // Detener todos los sonidos void stopAllSounds(); // Detener todos los sonidos
// === Configuración General === // --- Configuración General ---
void enable() { enabled_ = true; } // Habilitar audio void enable() { enabled_ = true; } // Habilitar audio
void disable() { enabled_ = false; } // Deshabilitar audio void disable() { enabled_ = false; } // Deshabilitar audio
void enable(bool value) { enabled_ = value; } // Establecer estado general void enable(bool value) { enabled_ = value; } // Establecer estado general
void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general
// === Configuración de Sonidos === // --- Configuración de Sonidos ---
void enableSound() { sound_enabled_ = true; } // Habilitar sonidos void enableSound() { sound_enabled_ = true; } // Habilitar sonidos
void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos
void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos
void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos
// === Configuración de Música === // --- Configuración de Música ---
void enableMusic() { music_enabled_ = true; } // Habilitar música void enableMusic() { music_enabled_ = true; } // Habilitar música
void disableMusic() { music_enabled_ = false; } // Deshabilitar música void disableMusic() { music_enabled_ = false; } // Deshabilitar música
void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música
void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música
// === Control de Volumen === // --- Control de Volumen ---
void setSoundVolume(int volume); // Ajustar volumen de efectos void setSoundVolume(int volume); // Ajustar volumen de efectos
void setMusicVolume(int volume); // Ajustar volumen de música void setMusicVolume(int volume); // Ajustar volumen de música
private: private:
// === Variables de Estado === // --- Variables de Estado ---
bool enabled_ = true; // Estado general del audio bool enabled_ = true; // Estado general del audio
bool sound_enabled_ = true; // Estado de los efectos de sonido bool sound_enabled_ = true; // Estado de los efectos de sonido
bool music_enabled_ = true; // Estado de la música bool music_enabled_ = true; // Estado de la música
// === Patrón Singleton === // --- Patrón Singleton ---
Audio(); // Constructor privado Audio(); // Constructor privado
~Audio(); // Destructor privado ~Audio(); // Destructor privado
Audio(const Audio &) = delete; // Evitar copia Audio(const Audio &) = delete; // Evitar copia
Audio &operator=(const Audio &) = delete; // Evitar asignación Audio &operator=(const Audio &) = delete; // Evitar asignación
// --- Singleton ---
static Audio *instance_;
}; };

View File

@@ -414,6 +414,6 @@ void Balloon::playSound()
{ {
if (sound_enabled_) if (sound_enabled_)
{ {
Audio::get().playSound(sound_); Audio::get()->playSound(sound_);
} }
} }

View File

@@ -320,7 +320,7 @@ int BalloonManager::destroyAllBalloons()
} }
balloon_deploy_counter_ = 300; balloon_deploy_counter_ = 300;
Audio::get().playSound("power_ball_explosion.wav"); Audio::get()->playSound("power_ball_explosion.wav");
Screen::get()->flash(FLASH_COLOR, 3); Screen::get()->flash(FLASH_COLOR, 3);
Screen::get()->shake(); Screen::get()->shake();

View File

@@ -71,7 +71,7 @@ Credits::~Credits()
SDL_DestroyTexture(text_texture_); SDL_DestroyTexture(text_texture_);
SDL_DestroyTexture(canvas_); SDL_DestroyTexture(canvas_);
resetVolume(); resetVolume();
Audio::get().stopMusic(); Audio::get()->stopMusic();
} }
// Bucle principal // Bucle principal
@@ -437,7 +437,7 @@ void Credits::updateBlackRects()
{ {
// Si los rectangulos izquierdo y derecho han llegado al centro // Si los rectangulos izquierdo y derecho han llegado al centro
setVolume(0); setVolume(0);
Audio::get().stopMusic(); Audio::get()->stopMusic();
if (counter_pre_fade_ == 400) if (counter_pre_fade_ == 400)
{ {
fade_out_->activate(); fade_out_->activate();
@@ -471,7 +471,7 @@ void Credits::updateAllFades()
fade_in_->update(); fade_in_->update();
if (fade_in_->hasEnded()) if (fade_in_->hasEnded())
{ {
Audio::get().playMusic("credits.ogg"); Audio::get()->playMusic("credits.ogg");
} }
fade_out_->update(); fade_out_->update();
@@ -485,14 +485,14 @@ void Credits::updateAllFades()
void Credits::setVolume(int amount) void Credits::setVolume(int amount)
{ {
options.audio.music.volume = std::clamp(amount, 0, 100); options.audio.music.volume = std::clamp(amount, 0, 100);
Audio::get().setMusicVolume(options.audio.music.volume); Audio::get()->setMusicVolume(options.audio.music.volume);
} }
// Reestablece el nivel de volumen // Reestablece el nivel de volumen
void Credits::resetVolume() void Credits::resetVolume()
{ {
options.audio.music.volume = initial_volume_; options.audio.music.volume = initial_volume_;
Audio::get().setMusicVolume(options.audio.music.volume); Audio::get()->setMusicVolume(options.audio.music.volume);
} }
// Cambia el color del fondo // Cambia el color del fondo

View File

@@ -16,48 +16,51 @@ class Fade;
class Player; class Player;
class TiledBG; class TiledBG;
constexpr int PLAY_AREA_HEIGHT = 200;
class Credits class Credits
{ {
public: public:
// --- Constructores y destructor ---
Credits(); Credits();
~Credits(); ~Credits();
void run(); // Bucle principal // --- Bucle principal ---
void run();
private: private:
// === Objetos Principales === // --- Constantes de clase ---
static constexpr int PLAY_AREA_HEIGHT = 200;
// --- Objetos principales ---
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo
std::unique_ptr<Fade> fade_in_; // Fundido de entrada std::unique_ptr<Fade> fade_in_; // Fundido de entrada
std::unique_ptr<Fade> fade_out_; // Fundido de salida std::unique_ptr<Fade> fade_out_; // Fundido de salida
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
// === Gestión de Texturas === // --- Gestión de texturas ---
SDL_Texture *text_texture_; // Textura con el texto SDL_Texture *text_texture_; // Textura con el texto de créditos
SDL_Texture *canvas_; // Textura donde dibujarlo todo SDL_Texture *canvas_; // Textura donde se dibuja todo
// === Temporización y Contadores === // --- Temporización y contadores ---
Uint64 ticks_ = 0; // Control de velocidad del programa Uint64 ticks_ = 0; // Control de velocidad del programa
Uint32 counter_ = 0; // Contador principal de lógica Uint32 counter_ = 0; // Contador principal de lógica
Uint32 counter_pre_fade_ = 0; // Activación del fundido final Uint32 counter_pre_fade_ = 0; // Activación del fundido final
Uint32 counter_prevent_endless_ = 0; // Prevención de bucle infinito Uint32 counter_prevent_endless_ = 0; // Prevención de bucle infinito
// === Variables de Estado === // --- Variables de estado ---
bool fading_ = false; // Estado del fade final bool fading_ = false; // Estado del fade final
bool want_to_pass_ = false; // Jugador quiere saltarse créditos bool want_to_pass_ = false; // Jugador quiere saltarse créditos
bool mini_logo_on_position_ = false; // Minilogo en posición final bool mini_logo_on_position_ = false; // Minilogo en posición final
// === Diseño y Posicionamiento === // --- Diseño y posicionamiento ---
float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
int mini_logo_final_pos_ = 0; // Posición final del minilogo int mini_logo_final_pos_ = 0; // Posición final del minilogo
// === Control de Audio === // --- Control de audio ---
int initial_volume_ = options.audio.music.volume; // Volumen inicial int initial_volume_ = options.audio.music.volume; // Volumen inicial
int steps_ = 0; // Pasos para reducir audio int steps_ = 0; // Pasos para reducir audio
// === Rectángulos de Renderizado === // --- Rectángulos de renderizado ---
// Texto de créditos // Texto de créditos
SDL_FRect credits_rect_src_ = param.game.game_area.rect; SDL_FRect credits_rect_src_ = param.game.game_area.rect;
SDL_FRect credits_rect_dst_ = param.game.game_area.rect; SDL_FRect credits_rect_dst_ = param.game.game_area.rect;
@@ -98,28 +101,28 @@ private:
// Borde para la ventana // Borde para la ventana
SDL_FRect red_rect = play_area_; // Delimitador de ventana SDL_FRect red_rect = play_area_; // Delimitador de ventana
// === Métodos del Bucle Principal === // --- Métodos del bucle principal ---
void update(); // Actualización principal void update(); // Actualización principal de la lógica
void render(); // Renderizado void render(); // Renderizado de la escena
void checkEvents(); // Manejo de eventos void checkEvents(); // Manejo de eventos
void checkInput(); // Procesamiento de entrada void checkInput(); // Procesamiento de entrada
// === Métodos de Renderizado === // --- Métodos de renderizado ---
void fillTextTexture(); // Crear textura de texto void fillTextTexture(); // Crear textura de texto de créditos
void fillCanvas(); // Renderizar todos los sprites void fillCanvas(); // Renderizar todos los sprites y fondos
void updateTextureDstRects(); // Actualizar destinos de texturas void updateTextureDstRects(); // Actualizar destinos de texturas
// === Métodos de Lógica del Juego === // --- Métodos de lógica del juego ---
void throwBalloons(); // Lanzar globos al escenario void throwBalloons(); // Lanzar globos al escenario
void initPlayers(); // Inicializar jugadores void initPlayers(); // Inicializar jugadores
void updateAllFades(); // Actualizar estados de fade void updateAllFades(); // Actualizar estados de fade
void cycleColors(); // Cambiar colores de fondo void cycleColors(); // Cambiar colores de fondo
// === Métodos de Interfaz === // --- Métodos de interfaz ---
void updateBlackRects(); // Actualizar rectángulos negros void updateBlackRects(); // Actualizar rectángulos negros (letterbox)
void updateRedRect(); // Actualizar rectángulo rojo void updateRedRect(); // Actualizar rectángulo rojo (borde)
// === Métodos de Audio === // --- Métodos de audio ---
void setVolume(int amount); // Establecer volumen void setVolume(int amount); // Establecer volumen
void resetVolume(); // Restablecer volumen void resetVolume(); // Restablecer volumen
}; };

View File

@@ -34,6 +34,7 @@
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.h" // Para Name, Options, name, options #include "section.h" // Para Name, Options, name, options
#include "service_menu.h" // Para ServiceMenu
#include "title.h" // Para Title #include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides #include "utils.h" // Para Overrides, overrides
@@ -91,13 +92,14 @@ void Director::init()
loadParams(); // Carga los parámetros del programa loadParams(); // Carga los parámetros del programa
loadScoreFile(); // Carga el archivo de puntuaciones loadScoreFile(); // Carga el archivo de puntuaciones
// Inicialización de subsistemas // Inicialización de subsistemas principales
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language))); // Carga el archivo de idioma lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language))); // Carga el archivo de idioma
Screen::init(); // Inicializa la pantalla y el sistema de renderizado Screen::init(); // Inicializa la pantalla y el sistema de renderizado
Audio::get(); // Activa el sistema de audio Audio::init(); // Activa el sistema de audio
Resource::init(); // Inicializa el sistema de gestión de recursos Resource::init(); // Inicializa el sistema de gestión de recursos
Input::init(Asset::get()->get("gamecontrollerdb.txt")); // Carga configuración de controles Input::init(Asset::get()->get("gamecontrollerdb.txt")); // Carga configuración de controles
bindInputs(); // Asigna los controles a la entrada del sistema bindInputs(); // Asigna los controles a la entrada del sistema
ServiceMenu::init(); // Inicializa el menú de servicio
// Inicialización del sistema de notificaciones // Inicialización del sistema de notificaciones
Notifier::init(std::string(), Resource::get()->getText("8bithud")); Notifier::init(std::string(), Resource::get()->getText("8bithud"));
@@ -109,20 +111,26 @@ void Director::init()
#endif #endif
} }
// Cierra todo // Cierra todo y libera recursos del sistema y de los singletons
void Director::close() void Director::close()
{ {
// Guarda las opciones actuales en el archivo de configuración
saveOptionsFile(Asset::get()->get("config.txt")); saveOptionsFile(Asset::get()->get("config.txt"));
Notifier::destroy(); // Libera los singletons y recursos en orden inverso al de inicialización
Input::destroy(); Notifier::destroy(); // Libera el sistema de notificaciones
Resource::destroy(); ServiceMenu::destroy(); // Libera el sistema de menú de servicio
Screen::destroy(); Input::destroy(); // Libera el sistema de entrada
Asset::destroy(); Resource::destroy(); // Libera el sistema de recursos gráficos y de texto
Audio::destroy(); // Libera el sistema de audio
Screen::destroy(); // Libera el sistema de pantalla y renderizado
Asset::destroy(); // Libera el gestor de archivos
// Libera todos los recursos de SDL
SDL_Quit(); SDL_Quit();
#ifdef ARCADE #ifdef ARCADE
// Si está en modo arcade, apaga el sistema si corresponde
shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER); shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER);
#endif #endif
} }
@@ -460,7 +468,7 @@ void Director::setFileList()
void Director::checkProgramArguments(int argc, const char *argv[]) void Director::checkProgramArguments(int argc, const char *argv[])
{ {
// Establece la ruta del programa // Establece la ruta del programa
executable_path_ = argv[0]; executable_path_ = getPath(argv[0]);
// Comprueba el resto de parámetros // Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
@@ -605,8 +613,8 @@ void Director::runDemoGame()
// Ejecuta la sección init // Ejecuta la sección init
void Director::runInit() void Director::runInit()
{ {
Audio::get().stopMusic(); Audio::get()->stopMusic();
Audio::get().stopAllSounds(); Audio::get()->stopAllSounds();
if (section::options == section::Options::RELOAD || true) if (section::options == section::Options::RELOAD || true)
{ {
Resource::get()->reload(); Resource::get()->reload();

View File

@@ -101,7 +101,7 @@ Game::~Game()
// [Modo DEMO] Vuelve a activar los sonidos // [Modo DEMO] Vuelve a activar los sonidos
if (demo_.enabled) if (demo_.enabled)
{ {
Audio::get().enableSound(); Audio::get()->enableSound();
} }
else else
{ {
@@ -109,7 +109,7 @@ Game::~Game()
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table); auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
manager->saveToFile(Asset::get()->get("score.bin")); manager->saveToFile(Asset::get()->get("score.bin"));
section::attract_mode = section::AttractMode::TITLE_TO_DEMO; section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
Audio::get().stopMusic(); Audio::get()->stopMusic();
} }
#ifdef RECORDING #ifdef RECORDING
@@ -201,7 +201,7 @@ void Game::updateHiScore()
if (hi_score_achieved_ == false) if (hi_score_achieved_ == false)
{ {
hi_score_achieved_ = true; hi_score_achieved_ = true;
Audio::get().playSound("hi_score_achieved.wav"); Audio::get()->playSound("hi_score_achieved.wav");
} }
} }
} }
@@ -259,7 +259,7 @@ void Game::updateStage()
// Cambio de fase // Cambio de fase
Stage::power = Stage::get(Stage::number).power_to_complete - Stage::power; Stage::power = Stage::get(Stage::number).power_to_complete - Stage::power;
++Stage::number; ++Stage::number;
Audio::get().playSound("stage_change.wav"); Audio::get()->playSound("stage_change.wav");
balloon_manager_->resetBalloonSpeed(); balloon_manager_->resetBalloonSpeed();
screen_->flash(FLASH_COLOR, 3); screen_->flash(FLASH_COLOR, 3);
screen_->shake(); screen_->shake();
@@ -311,7 +311,7 @@ void Game::updateGameStateGameOver()
if (game_over_counter_ == GAME_OVER_COUNTER_) if (game_over_counter_ == GAME_OVER_COUNTER_)
{ {
createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over")); createMessage({paths_.at(2), paths_.at(3)}, Resource::get()->getTexture("game_text_game_over"));
Audio::get().fadeOutMusic(1000); Audio::get()->fadeOutMusic(1000);
balloon_manager_->setSounds(true); balloon_manager_->setSounds(true);
} }
@@ -328,7 +328,7 @@ void Game::updateGameStateGameOver()
if (options.audio.enabled) if (options.audio.enabled)
{ {
const float VOL = static_cast<float>(64 * (100 - fade_out_->getValue())) / 100.0f; const float VOL = static_cast<float>(64 * (100 - fade_out_->getValue())) / 100.0f;
Audio::get().setSoundVolume(static_cast<int>(VOL)); Audio::get()->setSoundVolume(static_cast<int>(VOL));
} }
} }
@@ -347,8 +347,8 @@ void Game::updateGameStateGameOver()
section::options = section::Options::HI_SCORE_AFTER_PLAYING; section::options = section::Options::HI_SCORE_AFTER_PLAYING;
if (options.audio.enabled) if (options.audio.enabled)
{ {
Audio::get().stopAllSounds(); Audio::get()->stopAllSounds();
Audio::get().setSoundVolume(options.audio.sound.volume); Audio::get()->setSoundVolume(options.audio.sound.volume);
} }
} }
} }
@@ -481,7 +481,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
player->addScore(1000); player->addScore(1000);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(0)); createItemText(x, game_text_textures_.at(0));
Audio::get().playSound("item_pickup.wav"); Audio::get()->playSound("item_pickup.wav");
break; break;
} }
case ItemType::GAVINA: case ItemType::GAVINA:
@@ -489,7 +489,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
player->addScore(2500); player->addScore(2500);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(1)); createItemText(x, game_text_textures_.at(1));
Audio::get().playSound("item_pickup.wav"); Audio::get()->playSound("item_pickup.wav");
break; break;
} }
case ItemType::PACMAR: case ItemType::PACMAR:
@@ -497,7 +497,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
player->addScore(5000); player->addScore(5000);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(2)); createItemText(x, game_text_textures_.at(2));
Audio::get().playSound("item_pickup.wav"); Audio::get()->playSound("item_pickup.wav");
break; break;
} }
case ItemType::DEBIAN: case ItemType::DEBIAN:
@@ -505,7 +505,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
player->addScore(100000); player->addScore(100000);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(6)); createItemText(x, game_text_textures_.at(6));
Audio::get().playSound("debian_pickup.wav"); Audio::get()->playSound("debian_pickup.wav");
break; break;
} }
case ItemType::CLOCK: case ItemType::CLOCK:
@@ -513,7 +513,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
enableTimeStopItem(); enableTimeStopItem();
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(5)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(5)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(5)); createItemText(x, game_text_textures_.at(5));
Audio::get().playSound("item_pickup.wav"); Audio::get()->playSound("item_pickup.wav");
break; break;
} }
case ItemType::COFFEE: case ItemType::COFFEE:
@@ -530,7 +530,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(4)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(4)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(4)); createItemText(x, game_text_textures_.at(4));
} }
Audio::get().playSound("voice_coffee.wav"); Audio::get()->playSound("voice_coffee.wav");
break; break;
} }
case ItemType::COFFEE_MACHINE: case ItemType::COFFEE_MACHINE:
@@ -539,7 +539,7 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
coffee_machine_enabled_ = false; coffee_machine_enabled_ = false;
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(3)->getWidth()) / 2; const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(3)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(3)); createItemText(x, game_text_textures_.at(3));
Audio::get().playSound("voice_power_up.wav"); Audio::get()->playSound("voice_power_up.wav");
break; break;
} }
default: default:
@@ -568,7 +568,7 @@ void Game::checkBulletCollision()
if (tabe_->tryToGetBonus()) if (tabe_->tryToGetBonus())
{ {
createItem(ItemType::DEBIAN, pos.x, pos.y); createItem(ItemType::DEBIAN, pos.x, pos.y);
Audio::get().playSound("debian_drop.wav"); Audio::get()->playSound("debian_drop.wav");
} }
else else
{ {
@@ -576,7 +576,7 @@ void Game::checkBulletCollision()
{ {
createItem(ItemType::COFFEE, pos.x, pos.y); createItem(ItemType::COFFEE, pos.x, pos.y);
} }
Audio::get().playSound("tabe_hit.wav"); Audio::get()->playSound("tabe_hit.wav");
} }
break; break;
} }
@@ -598,7 +598,7 @@ void Game::checkBulletCollision()
if (dropped_item != ItemType::COFFEE_MACHINE) if (dropped_item != ItemType::COFFEE_MACHINE)
{ {
createItem(dropped_item, balloon->getPosX(), balloon->getPosY()); createItem(dropped_item, balloon->getPosX(), balloon->getPosY());
Audio::get().playSound("item_drop.wav"); Audio::get()->playSound("item_drop.wav");
} }
else else
{ {
@@ -620,7 +620,7 @@ void Game::checkBulletCollision()
updateHiScore(); updateHiScore();
// Sonido de explosión // Sonido de explosión
Audio::get().playSound("balloon.wav"); Audio::get()->playSound("balloon.wav");
// Deshabilita la bala // Deshabilita la bala
bullet->disable(); bullet->disable();
@@ -676,7 +676,7 @@ void Game::updateItems()
item->update(); item->update();
if (item->isOnFloor()) if (item->isOnFloor())
{ {
Audio::get().playSound("title.wav"); Audio::get()->playSound("title.wav");
screen_->shake(); screen_->shake();
} }
} }
@@ -903,16 +903,16 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
// Lo pierde // Lo pierde
player->removeExtraHit(); player->removeExtraHit();
throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2)); throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2));
Audio::get().playSound("coffee_out.wav"); Audio::get()->playSound("coffee_out.wav");
screen_->shake(); screen_->shake();
} }
else else
{ {
// Si no tiene cafes, muere // Si no tiene cafes, muere
balloon_manager_->stopAllBalloons(); balloon_manager_->stopAllBalloons();
Audio::get().playSound("player_collision.wav"); Audio::get()->playSound("player_collision.wav");
screen_->shake(); screen_->shake();
Audio::get().playSound("voice_no.wav"); Audio::get()->playSound("voice_no.wav");
player->setPlayingState(PlayerState::DYING); player->setPlayingState(PlayerState::DYING);
if (allPlayersAreNotPlaying()) if (allPlayersAreNotPlaying())
{ {
@@ -932,7 +932,7 @@ void Game::updateTimeStopped()
{ {
if (time_stopped_counter_ % 30 == 0) if (time_stopped_counter_ % 30 == 0)
{ {
Audio::get().playSound("clock.wav"); Audio::get()->playSound("clock.wav");
} }
} }
else else
@@ -940,12 +940,12 @@ void Game::updateTimeStopped()
if (time_stopped_counter_ % 30 == 0) if (time_stopped_counter_ % 30 == 0)
{ {
balloon_manager_->normalColorsToAllBalloons(); balloon_manager_->normalColorsToAllBalloons();
Audio::get().playSound("clock.wav"); Audio::get()->playSound("clock.wav");
} }
else if (time_stopped_counter_ % 30 == 15) else if (time_stopped_counter_ % 30 == 15)
{ {
balloon_manager_->reverseColorsToAllBalloons(); balloon_manager_->reverseColorsToAllBalloons();
Audio::get().playSound("clock.wav"); Audio::get()->playSound("clock.wav");
} }
} }
} }
@@ -1427,7 +1427,7 @@ void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bul
player->setInput(bulletType == BulletType::UP ? InputAction::FIRE_CENTER : bulletType == BulletType::LEFT ? InputAction::FIRE_LEFT player->setInput(bulletType == BulletType::UP ? InputAction::FIRE_CENTER : bulletType == BulletType::LEFT ? InputAction::FIRE_LEFT
: InputAction::FIRE_RIGHT); : InputAction::FIRE_RIGHT);
createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId()); createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId());
Audio::get().playSound("bullet.wav"); Audio::get()->playSound("bullet.wav");
// Establece un tiempo de espera para el próximo disparo. // Establece un tiempo de espera para el próximo disparo.
const int cooldown = player->isPowerUp() ? 5 : options.game.autofire ? 10 const int cooldown = player->isPowerUp() ? 5 : options.game.autofire ? 10
@@ -1629,7 +1629,7 @@ void Game::initDemo(int player_id)
} }
// Deshabilita los sonidos // Deshabilita los sonidos
Audio::get().disableSound(); Audio::get()->disableSound();
// Configura los marcadores // Configura los marcadores
scoreboard_->setMode(SCOREBOARD_LEFT_PANEL, ScoreboardMode::DEMO); scoreboard_->setMode(SCOREBOARD_LEFT_PANEL, ScoreboardMode::DEMO);
@@ -1731,7 +1731,7 @@ void Game::initPlayers(int player_id)
// Hace sonar la música // Hace sonar la música
void Game::playMusic() void Game::playMusic()
{ {
Audio::get().playMusic("playing.ogg"); Audio::get()->playMusic("playing.ogg");
} }
// Detiene la música // Detiene la música
@@ -1739,7 +1739,7 @@ void Game::stopMusic()
{ {
if (!demo_.enabled) if (!demo_.enabled)
{ {
Audio::get().stopMusic(); Audio::get()->stopMusic();
} }
} }
@@ -1823,7 +1823,7 @@ void Game::updateGameStateEnteringPlayer()
{ {
setState(GameState::SHOWING_GET_READY_MESSAGE); setState(GameState::SHOWING_GET_READY_MESSAGE);
createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready")); createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready"));
Audio::get().playSound("voice_get_ready.wav"); Audio::get()->playSound("voice_get_ready.wav");
} }
} }
} }

View File

@@ -123,7 +123,7 @@ void GameLogo::update()
coffee_crisis_status_ = Status::SHAKING; coffee_crisis_status_ = Status::SHAKING;
// Reproduce el efecto sonoro // Reproduce el efecto sonoro
Audio::get().playSound("title.wav"); Audio::get()->playSound("title.wav");
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY); Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
Screen::get()->shake(); Screen::get()->shake();
} }
@@ -187,7 +187,7 @@ void GameLogo::update()
zoom_ = 1.0f; zoom_ = 1.0f;
arcade_edition_sprite_->setZoom(zoom_); arcade_edition_sprite_->setZoom(zoom_);
shake_.init(1, 2, 8, arcade_edition_sprite_->getX()); shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
Audio::get().playSound("title.wav"); Audio::get()->playSound("title.wav");
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY); Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
Screen::get()->shake(); Screen::get()->shake();
} }

View File

@@ -60,7 +60,7 @@ namespace globalInputs
void toggleAudio() void toggleAudio()
{ {
options.audio.enabled = !options.audio.enabled; options.audio.enabled = !options.audio.enabled;
Audio::get().enable(options.audio.enabled); Audio::get()->enable(options.audio.enabled);
Notifier::get()->show({"Audio " + boolToOnOff(options.audio.enabled)}); Notifier::get()->show({"Audio " + boolToOnOff(options.audio.enabled)});
} }
@@ -151,7 +151,7 @@ namespace globalInputs
switch (section::name) switch (section::name)
{ {
case section::Name::INTRO: case section::Name::INTRO:
Audio::get().stopMusic(); Audio::get()->stopMusic();
/* Continua en el case de abajo */ /* Continua en el case de abajo */
case section::Name::LOGO: case section::Name::LOGO:
case section::Name::HI_SCORE_TABLE: case section::Name::HI_SCORE_TABLE:

View File

@@ -150,7 +150,7 @@ void HiScoreTable::checkInput()
// Bucle para la pantalla de instrucciones // Bucle para la pantalla de instrucciones
void HiScoreTable::run() void HiScoreTable::run()
{ {
Audio::get().playMusic("title.ogg"); Audio::get()->playMusic("title.ogg");
while (section::name == section::Name::HI_SCORE_TABLE) while (section::name == section::Name::HI_SCORE_TABLE)
{ {
checkInput(); checkInput();

View File

@@ -8,26 +8,17 @@
#include <unordered_map> // Para unordered_map, operator==, _Node_cons... #include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair #include <utility> // Para pair
// [SINGLETON] // Singleton
Input *Input::input_ = nullptr; Input *Input::instance_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática // Inicializa la instancia única del singleton
void Input::init(const std::string &game_controller_db_path) void Input::init(const std::string &game_controller_db_path) { Input::instance_ = new Input(game_controller_db_path); }
{
Input::input_ = new Input(game_controller_db_path);
}
// [SINGLETON] Destruiremos el objeto con esta función estática // Libera la instancia
void Input::destroy() void Input::destroy() { delete Input::instance_; }
{
delete Input::input_;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // Obtiene la instancia
Input *Input::get() Input *Input::get() { return Input::instance_; }
{
return Input::input_;
}
// Constructor // Constructor
Input::Input(const std::string &game_controller_db_path) Input::Input(const std::string &game_controller_db_path)

View File

@@ -69,66 +69,40 @@ enum class InputDeviceToUse : int
class Input class Input
{ {
public: public:
// [SINGLETON] Crearemos el objeto con esta función estática // --- Métodos de singleton ---
static void init(const std::string &game_controller_db_path); static void init(const std::string &game_controller_db_path); // Inicializa el singleton
static void destroy(); // Libera el singleton
static Input *get(); // Obtiene la instancia
// [SINGLETON] Destruiremos el objeto con esta función estática // --- Métodos de configuración de controles ---
static void destroy(); void bindKey(InputAction input, SDL_Scancode code); // Asigna inputs a teclas
void bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button); // Asigna inputs a botones del mando
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); // Asigna inputs a otros inputs del mando
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // --- Métodos de consulta de entrada ---
static Input *get(); bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); // Comprueba si un input está activo
bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); // Comprueba si hay al menos un input activo
int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); // Comprueba si hay algún botón pulsado
// Asigna inputs a teclas // --- Métodos de gestión de mandos ---
void bindKey(InputAction input, SDL_Scancode code); bool discoverGameControllers(); // Busca si hay mandos conectados
bool gameControllerFound(); // Comprueba si hay algún mando conectado
int getNumControllers() const; // Obtiene el número de mandos conectados
std::string getControllerName(int controller_index) const; // Obtiene el nombre de un mando de juego
int getJoyIndex(SDL_JoystickID id) const; // Obtiene el índice del controlador a partir de un event.id
// Asigna inputs a botones del mando // --- Métodos de consulta y utilidades ---
void bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button); void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const; // Muestra por consola los controles asignados
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); SDL_GamepadButton getControllerBinding(int controller_index, InputAction input) const; // Obtiene el SDL_GamepadButton asignado a un input
std::string to_string(InputAction input) const; // Convierte un InputAction a std::string
// Comprueba si un input está activo InputAction to_inputs_e(const std::string &name) const; // Convierte un std::string a InputAction
bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0); int getIndexByName(const std::string &name) const; // Obtiene el índice a partir del nombre del mando
// Comprueba si hay al menos un input activo
bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay algún botón pulsado
int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT);
// Busca si hay mandos conectados
bool discoverGameControllers();
// Comprueba si hay algún mando conectado
bool gameControllerFound();
// Obtiene el número de mandos conectados
int getNumControllers() const;
// Obtiene el nombre de un mando de juego
std::string getControllerName(int controller_index) const;
// Obtiene el índice del controlador a partir de un event.id
int getJoyIndex(SDL_JoystickID id) const;
// Muestra por consola los controles asignados
void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const;
// Obtiene el SDL_GamepadButton asignado a un input
SDL_GamepadButton getControllerBinding(int controller_index, InputAction input) const;
// Convierte un InputAction a std::string
std::string to_string(InputAction input) const;
// Convierte un std::string a InputAction
InputAction to_inputs_e(const std::string &name) const;
// Obtiene el índice a partir del nombre del mando
int getIndexByName(const std::string &name) const;
private: private:
// [SINGLETON] Objeto privado // --- Singleton ---
static Input *input_; static Input *instance_;
// Estructura para asociar teclas a acciones // --- Estructuras internas ---
struct KeyBindings struct KeyBindings
{ {
Uint8 scancode; // Scancode asociado Uint8 scancode; // Scancode asociado
@@ -138,7 +112,6 @@ private:
: scancode(sc), active(act) {} : scancode(sc), active(act) {}
}; };
// Estructura para asociar botones de mando a acciones
struct ControllerBindings struct ControllerBindings
{ {
SDL_GamepadButton button; // GameControllerButton asociado SDL_GamepadButton button; // GameControllerButton asociado
@@ -149,7 +122,7 @@ private:
: button(btn), active(act), axis_active(axis_act) {} : button(btn), active(act), axis_active(axis_act) {}
}; };
// Variables internas // --- Variables internas ---
std::vector<SDL_Gamepad *> connected_controllers_; // Vector con todos los mandos conectados std::vector<SDL_Gamepad *> connected_controllers_; // Vector con todos los mandos conectados
std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
@@ -160,14 +133,11 @@ private:
int num_gamepads_ = 0; // Número de mandos conectados int num_gamepads_ = 0; // Número de mandos conectados
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
void initSDL(); // Inicializa SDL para la gestión de mandos // --- Métodos internos ---
void initSDL(); // Inicializa SDL para la gestión de mandos
bool checkAxisInput(InputAction input, int controller_index, bool repeat); // Comprueba el eje del mando
// Comprueba el eje del mando // --- Constructor y destructor ---
bool checkAxisInput(InputAction input, int controller_index, bool repeat); explicit Input(const std::string &game_controller_db_path); // Constructor privado
~Input() = default; // Destructor privado
// Constructor privado
explicit Input(const std::string &game_controller_db_path);
// Destructor
~Input() = default;
}; };

View File

@@ -272,7 +272,7 @@ void Instructions::checkInput()
// Bucle para la pantalla de instrucciones // Bucle para la pantalla de instrucciones
void Instructions::run() void Instructions::run()
{ {
Audio::get().playMusic("title.ogg"); Audio::get()->playMusic("title.ogg");
while (section::name == section::Name::INSTRUCTIONS) while (section::name == section::Name::INSTRUCTIONS)
{ {
checkInput(); checkInput();

View File

@@ -281,7 +281,7 @@ void Intro::render()
// Bucle principal // Bucle principal
void Intro::run() void Intro::run()
{ {
Audio::get().playMusic("intro.ogg", 0); Audio::get()->playMusic("intro.ogg", 0);
while (section::name == section::Name::INTRO) while (section::name == section::Name::INTRO)
{ {
checkInput(); checkInput();
@@ -513,7 +513,7 @@ void Intro::updatePostState()
// Finaliza la intro después de 1 segundo // Finaliza la intro después de 1 segundo
if (ELAPSED_TIME >= 1000) if (ELAPSED_TIME >= 1000)
{ {
Audio::get().stopMusic(); Audio::get()->stopMusic();
section::name = section::Name::TITLE; section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1; section::options = section::Options::TITLE_1;
} }

View File

@@ -60,7 +60,7 @@ Logo::~Logo()
{ {
jail_texture_->setColor(255, 255, 255); jail_texture_->setColor(255, 255, 255);
since_texture_->setColor(255, 255, 255); since_texture_->setColor(255, 255, 255);
Audio::get().stopAllSounds(); Audio::get()->stopAllSounds();
} }
// Comprueba el manejador de eventos // Comprueba el manejador de eventos
@@ -84,7 +84,7 @@ void Logo::updateJAILGAMES()
{ {
if (counter_ == 30) if (counter_ == 30)
{ {
Audio::get().playSound("logo.wav"); Audio::get()->playSound("logo.wav");
} }
if (counter_ > 30) if (counter_ > 30)
@@ -181,7 +181,7 @@ void Logo::render()
// Bucle para el logo del juego // Bucle para el logo del juego
void Logo::run() void Logo::run()
{ {
Audio::get().fadeOutMusic(300); Audio::get()->fadeOutMusic(300);
while (section::name == section::Name::LOGO) while (section::name == section::Name::LOGO)
{ {
checkInput(); checkInput();

View File

@@ -12,26 +12,17 @@
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "resource.h" #include "resource.h"
// [SINGLETON] // Singleton
Notifier *Notifier::notifier_ = nullptr; Notifier *Notifier::instance_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática // Inicializa la instancia única del singleton
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text) void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text) { Notifier::instance_ = new Notifier(icon_file, text); }
{
Notifier::notifier_ = new Notifier(icon_file, text);
}
// [SINGLETON] Destruiremos el objeto con esta función estática // Libera la instancia
void Notifier::destroy() void Notifier::destroy() { delete Notifier::instance_; }
{
delete Notifier::notifier_;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // Obtiene la instancia
Notifier *Notifier::get() Notifier *Notifier::get() { return Notifier::instance_; }
{
return Notifier::notifier_;
}
// Constructor // Constructor
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text) Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text)
@@ -76,7 +67,7 @@ void Notifier::update()
if (notifications_[i].state == NotificationStatus::RISING) if (notifications_[i].state == NotificationStatus::RISING)
{ {
// Reproduce el sonido de la notificación // Reproduce el sonido de la notificación
Audio::get().playSound("notify.wav"); Audio::get()->playSound("notify.wav");
} }
} }
} }

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include <SDL3/SDL_rect.h> // Para SDL_FRect #include <SDL3/SDL_rect.h> // Para SDL_FRect
#include <SDL3/SDL_render.h> // Para SDL_Renderer #include <SDL3/SDL_render.h> // Para SDL_Renderer
#include <memory> // Para shared_ptr #include <memory> // Para shared_ptr
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
#include "utils.h" // Para Color #include "utils.h" // Para Color
class Sprite; class Sprite;
class Text; class Text;
@@ -15,89 +15,77 @@ class Texture;
class Notifier class Notifier
{ {
public: public:
// [SINGLETON] Crearemos el objeto con esta función estática // --- Métodos de singleton ---
static void init(const std::string &icon_file, std::shared_ptr<Text> text); static void init(const std::string &icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
static void destroy(); // Libera el singleton
static Notifier *get(); // Obtiene la instancia
// [SINGLETON] Destruiremos el objeto con esta función estática // --- Métodos principales ---
static void destroy(); void render(); // Dibuja las notificaciones por pantalla
void update(); // Actualiza el estado de las notificaciones
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // --- Gestión de notificaciones ---
static Notifier *get(); void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla
bool isActive() const { return !notifications_.empty(); } // Indica si hay notificaciones activas
// Dibuja las notificaciones por pantalla std::vector<std::string> getCodes(); // Obtiene los códigos de las notificaciones activas
void render(); bool checkCode(const std::string &code) { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
// Actualiza el estado de las notificaciones
void update();
// Muestra una notificación de texto por pantalla
void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());
// Indica si hay notificaciones activas
bool isActive() const { return !notifications_.empty(); }
// Obtiene los códigos de las notificaciones activas
std::vector<std::string> getCodes();
// Comprueba si hay alguna notificación con un código concreto
bool checkCode(const std::string &code) { return stringInVector(getCodes(), code); }
private: private:
// [SINGLETON] Objeto notifier // --- Singleton ---
static Notifier *notifier_; static Notifier *instance_;
// --- Tipos internos --- // --- Tipos internos ---
enum class NotificationStatus enum class NotificationStatus
{ {
RISING, RISING,
STAY, STAY,
VANISHING, VANISHING,
FINISHED, FINISHED,
}; };
enum class NotificationShape enum class NotificationShape
{ {
ROUNDED, ROUNDED,
SQUARED, SQUARED,
}; };
// --- Estructura Notification --- // --- Estructura Notification ---
struct Notification struct Notification
{ {
std::shared_ptr<Texture> texture; // Textura de la notificación std::shared_ptr<Texture> texture; // Textura de la notificación
std::shared_ptr<Sprite> sprite; // Sprite asociado std::shared_ptr<Sprite> sprite; // Sprite asociado
std::vector<std::string> texts; // Textos a mostrar std::vector<std::string> texts; // Textos a mostrar
int counter; // Contador de tiempo int counter; // Contador de tiempo
NotificationStatus state; // Estado de la notificación NotificationStatus state; // Estado de la notificación
NotificationShape shape; // Forma de la notificación NotificationShape shape; // Forma de la notificación
SDL_FRect rect; // Rectángulo de la notificación SDL_FRect rect; // Rectángulo de la notificación
int y; // Posición vertical int y; // Posición vertical
int travel_dist; // Distancia a recorrer int travel_dist; // Distancia a recorrer
std::string code; // Código identificador de la notificación std::string code; // Código identificador de la notificación
// Constructor // Constructor
explicit Notification() explicit Notification()
: texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING), : texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING),
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {} shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
}; };
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Renderer *renderer_; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
std::shared_ptr<Text> text_; // Objeto para dibujar texto std::shared_ptr<Text> text_; // Objeto para dibujar texto
// --- Variables de estado --- // --- Variables de estado ---
Color bg_color_; // Color de fondo de las notificaciones Color bg_color_; // Color de fondo de las notificaciones
int wait_time_; // Tiempo que se ve la notificación int wait_time_; // Tiempo que se ve la notificación
std::vector<Notification> notifications_; // Lista de notificaciones activas std::vector<Notification> notifications_; // Lista de notificaciones activas
bool stack_; // Indica si las notificaciones se apilan bool stack_; // Indica si las notificaciones se apilan
bool has_icons_; // Indica si el notificador tiene textura para iconos bool has_icons_; // Indica si el notificador tiene textura para iconos
// --- Métodos internos --- // --- Métodos internos ---
void clearFinishedNotifications(); // Elimina las notificaciones finalizadas void clearFinishedNotifications(); // Elimina las notificaciones finalizadas
void clearAllNotifications(); // Finaliza y elimina todas las notificaciones activas void clearAllNotifications(); // Finaliza y elimina todas las notificaciones activas
// [SINGLETON] Constructor y destructor privados // --- Constructor y destructor ---
Notifier(std::string icon_file, std::shared_ptr<Text> text); Notifier(std::string icon_file, std::shared_ptr<Text> text); // Constructor privado
~Notifier() = default; ~Notifier() = default; // Destructor privado
}; };

View File

@@ -221,7 +221,7 @@ void Player::move()
++step_counter_; ++step_counter_;
if (step_counter_ % 10 == 0) if (step_counter_ % 10 == 0)
{ {
Audio::get().playSound("walk.wav"); Audio::get()->playSound("walk.wav");
} }
switch (id_) switch (id_)
@@ -252,7 +252,7 @@ void Player::move()
++step_counter_; ++step_counter_;
if (step_counter_ % 10 == 0) if (step_counter_ % 10 == 0)
{ {
Audio::get().playSound("walk.wav"); Audio::get()->playSound("walk.wav");
} }
switch (id_) switch (id_)
@@ -752,7 +752,7 @@ void Player::decContinueCounter()
} }
else else
{ {
Audio::get().playSound("continue_clock.wav"); Audio::get()->playSound("continue_clock.wav");
} }
} }
@@ -798,5 +798,5 @@ void Player::shiftSprite()
void Player::playRandomBubbleSound() void Player::playRandomBubbleSound()
{ {
const std::vector<std::string> sounds = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"}; const std::vector<std::string> sounds = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
Audio::get().playSound(sounds.at(rand() % sounds.size())); Audio::get()->playSound(sounds.at(rand() % sounds.size()));
} }

View File

@@ -10,32 +10,20 @@
struct JA_Music_t; // lines 11-11 struct JA_Music_t; // lines 11-11
struct JA_Sound_t; // lines 12-12 struct JA_Sound_t; // lines 12-12
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // Singleton
Resource *Resource::resource_ = nullptr; Resource *Resource::instance_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática // Inicializa la instancia única del singleton
void Resource::init() void Resource::init() { Resource::instance_ = new Resource(); }
{
Resource::resource_ = new Resource();
}
// [SINGLETON] Destruiremos el objeto screen con esta función estática // Libera la instancia
void Resource::destroy() void Resource::destroy() { delete Resource::instance_; }
{
delete Resource::resource_;
}
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él // Obtiene la instancia
Resource *Resource::get() Resource *Resource::get() { return Resource::instance_; }
{
return Resource::resource_;
}
// Constructor // Constructor
Resource::Resource() Resource::Resource() { load(); }
{
load();
}
// Vacia todos los vectores de recursos // Vacia todos los vectores de recursos
void Resource::clear() void Resource::clear()

View File

@@ -97,7 +97,7 @@ public:
private: private:
// --- Singleton --- // --- Singleton ---
static Resource *resource_; static Resource *instance_;
// --- Vectores de recursos --- // --- Vectores de recursos ---
std::vector<ResourceSound> sounds_; // Vector con los sonidos std::vector<ResourceSound> sounds_; // Vector con los sonidos

View File

@@ -20,17 +20,17 @@
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "text.h" // Para Text #include "text.h" // Para Text
// [SINGLETON] // Singleton
Screen *Screen::screen_ = nullptr; Screen *Screen::instance_ = nullptr;
// [SINGLETON] Crearemos el objeto con esta función estática // Inicializa la instancia única del singleton
void Screen::init() { Screen::screen_ = new Screen(); } void Screen::init() { Screen::instance_ = new Screen(); }
// [SINGLETON] Destruiremos el objeto con esta función estática // Libera la instancia
void Screen::destroy() { delete Screen::screen_; } void Screen::destroy() { delete Screen::instance_; }
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él // Obtiene la instancia
Screen *Screen::get() { return Screen::screen_; } Screen *Screen::get() { return Screen::instance_; }
// Constructor // Constructor
Screen::Screen() Screen::Screen()

View File

@@ -178,7 +178,7 @@ private:
#endif #endif
// --- Singleton --- // --- Singleton ---
static Screen *screen_; static Screen *instance_;
// --- Objetos y punteros --- // --- Objetos y punteros ---
SDL_Window *window_; // Ventana de la aplicación SDL_Window *window_; // Ventana de la aplicación

View File

@@ -1,6 +1,19 @@
#include "service_menu.h" #include "service_menu.h"
#include <iostream> #include <iostream>
// Singleton
ServiceMenu *ServiceMenu::instance_ = nullptr;
// Inicializa la instancia única del singleton
void ServiceMenu::init() { ServiceMenu::instance_ = new ServiceMenu(); }
// Libera la instancia
void ServiceMenu::destroy() { delete ServiceMenu::instance_; }
// Obtiene la instancia
ServiceMenu *ServiceMenu::get() { return ServiceMenu::instance_; }
// Constructor
ServiceMenu::ServiceMenu() { ServiceMenu::ServiceMenu() {
// Inicializa los valores por defecto del menú de servicio // Inicializa los valores por defecto del menú de servicio
is_active = false; is_active = false;

View File

@@ -6,15 +6,10 @@
class ServiceMenu class ServiceMenu
{ {
public: public:
static ServiceMenu &get_instance() // --- Métodos de singleton ---
{ static void init(); // Inicializa el objeto ServiceMenu
static ServiceMenu instance; static void destroy(); // Libera el objeto ServiceMenu
return instance; static ServiceMenu *get(); // Obtiene el puntero al objeto ServiceMenu
}
// Eliminar copia y asignación
ServiceMenu(const ServiceMenu &) = delete;
ServiceMenu &operator=(const ServiceMenu &) = delete;
void show(); void show();
void render(); void render();
@@ -22,9 +17,16 @@ public:
void execute_option(size_t option); void execute_option(size_t option);
private: private:
ServiceMenu(); // --- Patrón Singleton ---
~ServiceMenu() = default; ServiceMenu(); // Constructor privado
~ServiceMenu() = default; // Destructor privado
ServiceMenu(const ServiceMenu &) = delete; // Evitar copia
ServiceMenu &operator=(const ServiceMenu &) = delete; // Evitar asignación
// --- Singleton ---
static ServiceMenu *instance_;
// -- Variables internas ---
bool is_active; bool is_active;
size_t selected_option; size_t selected_option;
std::vector<std::string> options; std::vector<std::string> options;

View File

@@ -131,7 +131,7 @@ void Tabe::setRandomFlyPath(TabeDirection direction, int lenght)
direction_ = direction; direction_ = direction;
fly_distance_ = lenght; fly_distance_ = lenght;
waiting_counter_ = 5 + rand() % 15; waiting_counter_ = 5 + rand() % 15;
Audio::get().playSound("tabe.wav"); Audio::get()->playSound("tabe.wav");
constexpr float SPEED = 2.0f; constexpr float SPEED = 2.0f;

View File

@@ -55,7 +55,7 @@ Title::Title()
Title::~Title() Title::~Title()
{ {
Resource::get()->getTexture("smb2.gif")->setPalette(0); Resource::get()->getTexture("smb2.gif")->setPalette(0);
Audio::get().stopAllSounds(); Audio::get()->stopAllSounds();
} }
// Actualiza las variables del objeto // Actualiza las variables del objeto
@@ -200,8 +200,8 @@ void Title::checkInput()
{ {
if ((state_ == TitleState::LOGO_FINISHED || ALLOW_TITLE_ANIMATION_SKIP) && !fade_->isEnabled()) if ((state_ == TitleState::LOGO_FINISHED || ALLOW_TITLE_ANIMATION_SKIP) && !fade_->isEnabled())
{ {
Audio::get().playSound("game_start.wav"); Audio::get()->playSound("game_start.wav");
Audio::get().fadeOutMusic(1500); Audio::get()->fadeOutMusic(1500);
switch (CONTROLLER.player_id) switch (CONTROLLER.player_id)
{ {
case 1: case 1:
@@ -322,7 +322,7 @@ void Title::updateFade()
// Se ha pulsado para jugar // Se ha pulsado para jugar
section::name = section::Name::GAME; section::name = section::Name::GAME;
section::options = selection_; section::options = selection_;
Audio::get().stopMusic(); Audio::get()->stopMusic();
} }
} }
} }
@@ -339,7 +339,7 @@ void Title::updateState()
if (game_logo_->hasFinished()) if (game_logo_->hasFinished())
{ {
state_ = TitleState::LOGO_FINISHED; state_ = TitleState::LOGO_FINISHED;
Audio::get().playMusic("title.ogg"); Audio::get()->playMusic("title.ogg");
} }
break; break;
} }