diff --git a/.clang-format b/.clang-format index 67c3d30..58bffd5 100644 --- a/.clang-format +++ b/.clang-format @@ -14,6 +14,8 @@ ContinuationIndentWidth: 4 ConstructorInitializerIndentWidth: 4 IndentWrappedFunctionNames: false Cpp11BracedListStyle: true -BreakConstructorInitializers: BeforeComma +BreakConstructorInitializers: BeforeColon +AllowAllConstructorInitializersOnNextLine: false +PackConstructorInitializers: Never AllowAllArgumentsOnNextLine: false AllowAllParametersOfDeclarationOnNextLine: false diff --git a/source/animated_sprite.cpp b/source/animated_sprite.cpp index 92adf3b..8e9fb06 100644 --- a/source/animated_sprite.cpp +++ b/source/animated_sprite.cpp @@ -9,9 +9,9 @@ #include // Para runtime_error #include // Para pair -#include "texture.h" // Para Texture #include "resource_helper.h" // Para ResourceHelper -#include "utils.h" // Para printWithDots +#include "texture.h" // Para Texture +#include "utils.h" // Para printWithDots // Carga las animaciones en un vector(Animations) desde un fichero auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffer { @@ -19,13 +19,13 @@ auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffe auto resource_data = ResourceHelper::loadFile(file_path); std::istringstream stream; bool using_resource_data = false; - + if (!resource_data.empty()) { std::string content(resource_data.begin(), resource_data.end()); stream.str(content); using_resource_data = true; } - + // Fallback a archivo directo std::ifstream file; if (!using_resource_data) { @@ -35,7 +35,7 @@ auto loadAnimationsFromFile(const std::string& file_path) -> AnimationsFileBuffe throw std::runtime_error("Fichero no encontrado: " + file_path); } } - + std::istream& input_stream = using_resource_data ? stream : static_cast(file); printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]"); diff --git a/source/animated_sprite.h b/source/animated_sprite.h index 232987a..3adcd21 100644 --- a/source/animated_sprite.h +++ b/source/animated_sprite.h @@ -50,7 +50,8 @@ class AnimatedSprite : public MovingSprite { // --- Constructores y destructor --- AnimatedSprite(std::shared_ptr texture, const std::string& file_path); AnimatedSprite(std::shared_ptr texture, const AnimationsFileBuffer& animations); - explicit AnimatedSprite(std::shared_ptr texture) : MovingSprite(std::move(texture)) {} + explicit AnimatedSprite(std::shared_ptr texture) + : MovingSprite(std::move(texture)) {} ~AnimatedSprite() override = default; // --- Métodos principales --- diff --git a/source/asset.cpp b/source/asset.cpp index b53b8e0..9295c70 100644 --- a/source/asset.cpp +++ b/source/asset.cpp @@ -8,8 +8,8 @@ #include // Para basic_istringstream #include // Para runtime_error -#include "utils.h" // Para getFileName #include "resource_helper.h" // Para ResourceHelper +#include "utils.h" // Para getFileName // Singleton Asset *Asset::instance = nullptr; @@ -209,7 +209,7 @@ auto Asset::checkFile(const std::string &path) -> bool { // Intentar primero con ResourceHelper auto data = ResourceHelper::loadFile(path); bool success = !data.empty(); - + // Si no se encuentra en el pack, intentar con filesystem directo if (!success) { std::ifstream file(path); diff --git a/source/asset.h b/source/asset.h index 2237b38..dcc4b76 100644 --- a/source/asset.h +++ b/source/asset.h @@ -1,10 +1,10 @@ #pragma once +#include // Para uint8_t #include // Para string #include // Para unordered_map #include // Para move #include // Para vector -#include // Para uint8_t // --- Clase Asset: gestor optimizado de recursos (singleton) --- class Asset { @@ -34,7 +34,7 @@ class Asset { void add(const std::string &file_path, Type type, bool required = true, bool absolute = false); void loadFromFile(const std::string &config_file_path, const std::string &prefix = "", const std::string &system_folder = ""); // Con soporte para variables [[nodiscard]] auto get(const std::string &filename) const -> std::string; // Mantener nombre original - [[nodiscard]] auto loadData(const std::string &filename) const -> std::vector; // Carga datos del archivo + [[nodiscard]] auto loadData(const std::string &filename) const -> std::vector; // Carga datos del archivo [[nodiscard]] auto check() const -> bool; [[nodiscard]] auto getListByType(Type type) const -> std::vector; [[nodiscard]] auto exists(const std::string &filename) const -> bool; // Nueva función para verificar existencia @@ -47,7 +47,9 @@ class Asset { bool required; // Indica si el archivo es obligatorio Item(std::string path, Type asset_type, bool is_required) - : file(std::move(path)), type(asset_type), required(is_required) {} + : file(std::move(path)), + type(asset_type), + required(is_required) {} }; // --- Variables internas --- diff --git a/source/asset_integrated.cpp b/source/asset_integrated.cpp index 66cb85d..a657253 100644 --- a/source/asset_integrated.cpp +++ b/source/asset_integrated.cpp @@ -1,17 +1,18 @@ #include "asset_integrated.h" + #include -#include #include +#include bool AssetIntegrated::resource_pack_enabled_ = false; -void AssetIntegrated::initWithResourcePack(const std::string &executable_path, - const std::string &resource_pack_path) { +void AssetIntegrated::initWithResourcePack(const std::string &executable_path, + const std::string &resource_pack_path) { // Inicializar Asset normal Asset::init(executable_path); - + // Inicializar ResourceLoader - auto& loader = ResourceLoader::getInstance(); + auto &loader = ResourceLoader::getInstance(); if (loader.initialize(resource_pack_path, true)) { resource_pack_enabled_ = true; std::cout << "Asset system initialized with resource pack: " << resource_pack_path << std::endl; @@ -24,58 +25,58 @@ void AssetIntegrated::initWithResourcePack(const std::string &executable_path, std::vector AssetIntegrated::loadFile(const std::string &filename) { if (shouldUseResourcePack(filename) && resource_pack_enabled_) { // Intentar cargar del pack de recursos - auto& loader = ResourceLoader::getInstance(); - + auto &loader = ResourceLoader::getInstance(); + // Convertir ruta completa a ruta relativa para el pack std::string relativePath = filename; - + // Si la ruta contiene "data/", extraer la parte relativa size_t dataPos = filename.find("data/"); if (dataPos != std::string::npos) { - relativePath = filename.substr(dataPos + 5); // +5 para saltar "data/" + relativePath = filename.substr(dataPos + 5); // +5 para saltar "data/" } - + auto data = loader.loadResource(relativePath); if (!data.empty()) { return data; } } - + // Fallback: cargar del filesystem std::ifstream file(filename, std::ios::binary | std::ios::ate); if (!file) { std::cerr << "Error: Could not open file: " << filename << std::endl; return {}; } - + std::streamsize fileSize = file.tellg(); file.seekg(0, std::ios::beg); - + std::vector data(fileSize); - if (!file.read(reinterpret_cast(data.data()), fileSize)) { + if (!file.read(reinterpret_cast(data.data()), fileSize)) { std::cerr << "Error: Could not read file: " << filename << std::endl; return {}; } - + return data; } bool AssetIntegrated::fileExists(const std::string &filename) const { if (shouldUseResourcePack(filename) && resource_pack_enabled_) { - auto& loader = ResourceLoader::getInstance(); - + auto &loader = ResourceLoader::getInstance(); + // Convertir ruta completa a ruta relativa para el pack std::string relativePath = filename; size_t dataPos = filename.find("data/"); if (dataPos != std::string::npos) { relativePath = filename.substr(dataPos + 5); } - + if (loader.resourceExists(relativePath)) { return true; } } - + // Verificar en filesystem return std::filesystem::exists(filename); } @@ -90,16 +91,16 @@ bool AssetIntegrated::shouldUseResourcePack(const std::string &filepath) const { // - Archivos de config/ (ahora están fuera de data/) // - Archivos con absolute=true en assets.txt // - Archivos de sistema (${SYSTEM_FOLDER}) - - if (filepath.find("/config/") != std::string::npos || + + if (filepath.find("/config/") != std::string::npos || filepath.find("config/") == 0) { return false; } - + if (filepath.find("/data/") != std::string::npos || filepath.find("data/") == 0) { return true; } - + return false; } \ No newline at end of file diff --git a/source/asset_integrated.h b/source/asset_integrated.h index 2c9afe6..9a85213 100644 --- a/source/asset_integrated.h +++ b/source/asset_integrated.h @@ -1,28 +1,29 @@ #pragma once +#include + #include "asset.h" #include "resource_loader.h" -#include // Extensión de Asset que integra ResourceLoader class AssetIntegrated : public Asset { -public: - // Inicializa Asset con ResourceLoader - static void initWithResourcePack(const std::string &executable_path, - const std::string &resource_pack_path = "resources.pack"); - - // Carga un archivo usando ResourceLoader como primera opción - std::vector loadFile(const std::string &filename); - - // Verifica si un archivo existe (pack o filesystem) - bool fileExists(const std::string &filename) const; - - // Obtiene la ruta completa para archivos del sistema/config - std::string getSystemPath(const std::string &filename) const; - -private: - static bool resource_pack_enabled_; - - // Determina si un archivo debe cargarse del pack o del filesystem - bool shouldUseResourcePack(const std::string &filepath) const; + public: + // Inicializa Asset con ResourceLoader + static void initWithResourcePack(const std::string &executable_path, + const std::string &resource_pack_path = "resources.pack"); + + // Carga un archivo usando ResourceLoader como primera opción + std::vector loadFile(const std::string &filename); + + // Verifica si un archivo existe (pack o filesystem) + bool fileExists(const std::string &filename) const; + + // Obtiene la ruta completa para archivos del sistema/config + std::string getSystemPath(const std::string &filename) const; + + private: + static bool resource_pack_enabled_; + + // Determina si un archivo debe cargarse del pack o del filesystem + bool shouldUseResourcePack(const std::string &filepath) const; }; \ No newline at end of file diff --git a/source/audio.h b/source/audio.h index f1ab276..213ef16 100644 --- a/source/audio.h +++ b/source/audio.h @@ -75,11 +75,15 @@ class Audio { bool loop; // Indica si la última pista de música se debe reproducir en bucle // Constructor para inicializar la música con valores predeterminados - Music() : state(MusicState::STOPPED), loop(false) {} + Music() + : state(MusicState::STOPPED), + loop(false) {} // Constructor para inicializar con valores específicos Music(MusicState init_state, std::string init_name, bool init_loop) - : state(init_state), name(std::move(init_name)), loop(init_loop) {} + : state(init_state), + name(std::move(init_name)), + loop(init_loop) {} }; // --- Variables de estado --- diff --git a/source/balloon.cpp b/source/balloon.cpp index 32c6c7e..e982ba1 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -11,20 +11,21 @@ #include "texture.h" // Para Texture // Constructor -Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, const std::shared_ptr &texture, const std::vector &animation) - : sprite_(std::make_unique(texture, animation)), - x_(x), - y_(y), - vx_(vel_x), - being_created_(creation_timer > 0), - invulnerable_(creation_timer > 0), - stopped_(creation_timer > 0), - creation_counter_(creation_timer), - creation_counter_ini_(creation_timer), - type_(type), - size_(size), - speed_(speed), - play_area_(play_area) { +Balloon::Balloon(const Config& config) + : sprite_(std::make_unique(config.texture, config.animation)), + x_(config.x), + y_(config.y), + vx_(config.vel_x), + being_created_(config.creation_counter > 0), + invulnerable_(config.creation_counter > 0), + stopped_(config.creation_counter > 0), + creation_counter_(config.creation_counter), + creation_counter_ini_(config.creation_counter), + type_(config.type), + size_(config.size), + speed_(config.speed), + play_area_(config.play_area), + sound_(config.sound) { switch (type_) { case Type::BALLOON: { vy_ = 0; @@ -37,9 +38,8 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee power_ = POWER.at(INDEX); menace_ = MENACE.at(INDEX); score_ = SCORE.at(INDEX); - bouncing_sound_ = BOUNCING_SOUND.at(INDEX); - popping_sound_ = POPPING_SOUND.at(INDEX); - + sound_.bouncing_file = BOUNCING_SOUND.at(INDEX); + sound_.popping_file = POPPING_SOUND.at(INDEX); break; } @@ -52,17 +52,16 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee power_ = POWER.at(INDEX); menace_ = MENACE.at(INDEX); score_ = SCORE.at(INDEX); - bouncing_sound_ = BOUNCING_SOUND.at(INDEX); - popping_sound_ = POPPING_SOUND.at(INDEX); - + sound_.bouncing_file = BOUNCING_SOUND.at(INDEX); + sound_.popping_file = POPPING_SOUND.at(INDEX); break; } case Type::POWERBALL: { constexpr int INDEX = 3; h_ = w_ = WIDTH.at(4); - bouncing_sound_ = BOUNCING_SOUND.at(3); - popping_sound_ = "power_ball_explosion.wav"; + sound_.bouncing_file = BOUNCING_SOUND.at(3); + sound_.popping_file = "power_ball_explosion.wav"; power_ = score_ = menace_ = 0; vy_ = 0; @@ -70,9 +69,8 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee gravity_ = param.balloon.settings.at(INDEX).grav; default_vy_ = param.balloon.settings.at(INDEX).vel; - sprite_->setRotate(creation_timer <= 0); + sprite_->setRotate(config.creation_counter <= 0); sprite_->setRotateAmount(vx_ > 0.0F ? 2.0 : -2.0); - break; } @@ -233,8 +231,14 @@ void Balloon::applyGravity() { } void Balloon::playBouncingSound() { - if (bouncing_sound_enabled_) { - playSound(bouncing_sound_); + if (sound_.enabled && sound_.bouncing_enabled) { + Audio::get()->playSound(sound_.bouncing_file); + } +} + +void Balloon::playPoppingSound() { + if (sound_.enabled && sound_.poping_enabled) { + Audio::get()->playSound(sound_.popping_file); } } @@ -368,23 +372,8 @@ void Balloon::useNormalColor() { setAnimation(); } -// Reproduce sonido -void Balloon::playSound(const std::string &name) const { - if (!sound_enabled_) { - return; - } - - static auto *audio_ = Audio::get(); - audio_->playSound(name); -} - // Explota el globo void Balloon::pop(bool should_sound) { - if (should_sound) { - if (poping_sound_enabled_) { - playSound(popping_sound_); - } - } - + if (should_sound) { playPoppingSound(); } enabled_ = false; } \ No newline at end of file diff --git a/source/balloon.h b/source/balloon.h index d190fa9..96af872 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -25,10 +25,16 @@ class Balloon { static constexpr std::array WIDTH = {10, 16, 26, 48, 49}; static constexpr std::array BOUNCING_SOUND = { - "balloon_bounce0.wav", "balloon_bounce1.wav", "balloon_bounce2.wav", "balloon_bounce3.wav"}; + "balloon_bounce0.wav", + "balloon_bounce1.wav", + "balloon_bounce2.wav", + "balloon_bounce3.wav"}; static constexpr std::array POPPING_SOUND = { - "balloon_pop0.wav", "balloon_pop1.wav", "balloon_pop2.wav", "balloon_pop3.wav"}; + "balloon_pop0.wav", + "balloon_pop1.wav", + "balloon_pop2.wav", + "balloon_pop3.wav"}; static constexpr float VELX_POSITIVE = 0.7F; static constexpr float VELX_NEGATIVE = -0.7F; @@ -52,18 +58,32 @@ class Balloon { POWERBALL = 2, // Globo de poder }; + // --- Estructura para manejo de sonido --- + struct Sound { + std::string bouncing_file; // Archivo de sonido al rebotar + std::string popping_file; // Archivo de sonido al explotar + bool bouncing_enabled = false; // Si debe sonar el globo al rebotar + bool poping_enabled = true; // Si debe sonar el globo al explotar + bool enabled = true; // Indica si los globos deben hacer algun sonido + }; + + // --- Estructura de configuración para inicialización --- + struct Config { + float x = 0.0F; + float y = 0.0F; + Type type = Type::BALLOON; + Size size = Size::EXTRALARGE; + float vel_x = VELX_POSITIVE; + float speed = SPEED.at(0); + Uint16 creation_counter = 0; + SDL_FRect play_area = {.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F}; + std::shared_ptr texture = nullptr; + std::vector animation; + Sound sound; + }; + // --- Constructores y destructor --- - Balloon( - float x, - float y, - Type type, - Size size, - float vel_x, - float speed, - Uint16 creation_timer, - SDL_FRect play_area, - const std::shared_ptr& texture, - const std::vector& animation); + Balloon(const Config& config); ~Balloon() = default; // --- Métodos principales --- @@ -102,9 +122,9 @@ class Balloon { void setVelY(float vel_y) { vy_ = vel_y; } void setSpeed(float speed) { speed_ = speed; } void setInvulnerable(bool value) { invulnerable_ = value; } - void setBouncingSound(bool value) { bouncing_sound_enabled_ = value; } - void setPoppingSound(bool value) { poping_sound_enabled_ = value; } - void setSound(bool value) { sound_enabled_ = value; } + void setBouncingSound(bool value) { sound_.bouncing_enabled = value; } + void setPoppingSound(bool value) { sound_.poping_enabled = value; } + void setSound(bool value) { sound_.enabled = value; } private: // --- Estructura para el efecto de rebote --- @@ -114,10 +134,28 @@ class Balloon { // Tablas de valores predefinidos para el efecto de rebote static constexpr std::array HORIZONTAL_ZOOM_VALUES = { - 1.10F, 1.05F, 1.00F, 0.95F, 0.90F, 0.95F, 1.00F, 1.02F, 1.05F, 1.02F}; + 1.10F, + 1.05F, + 1.00F, + 0.95F, + 0.90F, + 0.95F, + 1.00F, + 1.02F, + 1.05F, + 1.02F}; static constexpr std::array VERTICAL_ZOOM_VALUES = { - 0.90F, 0.95F, 1.00F, 1.05F, 1.10F, 1.05F, 1.00F, 0.98F, 0.95F, 0.98F}; + 0.90F, + 0.95F, + 1.00F, + 1.05F, + 1.10F, + 1.05F, + 1.00F, + 0.98F, + 0.95F, + 0.98F}; // Estado del efecto bool enabled_ = false; // Si el efecto está activo @@ -203,47 +241,43 @@ class Balloon { std::unique_ptr sprite_; // Sprite del objeto globo // --- Variables de estado y físicas --- - float x_; // Posición X - float y_; // Posición Y - float w_; // Ancho - float h_; // Alto - float vx_; // Velocidad X - float vy_; // Velocidad Y - float gravity_; // Aceleración en Y - float default_vy_; // Velocidad inicial al rebotar - float max_vy_; // Máxima velocidad en Y - bool being_created_; // Si el globo se está creando - bool enabled_ = true; // Si el globo está activo - bool invulnerable_; // Si el globo es invulnerable - bool stopped_; // Si el globo está parado - bool use_reversed_colors_ = false; // Si se usa el color alternativo - Circle collider_; // Círculo de colisión - Uint16 creation_counter_; // Temporizador de creación - Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación - Uint16 score_; // Puntos al destruir el globo - Type type_; // Tipo de globo - Size size_; // Tamaño de globo - Uint8 menace_; // Amenaza que genera el globo - Uint32 counter_ = 0; // Contador interno - float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad - float speed_; // Velocidad del globo - Uint8 power_; // Poder que alberga el globo - SDL_FRect play_area_; // Zona de movimiento del globo - std::string bouncing_sound_; // Archivo de sonido al rebotar - std::string popping_sound_; // Archivo de sonido al explotar - bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar - bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar - bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido - BounceEffect bounce_effect_; // Efecto de rebote + float x_; // Posición X + float y_; // Posición Y + float w_; // Ancho + float h_; // Alto + float vx_; // Velocidad X + float vy_; // Velocidad Y + float gravity_; // Aceleración en Y + float default_vy_; // Velocidad inicial al rebotar + float max_vy_; // Máxima velocidad en Y + bool being_created_; // Si el globo se está creando + bool enabled_ = true; // Si el globo está activo + bool invulnerable_; // Si el globo es invulnerable + bool stopped_; // Si el globo está parado + bool use_reversed_colors_ = false; // Si se usa el color alternativo + Circle collider_; // Círculo de colisión + Uint16 creation_counter_; // Temporizador de creación + Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación + Uint16 score_; // Puntos al destruir el globo + Type type_; // Tipo de globo + Size size_; // Tamaño de globo + Uint8 menace_; // Amenaza que genera el globo + Uint32 counter_ = 0; // Contador interno + float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad + float speed_; // Velocidad del globo + Uint8 power_; // Poder que alberga el globo + SDL_FRect play_area_; // Zona de movimiento del globo + Sound sound_; // Configuración de sonido del globo + BounceEffect bounce_effect_; // Efecto de rebote // --- Posicionamiento y transformación --- void shiftColliders(); // Alinea el círculo de colisión con el sprite void shiftSprite(); // Alinea el sprite en pantalla // --- Animación y sonido --- - void setAnimation(); // Establece la animación correspondiente - void playSound(const std::string& name) const; // Reproduce un sonido por nombre - void playBouncingSound(); // Reproduce el sonido de rebote + void setAnimation(); // Establece la animación correspondiente + void playBouncingSound(); // Reproduce el sonido de rebote + void playPoppingSound(); // Reproduce el sonido de reventar // --- Movimiento y física --- void handleHorizontalMovement(); // Maneja el movimiento horizontal diff --git a/source/balloon_formations.h b/source/balloon_formations.h index 272275c..76b5d89 100644 --- a/source/balloon_formations.h +++ b/source/balloon_formations.h @@ -15,19 +15,24 @@ class BalloonFormations { public: // --- Estructuras --- struct SpawnParams { - int x = 0; // Posición en el eje X donde crear el globo - int y = 0; // Posición en el eje Y donde crear el globo + float x = 0; // Posición en el eje X donde crear el globo + float y = 0; // Posición en el eje Y donde crear el globo float vel_x = 0.0F; // Velocidad inicial en el eje X Balloon::Type type = Balloon::Type::BALLOON; // Tipo de globo Balloon::Size size = Balloon::Size::SMALL; // Tamaño de globo - int creation_counter = 0; // Temporizador para la creación del globo + Uint16 creation_counter = 0; // Temporizador para la creación del globo // Constructor por defecto SpawnParams() = default; // Constructor con parámetros - SpawnParams(int x, int y, float vel_x, Balloon::Type type, Balloon::Size size, int creation_counter) - : x(x), y(y), vel_x(vel_x), type(type), size(size), creation_counter(creation_counter) {} + SpawnParams(float x, float y, float vel_x, Balloon::Type type, Balloon::Size size, Uint16 creation_counter) + : x(x), + y(y), + vel_x(vel_x), + type(type), + size(size), + creation_counter(creation_counter) {} }; struct Formation { diff --git a/source/balloon_manager.cpp b/source/balloon_manager.cpp index 2ab8f26..dbfec87 100644 --- a/source/balloon_manager.cpp +++ b/source/balloon_manager.cpp @@ -17,7 +17,9 @@ // Constructor BalloonManager::BalloonManager(IStageInfo *stage_info) - : explosions_(std::make_unique()), balloon_formations_(std::make_unique()), stage_info_(stage_info) { init(); } + : explosions_(std::make_unique()), + balloon_formations_(std::make_unique()), + stage_info_(stage_info) { init(); } // Inicializa void BalloonManager::init() { @@ -105,7 +107,15 @@ void BalloonManager::deployRandomFormation(int stage) { // Crea los globos de la formación const auto BALLOONS = balloon_formations_->getFormationFromPool(stage, formation_id).balloons; for (auto balloon : BALLOONS) { - createBalloon(balloon.x, balloon.y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, (creation_time_enabled_) ? balloon.creation_counter : 0); + Balloon::Config config = { + .x = balloon.x, + .y = balloon.y, + .vel_x = balloon.vel_x, + .type = balloon.type, + .size = balloon.size, + .speed = balloon_speed_, + .creation_counter = static_cast(creation_time_enabled_ ? balloon.creation_counter : 0)}; + createBalloon(config); } // Reinicia el contador para el próximo despliegue @@ -118,15 +128,31 @@ void BalloonManager::deployRandomFormation(int stage) { void BalloonManager::deployFormation(int formation_id) { const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons; for (auto balloon : BALLOONS) { - createBalloon(balloon.x, balloon.y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, balloon.creation_counter); + Balloon::Config config = { + .x = balloon.x, + .y = balloon.y, + .vel_x = balloon.vel_x, + .type = balloon.type, + .size = balloon.size, + .speed = balloon_speed_, + .creation_counter = balloon.creation_counter}; + createBalloon(config); } } // Crea una formación de globos específica a una altura determinada -void BalloonManager::deployFormation(int formation_id, int y) { +void BalloonManager::deployFormation(int formation_id, float y) { const auto BALLOONS = balloon_formations_->getFormation(formation_id).balloons; for (auto balloon : BALLOONS) { - createBalloon(balloon.x, y, balloon.type, balloon.size, balloon.vel_x, balloon_speed_, balloon.creation_counter); + Balloon::Config config = { + .x = balloon.x, + .y = y, + .vel_x = balloon.vel_x, + .type = balloon.type, + .size = balloon.size, + .speed = balloon_speed_, + .creation_counter = balloon.creation_counter}; + createBalloon(config); } } @@ -152,13 +178,16 @@ auto BalloonManager::calculateScreenPower() -> int { } // Crea un globo nuevo en el vector de globos -auto BalloonManager::createBalloon(float x, int y, Balloon::Type type, Balloon::Size size, float velx, float speed, int creation_timer) -> std::shared_ptr { +auto BalloonManager::createBalloon(Balloon::Config config) -> std::shared_ptr { if (can_deploy_balloons_) { - const int INDEX = static_cast(size); - balloons_.emplace_back(std::make_shared(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(INDEX), balloon_animations_.at(INDEX))); - balloons_.back()->setSound(sound_enabled_); - balloons_.back()->setBouncingSound(bouncing_sound_enabled_); - balloons_.back()->setPoppingSound(poping_sound_enabled_); + const int INDEX = static_cast(config.size); + config.play_area = play_area_; + config.texture = balloon_textures_.at(INDEX); + config.animation = balloon_animations_.at(INDEX); + config.sound.enabled = sound_enabled_; + config.sound.bouncing_enabled = bouncing_sound_enabled_; + config.sound.poping_enabled = poping_sound_enabled_; + balloons_.emplace_back(std::make_shared(config)); return balloons_.back(); } @@ -169,19 +198,24 @@ auto BalloonManager::createBalloon(float x, int y, Balloon::Type type, Balloon:: void BalloonManager::createChildBalloon(const std::shared_ptr &balloon, const std::string &direction) { if (can_deploy_balloons_) { // Calcula parametros - const float VX = direction == "LEFT" ? Balloon::VELX_NEGATIVE : Balloon::VELX_POSITIVE; - const auto SIZE = static_cast(static_cast(balloon->getSize()) - 1); const int PARENT_HEIGHT = balloon->getHeight(); const int CHILD_HEIGHT = Balloon::WIDTH.at(static_cast(balloon->getSize()) - 1); const int CHILD_WIDTH = CHILD_HEIGHT; - const float Y = balloon->getPosY() + ((PARENT_HEIGHT - CHILD_HEIGHT) / 2); - float x = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + (2 * (balloon->getWidth() / 3)); + + const float X = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + (2 * (balloon->getWidth() / 3)); const float MIN_X = play_area_.x; const float MAX_X = play_area_.w - CHILD_WIDTH; - x = std::clamp(x - (CHILD_WIDTH / 2), MIN_X, MAX_X); + + Balloon::Config config = { + .x = std::clamp(X - (CHILD_WIDTH / 2), MIN_X, MAX_X), + .y = balloon->getPosY() + ((PARENT_HEIGHT - CHILD_HEIGHT) / 2), + .size = static_cast(static_cast(balloon->getSize()) - 1), + .vel_x = direction == "LEFT" ? Balloon::VELX_NEGATIVE : Balloon::VELX_POSITIVE, + .creation_counter = 0, + .speed = balloon_speed_}; // Crea el globo - auto b = createBalloon(x, Y, balloon->getType(), SIZE, VX, balloon_speed_, 0); + auto b = createBalloon(config); // Establece parametros b->setVelY(b->getType() == Balloon::Type::BALLOON ? -2.50F : Balloon::VELX_NEGATIVE * 2.0F); @@ -196,22 +230,33 @@ void BalloonManager::createChildBalloon(const std::shared_ptr &balloon, void BalloonManager::createPowerBall() { if (can_deploy_balloons_) { constexpr int VALUES = 6; - constexpr float POS_Y = -Balloon::WIDTH.at(4); - constexpr int CREATION_TIME = 0; + const int LUCK = rand() % VALUES; const float LEFT = param.game.play_area.rect.x; const float CENTER = param.game.play_area.center_x - (Balloon::WIDTH.at(4) / 2); const float RIGHT = param.game.play_area.rect.w - Balloon::WIDTH.at(4); - const int LUCK = rand() % VALUES; const std::array POS_X = {LEFT, LEFT, CENTER, CENTER, RIGHT, RIGHT}; const std::array VEL_X = {Balloon::VELX_POSITIVE, Balloon::VELX_POSITIVE, Balloon::VELX_POSITIVE, Balloon::VELX_NEGATIVE, Balloon::VELX_NEGATIVE, Balloon::VELX_NEGATIVE}; - balloons_.emplace_back(std::make_unique(POS_X[LUCK], POS_Y, Balloon::Type::POWERBALL, Balloon::Size::EXTRALARGE, VEL_X[LUCK], balloon_speed_, CREATION_TIME, play_area_, balloon_textures_[4], balloon_animations_[4])); + Balloon::Config config = { + .x = POS_X.at(LUCK), + .y = -Balloon::WIDTH.at(4), + .type = Balloon::Type::POWERBALL, + .size = Balloon::Size::EXTRALARGE, + .vel_x = VEL_X.at(LUCK), + .speed = balloon_speed_, + .creation_counter = 0, + .play_area = play_area_, + .texture = balloon_textures_.at(4), + .animation = balloon_animations_.at(4), + .sound = { + .enabled = sound_enabled_, + .bouncing_enabled = bouncing_sound_enabled_, + .poping_enabled = poping_sound_enabled_}}; + + balloons_.emplace_back(std::make_unique(config)); balloons_.back()->setInvulnerable(true); - balloons_.back()->setSound(sound_enabled_); - balloons_.back()->setBouncingSound(bouncing_sound_enabled_); - balloons_.back()->setPoppingSound(poping_sound_enabled_); power_ball_enabled_ = true; power_ball_counter_ = Balloon::POWERBALL_COUNTER; @@ -335,19 +380,6 @@ void BalloonManager::createTwoBigBalloons() { deployFormation(1); } -// Crea una disposición de globos aleatoria -void BalloonManager::createRandomBalloons() { - const int NUM_BALLOONS = 2 + (rand() % 4); - for (int i = 0; i < NUM_BALLOONS; ++i) { - const float X = param.game.game_area.rect.x + (rand() % static_cast(param.game.game_area.rect.w)) - Balloon::WIDTH.at(3); - const int Y = param.game.game_area.rect.y + (rand() % 50); - const auto SIZE = static_cast(rand() % 4); - const float VEL_X = (rand() % 2 == 0) ? Balloon::VELX_POSITIVE : Balloon::VELX_NEGATIVE; - const int CREATION_COUNTER = 0; - createBalloon(X, Y, Balloon::Type::BALLOON, SIZE, VEL_X, balloon_speed_, CREATION_COUNTER); - } -} - // Obtiene el nivel de ameza actual generado por los globos auto BalloonManager::getMenace() -> int { return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); }); diff --git a/source/balloon_manager.h b/source/balloon_manager.h index 5ff5fa1..6458e6a 100644 --- a/source/balloon_manager.h +++ b/source/balloon_manager.h @@ -37,14 +37,13 @@ class BalloonManager { // --- Creación de formaciones enemigas --- void deployRandomFormation(int stage); // Crea una formación de globos aleatoria void deployFormation(int formation_id); // Crea una formación específica - void deployFormation(int formation_id, int y); // Crea una formación específica con coordenadas + void deployFormation(int formation_id, float y); // Crea una formación específica con coordenadas // --- Creación de globos --- - auto createBalloon(float x, int y, Balloon::Type type, Balloon::Size size, float velx, float speed, int creation_timer) -> std::shared_ptr; // Crea un nuevo globo + auto createBalloon(Balloon::Config config) -> std::shared_ptr; // Crea un nuevo globo void createChildBalloon(const std::shared_ptr &balloon, const std::string &direction); // Crea un globo a partir de otro void createPowerBall(); // Crea una PowerBall void createTwoBigBalloons(); // Crea dos globos grandes - void createRandomBalloons(); // Crea una disposición aleatoria de globos // --- Control de velocidad y despliegue --- void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos diff --git a/source/color.cpp b/source/color.cpp index b14d0d3..c852c39 100644 --- a/source/color.cpp +++ b/source/color.cpp @@ -116,71 +116,71 @@ constexpr auto Color::hsvToRgb(HSV hsv) -> Color { // Implementaciones del namespace Colors namespace Colors { - // Obtiene un color del vector de colores imitando al Coche Fantástico - auto getColorLikeKnightRider(const std::vector &colors, int counter) -> Color { - int cycle_length = (colors.size() * 2) - 2; - size_t n = counter % cycle_length; +// Obtiene un color del vector de colores imitando al Coche Fantástico +auto getColorLikeKnightRider(const std::vector &colors, int counter) -> Color { + int cycle_length = (colors.size() * 2) - 2; + size_t n = counter % cycle_length; - size_t index; - if (n < colors.size()) { - index = n; // Avanza: 0,1,2,3 - } else { - index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1 - } - - return colors[index]; + size_t index; + if (n < colors.size()) { + index = n; // Avanza: 0,1,2,3 + } else { + index = 2 * (colors.size() - 1) - n; // Retrocede: 2,1 } - auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle { - Cycle result{}; - HSV base_hsv = Color::rgbToHsv(base); + return colors[index]; +} - for (size_t i = 0; i < CYCLE_SIZE; ++i) { - float t = static_cast(i) / (CYCLE_SIZE - 1); // 0 → 1 - float hue_shift = 0.0F; - float sat_shift = 0.0F; - float val_shift = 0.0F; +auto generateMirroredCycle(Color base, ColorCycleStyle style) -> Cycle { + Cycle result{}; + HSV base_hsv = Color::rgbToHsv(base); - switch (style) { - case ColorCycleStyle::SUBTLE_PULSE: - // Solo brillo suave - val_shift = 0.07F * sinf(t * M_PI); - break; + for (size_t i = 0; i < CYCLE_SIZE; ++i) { + float t = static_cast(i) / (CYCLE_SIZE - 1); // 0 → 1 + float hue_shift = 0.0F; + float sat_shift = 0.0F; + float val_shift = 0.0F; - case ColorCycleStyle::HUE_WAVE: - // Oscilación leve de tono - hue_shift = 15.0F * (t - 0.5F) * 2.0F; - val_shift = 0.05F * sinf(t * M_PI); - break; + switch (style) { + case ColorCycleStyle::SUBTLE_PULSE: + // Solo brillo suave + val_shift = 0.07F * sinf(t * M_PI); + break; - case ColorCycleStyle::VIBRANT: - // Cambios fuertes en tono y brillo - hue_shift = 35.0F * sinf(t * M_PI); - val_shift = 0.2F * sinf(t * M_PI); - sat_shift = -0.2F * sinf(t * M_PI); - break; + case ColorCycleStyle::HUE_WAVE: + // Oscilación leve de tono + hue_shift = 15.0F * (t - 0.5F) * 2.0F; + val_shift = 0.05F * sinf(t * M_PI); + break; - case ColorCycleStyle::DARKEN_GLOW: - // Se oscurece al centro - val_shift = -0.15F * sinf(t * M_PI); - break; + case ColorCycleStyle::VIBRANT: + // Cambios fuertes en tono y brillo + hue_shift = 35.0F * sinf(t * M_PI); + val_shift = 0.2F * sinf(t * M_PI); + sat_shift = -0.2F * sinf(t * M_PI); + break; - case ColorCycleStyle::LIGHT_FLASH: - // Se ilumina al centro - val_shift = 0.25F * sinf(t * M_PI); - break; - } + case ColorCycleStyle::DARKEN_GLOW: + // Se oscurece al centro + val_shift = -0.15F * sinf(t * M_PI); + break; - HSV adjusted = { - .h = fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F), - .s = fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)), - .v = fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))}; - - Color c = Color::hsvToRgb(adjusted); - result[i] = c; - result[(2 * CYCLE_SIZE) - 1 - i] = c; // espejo + case ColorCycleStyle::LIGHT_FLASH: + // Se ilumina al centro + val_shift = 0.25F * sinf(t * M_PI); + break; } - return result; + HSV adjusted = { + .h = fmodf(base_hsv.h + hue_shift + 360.0F, 360.0F), + .s = fminf(1.0F, fmaxf(0.0F, base_hsv.s + sat_shift)), + .v = fminf(1.0F, fmaxf(0.0F, base_hsv.v + val_shift))}; + + Color c = Color::hsvToRgb(adjusted); + result[i] = c; + result[(2 * CYCLE_SIZE) - 1 - i] = c; // espejo } -} \ No newline at end of file + + return result; +} +} // namespace Colors \ No newline at end of file diff --git a/source/color.h b/source/color.h index 6414dab..413af34 100644 --- a/source/color.h +++ b/source/color.h @@ -36,10 +36,17 @@ struct Color { Uint8 r, g, b, a; - constexpr Color() : r(MIN_COLOR_VALUE), g(MIN_COLOR_VALUE), b(MIN_COLOR_VALUE), a(DEFAULT_ALPHA) {} + constexpr Color() + : r(MIN_COLOR_VALUE), + g(MIN_COLOR_VALUE), + b(MIN_COLOR_VALUE), + a(DEFAULT_ALPHA) {} explicit constexpr Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha = DEFAULT_ALPHA) - : r(red), g(green), b(blue), a(alpha) {} + : r(red), + g(green), + b(blue), + a(alpha) {} [[nodiscard]] constexpr auto INVERSE() const -> Color { return Color(MAX_COLOR_VALUE - r, MAX_COLOR_VALUE - g, MAX_COLOR_VALUE - b, a); @@ -108,25 +115,25 @@ enum class ColorCycleStyle { // --- Namespace Colors: constantes y utilidades de color --- namespace Colors { - // --- Constantes --- - constexpr size_t CYCLE_SIZE = 6; // Mitad del ciclo espejado +// --- Constantes --- +constexpr size_t CYCLE_SIZE = 6; // Mitad del ciclo espejado - // --- Alias --- - using Cycle = std::array; +// --- Alias --- +using Cycle = std::array; - // --- Colores predefinidos --- - constexpr Color NO_COLOR_MOD = Color(0XFF, 0XFF, 0XFF); - constexpr Color SHADOW_TEXT = Color(0X43, 0X43, 0X4F); - constexpr Color TITLE_SHADOW_TEXT = Color(0x14, 0x87, 0xc4); - constexpr Color ORANGE_TEXT = Color(0XFF, 0X7A, 0X00); +// --- Colores predefinidos --- +constexpr Color NO_COLOR_MOD = Color(0XFF, 0XFF, 0XFF); +constexpr Color SHADOW_TEXT = Color(0X43, 0X43, 0X4F); +constexpr Color TITLE_SHADOW_TEXT = Color(0x14, 0x87, 0xc4); +constexpr Color ORANGE_TEXT = Color(0XFF, 0X7A, 0X00); - constexpr Color FLASH = Color(0XFF, 0XFF, 0XFF); +constexpr Color FLASH = Color(0XFF, 0XFF, 0XFF); - constexpr Color BLUE_SKY = Color(0X02, 0X88, 0XD1); - constexpr Color PINK_SKY = Color(0XFF, 0X6B, 0X97); - constexpr Color GREEN_SKY = Color(0X00, 0X79, 0X6B); +constexpr Color BLUE_SKY = Color(0X02, 0X88, 0XD1); +constexpr Color PINK_SKY = Color(0XFF, 0X6B, 0X97); +constexpr Color GREEN_SKY = Color(0X00, 0X79, 0X6B); - // --- Funciones --- - auto getColorLikeKnightRider(const std::vector &colors, int counter) -> Color; - auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> Cycle; -} \ No newline at end of file +// --- Funciones --- +auto getColorLikeKnightRider(const std::vector &colors, int counter) -> Color; +auto generateMirroredCycle(Color base, ColorCycleStyle style = ColorCycleStyle::SUBTLE_PULSE) -> Cycle; +} // namespace Colors \ No newline at end of file diff --git a/source/defaults.h b/source/defaults.h index 9035f58..5b6c95d 100644 --- a/source/defaults.h +++ b/source/defaults.h @@ -76,7 +76,8 @@ struct BalloonSettings { float vel; float grav; constexpr BalloonSettings(float v, float g) - : vel(v), grav(g) {} + : vel(v), + grav(g) {} }; constexpr std::array SETTINGS = {{ diff --git a/source/define_buttons.h b/source/define_buttons.h index 49562c6..f85d9b3 100644 --- a/source/define_buttons.h +++ b/source/define_buttons.h @@ -25,7 +25,9 @@ class DefineButtons { int button; Button(std::string label, Input::Action action, int button) - : label(std::move(label)), action(action), button(button) {} + : label(std::move(label)), + action(action), + button(button) {} }; // --- Constructor y destructor --- diff --git a/source/director.cpp b/source/director.cpp index f49d54e..31055e2 100644 --- a/source/director.cpp +++ b/source/director.cpp @@ -18,9 +18,9 @@ #include "manage_hiscore_table.h" // Para ManageHiScoreTable #include "options.h" // Para loadFromFile, saveToFile, Settings, settings, setConfigFile, setControllersFile #include "param.h" // Para loadParamsFromFile -#include "resource_helper.h" // Para ResourceHelper #include "player.h" // Para Player #include "resource.h" // Para Resource +#include "resource_helper.h" // Para ResourceHelper #include "screen.h" // Para Screen #include "section.hpp" // Para Name, Options, name, options, AttractMode, attract_mode #include "sections/credits.h" // Para Credits @@ -77,8 +77,8 @@ Director::~Director() { // Inicializa todo void Director::init() { // Configuración inicial de parametros - Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos - + Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos + #ifdef MACOS_BUNDLE ResourceHelper::initializeResourceSystem(executable_path_ + "/../Resources/resources.pack"); #else diff --git a/source/enter_name.cpp b/source/enter_name.cpp index f985245..f12e8cc 100644 --- a/source/enter_name.cpp +++ b/source/enter_name.cpp @@ -45,8 +45,8 @@ void EnterName::incPosition() { } else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGTH { // Copiamos el índice del carácter anterior si es posible. - //character_index_[position_] = character_index_[position_ - 1]; - + // character_index_[position_] = character_index_[position_ - 1]; + // Ponemos el caracter "espacio" character_index_[position_] = 0; } else { @@ -147,12 +147,19 @@ auto EnterName::findIndex(char character) const -> int { // Devuelve un nombre al azar auto EnterName::getRandomName() -> std::string { static constexpr std::array NAMES = { - "BAL1", "TABE", "DOC", "MON", "SAM1", "JORDI", "JDES", "PEPE"}; + "BAL1", + "TABE", + "DOC", + "MON", + "SAM1", + "JORDI", + "JDES", + "PEPE"}; return std::string(NAMES[rand() % NAMES.size()]); } // Obtiene el nombre final introducido auto EnterName::getFinalName() -> std::string { - auto name = trim(name_.substr(0, position_ + 1)); // Devuelve el texto intruducido incluyendo el del selector + auto name = trim(name_.substr(0, position_ + 1)); // Devuelve el texto intruducido incluyendo el del selector if (name.empty()) { name = getRandomName(); } diff --git a/source/explosions.h b/source/explosions.h index 47a5056..20a39c2 100644 --- a/source/explosions.h +++ b/source/explosions.h @@ -16,7 +16,9 @@ struct ExplosionTexture { std::vector animation; // Animación para la textura ExplosionTexture(int sz, std::shared_ptr tex, const std::vector &anim) - : size(sz), texture(std::move(tex)), animation(anim) {} + : size(sz), + texture(std::move(tex)), + animation(anim) {} }; // --- Clase Explosions: gestor de explosiones --- diff --git a/source/fade.cpp b/source/fade.cpp index c29b182..61257e5 100644 --- a/source/fade.cpp +++ b/source/fade.cpp @@ -41,7 +41,7 @@ void Fade::init() { num_squares_width_ = param.fade.num_squares_width; num_squares_height_ = param.fade.num_squares_height; random_squares_duration_ = param.fade.random_squares_duration_ms; // Usar como duración en ms - square_transition_duration_ = random_squares_duration_ / 4; // 25% del tiempo total para la transición individual + square_transition_duration_ = random_squares_duration_ / 4; // 25% del tiempo total para la transición individual random_squares_start_time_ = 0; } @@ -60,7 +60,7 @@ void Fade::render() { if (state_ == State::FINISHED && mode_ == Mode::IN) { return; } - + SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr); } } @@ -85,7 +85,7 @@ void Fade::update() { void Fade::updatePreState() { // Sistema basado en tiempo únicamente Uint32 elapsed_time = SDL_GetTicks() - pre_start_time_; - + if (elapsed_time >= static_cast(pre_duration_)) { state_ = State::FADING; // CRÍTICO: Reinicializar tiempo de inicio para tipos que usan random_squares_start_time_ @@ -129,17 +129,17 @@ void Fade::changeToPostState() { void Fade::updatePostState() { // Sistema basado en tiempo únicamente Uint32 elapsed_time = SDL_GetTicks() - post_start_time_; - + if (elapsed_time >= static_cast(post_duration_)) { state_ = State::FINISHED; } - + // Mantener el alpha final correcto para cada tipo de fade Uint8 post_alpha = a_; if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) { post_alpha = (mode_ == Mode::OUT) ? 255 : 0; } - + cleanBackbuffer(r_, g_, b_, post_alpha); } @@ -204,16 +204,16 @@ void Fade::updateRandomSquareFade() { void Fade::updateRandomSquare2Fade() { Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_; - + int total_squares = num_squares_width_ * num_squares_height_; - + // Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados int activation_time = random_squares_duration_ - square_transition_duration_; activation_time = std::max(activation_time, square_transition_duration_); // Mínimo igual a la duración de transición - + // Lógica diferente según el modo int squares_to_activate = 0; - + if (mode_ == Mode::OUT) { // OUT: Activa cuadrados gradualmente if (elapsed_time < static_cast(activation_time)) { @@ -222,7 +222,7 @@ void Fade::updateRandomSquare2Fade() { } else { squares_to_activate = total_squares; // Activar todos } - + // Activa nuevos cuadrados y guarda su tiempo de activación for (int i = 0; i < squares_to_activate && i < total_squares; ++i) { if (square_age_[i] == -1) { @@ -232,22 +232,22 @@ void Fade::updateRandomSquare2Fade() { } else { // IN: Todos los cuadrados empiezan activos desde el inicio squares_to_activate = total_squares; - + // Activa cuadrados gradualmente con tiempo de inicio escalonado float activation_progress = static_cast(elapsed_time) / activation_time; int squares_starting_transition = static_cast(activation_progress * total_squares); - + // Asegurar que al menos 1 cuadrado se active desde el primer frame squares_starting_transition = std::max(squares_starting_transition, 1); squares_starting_transition = std::min(squares_starting_transition, total_squares); - + for (int i = 0; i < squares_starting_transition; ++i) { if (square_age_[i] == -1) { square_age_[i] = elapsed_time; // Empieza la transición a transparente } } } - + drawRandomSquares2(); value_ = calculateValue(0, total_squares, squares_to_activate); @@ -265,7 +265,7 @@ void Fade::updateRandomSquare2Fade() { } } } - + if (all_completed) { // Pintar textura final: OUT opaca, IN transparente Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; @@ -277,17 +277,17 @@ void Fade::updateRandomSquare2Fade() { void Fade::updateDiagonalFade() { Uint32 elapsed_time = SDL_GetTicks() - random_squares_start_time_; - + int total_squares = num_squares_width_ * num_squares_height_; - + // Calcula el tiempo de activación: total - tiempo que necesitan los últimos cuadrados int activation_time = random_squares_duration_ - square_transition_duration_; activation_time = std::max(activation_time, square_transition_duration_); - + // Calcula cuántas diagonales deberían estar activas int max_diagonal = num_squares_width_ + num_squares_height_ - 1; // Número total de diagonales int active_diagonals = 0; - + if (mode_ == Mode::OUT) { // OUT: Activa diagonales gradualmente desde esquina superior izquierda if (elapsed_time < static_cast(activation_time)) { @@ -296,7 +296,7 @@ void Fade::updateDiagonalFade() { } else { active_diagonals = max_diagonal; // Activar todas } - + // Activa cuadrados por diagonales for (int diagonal = 0; diagonal < active_diagonals; ++diagonal) { activateDiagonal(diagonal, elapsed_time); @@ -304,12 +304,12 @@ void Fade::updateDiagonalFade() { } else { // IN: Todas las diagonales empiezan activas, van desapareciendo active_diagonals = max_diagonal; - + // Activa diagonales gradualmente para transición if (elapsed_time < static_cast(activation_time)) { float activation_progress = static_cast(elapsed_time) / activation_time; int diagonals_starting_transition = static_cast(activation_progress * max_diagonal); - + for (int diagonal = 0; diagonal < diagonals_starting_transition; ++diagonal) { activateDiagonal(diagonal, elapsed_time); } @@ -320,7 +320,7 @@ void Fade::updateDiagonalFade() { } } } - + drawDiagonal(); value_ = calculateValue(0, total_squares, active_diagonals * (total_squares / max_diagonal)); @@ -338,7 +338,7 @@ void Fade::updateDiagonalFade() { } } } - + if (all_completed) { // Pintar textura final: OUT opaca, IN transparente Uint8 final_alpha = (mode_ == Mode::OUT) ? 255 : 0; @@ -354,15 +354,15 @@ void Fade::activateDiagonal(int diagonal_index, Uint32 current_time) { // Diagonal 1: (1,0), (0,1) // Diagonal 2: (2,0), (1,1), (0,2) // etc. - + for (int x = 0; x < num_squares_width_; ++x) { int y = diagonal_index - x; - + // Verificar que y está dentro de los límites if (y >= 0 && y < num_squares_height_) { // Convertir coordenadas (x,y) a índice en el vector int index = y * num_squares_width_ + x; - + if (index >= 0 && index < static_cast(square_age_.size())) { if (square_age_[index] == -1) { square_age_[index] = current_time; // Guarda el tiempo de activación @@ -385,30 +385,30 @@ void Fade::drawDiagonal() { SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha Uint32 current_time = SDL_GetTicks() - random_squares_start_time_; - + // Lógica unificada: sobre textura transparente, pintar cuadrados según su estado for (size_t i = 0; i < square_.size(); ++i) { Uint8 current_alpha = 0; - + if (square_age_[i] == -1) { // Cuadrado no activado if (mode_ == Mode::OUT) { current_alpha = 0; // OUT: transparente si no activado } else { - current_alpha = a_; // IN: opaco si no activado + current_alpha = a_; // IN: opaco si no activado } } else { // Cuadrado activado - calculamos progreso Uint32 square_elapsed = current_time - square_age_[i]; float progress = std::min(static_cast(square_elapsed) / square_transition_duration_, 1.0f); - + if (mode_ == Mode::OUT) { current_alpha = static_cast(progress * a_); // 0 → 255 } else { current_alpha = static_cast((1.0f - progress) * a_); // 255 → 0 } } - + if (current_alpha > 0) { SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha); SDL_RenderFillRect(renderer_, &square_[i]); @@ -450,30 +450,30 @@ void Fade::drawRandomSquares2() { SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); // Usar BLEND para alpha Uint32 current_time = SDL_GetTicks() - random_squares_start_time_; - + // Lógica unificada: sobre textura transparente, pintar cuadrados según su estado for (size_t i = 0; i < square_.size(); ++i) { Uint8 current_alpha = 0; - + if (square_age_[i] == -1) { // Cuadrado no activado if (mode_ == Mode::OUT) { current_alpha = 0; // OUT: transparente si no activado } else { - current_alpha = a_; // IN: opaco si no activado + current_alpha = a_; // IN: opaco si no activado } } else { // Cuadrado activado - calculamos progreso Uint32 square_elapsed = current_time - square_age_[i]; float progress = std::min(static_cast(square_elapsed) / square_transition_duration_, 1.0f); - + if (mode_ == Mode::OUT) { current_alpha = static_cast(progress * a_); // 0 → 255 } else { current_alpha = static_cast((1.0f - progress) * a_); // 255 → 0 } } - + if (current_alpha > 0) { SDL_SetRenderDrawColor(renderer_, r_, g_, b_, current_alpha); SDL_RenderFillRect(renderer_, &square_[i]); diff --git a/source/fade.h b/source/fade.h index eff1303..4ea96fe 100644 --- a/source/fade.h +++ b/source/fade.h @@ -11,12 +11,12 @@ class Fade { public: // --- Enums --- enum class Type : Uint8 { - FULLSCREEN = 0, // Fundido de pantalla completa - CENTER = 1, // Fundido desde el centro - RANDOM_SQUARE = 2, // Fundido con cuadrados aleatorios - RANDOM_SQUARE2 = 3, // Fundido con cuadrados aleatorios (variante 2) - DIAGONAL = 4, // Fundido diagonal desde esquina superior izquierda - VENETIAN = 5, // Fundido tipo persiana veneciana + FULLSCREEN = 0, // Fundido de pantalla completa + CENTER = 1, // Fundido desde el centro + RANDOM_SQUARE = 2, // Fundido con cuadrados aleatorios + RANDOM_SQUARE2 = 3, // Fundido con cuadrados aleatorios (variante 2) + DIAGONAL = 4, // Fundido diagonal desde esquina superior izquierda + VENETIAN = 5, // Fundido tipo persiana veneciana }; enum class Mode : Uint8 { @@ -104,10 +104,10 @@ class Fade { void calculateVenetianProgress(); // Calcula el progreso del efecto veneciano // --- Dibujo de efectos visuales --- - void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central - void drawRandomSquares(int active_count = -1); // Dibuja los cuadrados aleatorios del fundido - void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2) - void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal + void drawCenterFadeRectangles(); // Dibuja los rectángulos del fundido central + void drawRandomSquares(int active_count = -1); // Dibuja los cuadrados aleatorios del fundido + void drawRandomSquares2(); // Dibuja los cuadrados con transición de color (RANDOM_SQUARE2) + void drawDiagonal(); // Dibuja los cuadrados con patrón diagonal void activateDiagonal(int diagonal_index, Uint32 current_time); // Activa una diagonal específica - void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido + void drawVenetianBlinds(); // Dibuja las persianas venecianas del fundido }; \ No newline at end of file diff --git a/source/game_logo.h b/source/game_logo.h index 84e4944..07e8563 100644 --- a/source/game_logo.h +++ b/source/game_logo.h @@ -43,7 +43,12 @@ class GameLogo { Shake() = default; Shake(int d, int de, int l, int o) - : desp(d), delay(de), length(l), remaining(l), counter(de), origin(o) {} + : desp(d), + delay(de), + length(l), + remaining(l), + counter(de), + origin(o) {} void init(int d, int de, int l, int o) { desp = d; diff --git a/source/input.h b/source/input.h index beaa943..37d9c76 100644 --- a/source/input.h +++ b/source/input.h @@ -32,7 +32,9 @@ class Input { bool just_pressed; // Se acaba de pulsar en este fotograma KeyState(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false) - : scancode(scancode), is_held(is_held), just_pressed(just_pressed) {} + : scancode(scancode), + is_held(is_held), + just_pressed(just_pressed) {} }; struct ButtonState { @@ -43,7 +45,10 @@ class Input { bool trigger_active{false}; // Estado del trigger como botón digital ButtonState(int btn = static_cast(SDL_GAMEPAD_BUTTON_INVALID), bool is_held = false, bool just_pressed = false, bool axis_act = false) - : button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {} + : button(btn), + is_held(is_held), + just_pressed(just_pressed), + axis_active(axis_act) {} }; struct Keyboard { diff --git a/source/item.cpp b/source/item.cpp index 9e990c4..6e1d20d 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -9,7 +9,9 @@ class Texture; // lines 6-6 Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, const std::shared_ptr &texture, const std::vector &animation) - : sprite_(std::make_unique(texture, animation)), play_area_(play_area), type_(type) { + : sprite_(std::make_unique(texture, animation)), + play_area_(play_area), + type_(type) { switch (type) { case ItemType::COFFEE_MACHINE: { width_ = COFFEE_MACHINE_WIDTH; @@ -90,7 +92,7 @@ void Item::move() { // Si toca el borde lateral if (pos_x_ == MIN_X || pos_x_ == MAX_X) { - vel_x_ = -vel_x_; // Invierte la velocidad horizontal + vel_x_ = -vel_x_; // Invierte la velocidad horizontal } // Si colisiona por arriba, rebota (excepto la máquina de café) diff --git a/source/lang.cpp b/source/lang.cpp index 1c75020..b0082a8 100644 --- a/source/lang.cpp +++ b/source/lang.cpp @@ -30,10 +30,10 @@ auto loadFromFile(const std::string &file_path) -> bool { // Intentar cargar desde ResourceHelper primero auto resource_data = ResourceHelper::loadFile(file_path); - + try { json j; - + if (!resource_data.empty()) { // Cargar desde datos del pack std::string content(resource_data.begin(), resource_data.end()); diff --git a/source/lang.h b/source/lang.h index 3b27206..ed0b483 100644 --- a/source/lang.h +++ b/source/lang.h @@ -19,7 +19,9 @@ struct Language { std::string file_name; // Nombre del fichero con los textos Language(Code c, std::string n, std::string fn) - : code(c), name(std::move(n)), file_name(std::move(fn)) {} + : code(c), + name(std::move(n)), + file_name(std::move(fn)) {} }; // --- Funciones --- diff --git a/source/manage_hiscore_table.h b/source/manage_hiscore_table.h index 552d137..d030c98 100644 --- a/source/manage_hiscore_table.h +++ b/source/manage_hiscore_table.h @@ -11,7 +11,9 @@ struct HiScoreEntry { // Constructor explicit HiScoreEntry(const std::string &n = "", int s = 0, bool occ = false) - : name(n.substr(0, 6)), score(s), one_credit_complete(occ) {} + : name(n.substr(0, 6)), + score(s), + one_credit_complete(occ) {} }; // --- Tipos --- diff --git a/source/param.cpp b/source/param.cpp index 3de54cb..020c55c 100644 --- a/source/param.cpp +++ b/source/param.cpp @@ -196,46 +196,48 @@ auto setParams(const std::string& var, const std::string& value) -> bool { // Colores válidos para globos static const std::unordered_map VALID_BALLOON_COLORS = { - {"blue", true}, {"orange", true}, {"red", true}, {"green", true} - }; - + {"blue", true}, + {"orange", true}, + {"red", true}, + {"green", true}}; + auto validateBalloonColor = [](const std::string& color) -> bool { return VALID_BALLOON_COLORS.find(color) != VALID_BALLOON_COLORS.end(); }; static const std::unordered_map> STRING_PARAMS = { - {"balloon.color[0]", [validateBalloonColor](const std::string& v) { - if (!validateBalloonColor(v)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'blue' por defecto.", v.c_str()); - param.balloon.color.at(0) = "blue"; - } else { - param.balloon.color.at(0) = v; - } - }}, - {"balloon.color[1]", [validateBalloonColor](const std::string& v) { - if (!validateBalloonColor(v)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'orange' por defecto.", v.c_str()); - param.balloon.color.at(1) = "orange"; - } else { - param.balloon.color.at(1) = v; - } - }}, - {"balloon.color[2]", [validateBalloonColor](const std::string& v) { - if (!validateBalloonColor(v)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'red' por defecto.", v.c_str()); - param.balloon.color.at(2) = "red"; - } else { - param.balloon.color.at(2) = v; - } - }}, - {"balloon.color[3]", [validateBalloonColor](const std::string& v) { - if (!validateBalloonColor(v)) { - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'green' por defecto.", v.c_str()); - param.balloon.color.at(3) = "green"; - } else { - param.balloon.color.at(3) = v; - } - }}}; + {"balloon.color[0]", [validateBalloonColor](const std::string& v) { + if (!validateBalloonColor(v)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'blue' por defecto.", v.c_str()); + param.balloon.color.at(0) = "blue"; + } else { + param.balloon.color.at(0) = v; + } + }}, + {"balloon.color[1]", [validateBalloonColor](const std::string& v) { + if (!validateBalloonColor(v)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'orange' por defecto.", v.c_str()); + param.balloon.color.at(1) = "orange"; + } else { + param.balloon.color.at(1) = v; + } + }}, + {"balloon.color[2]", [validateBalloonColor](const std::string& v) { + if (!validateBalloonColor(v)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'red' por defecto.", v.c_str()); + param.balloon.color.at(2) = "red"; + } else { + param.balloon.color.at(2) = v; + } + }}, + {"balloon.color[3]", [validateBalloonColor](const std::string& v) { + if (!validateBalloonColor(v)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Color de globo inválido '%s'. Usando 'green' por defecto.", v.c_str()); + param.balloon.color.at(3) = "green"; + } else { + param.balloon.color.at(3) = v; + } + }}}; // Lambda para intentar cada mapa de parámetros auto try_map = [&](const auto& param_map) -> bool { diff --git a/source/param.h b/source/param.h index c3a0a86..9f87cf1 100644 --- a/source/param.h +++ b/source/param.h @@ -57,7 +57,8 @@ struct ParamBalloon { // Constructor por defecto constexpr Settings(float grav_val = 0.0F, float vel_val = 0.0F) - : grav(grav_val), vel(vel_val) {} + : grav(grav_val), + vel(vel_val) {} }; // Inicialización con los valores por defecto desde GameDefaults @@ -164,7 +165,10 @@ struct ParamPlayer { // Constructor con tonalidades específicas Shirt(const Color& darkest_tone, const Color& dark_tone, const Color& base_tone, const Color& light_tone) - : darkest(darkest_tone), dark(dark_tone), base(base_tone), light(light_tone) {} + : darkest(darkest_tone), + dark(dark_tone), + base(base_tone), + light(light_tone) {} }; // Inicialización con valores por defecto diff --git a/source/path_sprite.h b/source/path_sprite.h index 9d7b9c9..7e5646b 100644 --- a/source/path_sprite.h +++ b/source/path_sprite.h @@ -33,7 +33,8 @@ struct Path { // Define un recorrido para el sprite // Constructor Path(const std::vector &spots_init, int waiting_counter_init) - : spots(spots_init), waiting_counter(waiting_counter_init) {} + : spots(spots_init), + waiting_counter(waiting_counter_init) {} }; // --- Funciones --- diff --git a/source/player.cpp b/source/player.cpp index bd1f0d5..a18f470 100644 --- a/source/player.cpp +++ b/source/player.cpp @@ -22,7 +22,17 @@ // Constructor Player::Player(const Config &config) - : player_sprite_(std::make_unique(config.texture.at(0), config.animations.at(0))), power_sprite_(std::make_unique(config.texture.at(4), config.animations.at(1))), enter_name_(std::make_unique()), hi_score_table_(config.hi_score_table), glowing_entry_(config.glowing_entry), stage_info_(config.stage_info), play_area_(*config.play_area), id_(config.id), default_pos_x_(config.x), default_pos_y_(config.y), demo_(config.demo) { + : player_sprite_(std::make_unique(config.texture.at(0), config.animations.at(0))), + power_sprite_(std::make_unique(config.texture.at(4), config.animations.at(1))), + enter_name_(std::make_unique()), + hi_score_table_(config.hi_score_table), + glowing_entry_(config.glowing_entry), + stage_info_(config.stage_info), + play_area_(*config.play_area), + id_(config.id), + default_pos_x_(config.x), + default_pos_y_(config.y), + demo_(config.demo) { // Configura objetos player_sprite_->addTexture(config.texture.at(1)); player_sprite_->addTexture(config.texture.at(2)); @@ -624,7 +634,7 @@ void Player::setPlayingState(State state) { switch (playing_state_) { case State::RECOVER: { - score_ = 0; // Pon los puntos a cero para que no se vea en el marcador + score_ = 0; // Pon los puntos a cero para que no se vea en el marcador score_multiplier_ = 1.0F; setScoreboardMode(Scoreboard::Mode::SCORE); break; diff --git a/source/resource.cpp b/source/resource.cpp index ce725a2..6248e0f 100644 --- a/source/resource.cpp +++ b/source/resource.cpp @@ -2,57 +2,57 @@ #include // Para SDL_LogInfo, SDL_LogCategory, SDL_LogError, SDL_SetRenderDrawColor, SDL_EventType, SDL_PollEvent, SDL_RenderFillRect, SDL_RenderRect, SDLK_ESCAPE, SDL_Event -#include // Para find_if, max, find -#include // Para array -#include // Para exit, getenv -#include // Para filesystem::remove, filesystem::exists -#include // Para ofstream -#include // Para runtime_error -#include // Para move +#include // Para find_if, max, find +#include // Para array +#include // Para exit, getenv +#include // Para filesystem::remove, filesystem::exists +#include // Para ofstream +#include // Para runtime_error +#include // Para move #include "asset.h" // Para Asset #include "color.h" // Para Color #ifndef NO_AUDIO #include "external/jail_audio.h" // Para JA_LoadMusic, JA_LoadSound, JA_DeleteMusic, JA_DeleteSound #endif -#include "lang.h" // Para getText -#include "param.h" // Para Param, param, ParamResource, ParamGame -#include "screen.h" // Para Screen -#include "text.h" // Para Text +#include "lang.h" // Para getText +#include "param.h" // Para Param, param, ParamResource, ParamGame #include "resource_helper.h" // Para ResourceHelper +#include "screen.h" // Para Screen +#include "text.h" // Para Text struct JA_Music_t; // lines 11-11 struct JA_Sound_t; // lines 12-12 // Helper para cargar archivos de audio desde pack o filesystem namespace { - std::string createTempAudioFile(const std::string& file_path, std::vector& temp_files_tracker) { - auto resource_data = ResourceHelper::loadFile(file_path); - if (!resource_data.empty()) { - // Crear archivo temporal - std::string temp_dir; +std::string createTempAudioFile(const std::string &file_path, std::vector &temp_files_tracker) { + auto resource_data = ResourceHelper::loadFile(file_path); + if (!resource_data.empty()) { + // Crear archivo temporal + std::string temp_dir; #ifdef _WIN32 - temp_dir = std::getenv("TEMP") ? std::getenv("TEMP") : "C:\\temp"; + temp_dir = std::getenv("TEMP") ? std::getenv("TEMP") : "C:\\temp"; #else - temp_dir = "/tmp"; + temp_dir = "/tmp"; #endif - std::string temp_path = temp_dir + "/ccae_audio_" + std::to_string(std::hash{}(file_path)); - std::ofstream temp_file(temp_path, std::ios::binary); - if (!temp_file) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot create temp file %s", temp_path.c_str()); - return file_path; - } - temp_file.write(reinterpret_cast(resource_data.data()), resource_data.size()); - temp_file.close(); - - // Agregar a la lista de archivos temporales para limpieza posterior - temp_files_tracker.push_back(temp_path); - - return temp_path; + std::string temp_path = temp_dir + "/ccae_audio_" + std::to_string(std::hash{}(file_path)); + std::ofstream temp_file(temp_path, std::ios::binary); + if (!temp_file) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot create temp file %s", temp_path.c_str()); + return file_path; } - return file_path; // Usar ruta original si no está en pack + temp_file.write(reinterpret_cast(resource_data.data()), resource_data.size()); + temp_file.close(); + + // Agregar a la lista de archivos temporales para limpieza posterior + temp_files_tracker.push_back(temp_path); + + return temp_path; } + return file_path; // Usar ruta original si no está en pack } +} // namespace // Declaraciones de funciones que necesitas implementar en otros archivos @@ -75,7 +75,8 @@ auto Resource::get() -> Resource * { return Resource::instance; } // Constructor con modo de carga Resource::Resource(LoadingMode mode) - : loading_mode_(mode), loading_text_(nullptr) { + : loading_mode_(mode), + loading_text_(nullptr) { if (loading_mode_ == LoadingMode::PRELOAD) { loading_text_ = Screen::get()->getText(); load(); @@ -649,7 +650,8 @@ void Resource::createTextTextures() { std::string text; NameAndText(std::string name_init, std::string text_init) - : name(std::move(name_init)), text(std::move(text_init)) {} + : name(std::move(name_init)), + text(std::move(text_init)) {} }; SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXTURES"); @@ -694,7 +696,10 @@ void Resource::createText() { std::string white_texture_file; // Textura blanca opcional ResourceInfo(std::string k, std::string t_file, std::string txt_file, std::string w_file = "") - : key(std::move(k)), texture_file(std::move(t_file)), text_file(std::move(txt_file)), white_texture_file(std::move(w_file)) {} + : key(std::move(k)), + texture_file(std::move(t_file)), + text_file(std::move(txt_file)), + white_texture_file(std::move(w_file)) {} }; SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXT OBJECTS"); @@ -704,7 +709,7 @@ void Resource::createText() { {"04b_25_enhanced", "04b_25.png", "04b_25.txt", "04b_25_white.png"}, // Nueva fuente con textura blanca {"04b_25_white", "04b_25_white.png", "04b_25.txt"}, {"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"}, - {"04b_25_2x_enhanced", "04b_25_2x.png", "04b_25_2x.txt", "04b_25_2x_white.png"},// Nueva fuente con textura blanca + {"04b_25_2x_enhanced", "04b_25_2x.png", "04b_25_2x.txt", "04b_25_2x_white.png"}, // Nueva fuente con textura blanca {"04b_25_metal", "04b_25_metal.png", "04b_25.txt"}, {"04b_25_grey", "04b_25_grey.png", "04b_25.txt"}, {"04b_25_flat", "04b_25_flat.png", "04b_25.txt"}, @@ -866,13 +871,13 @@ void Resource::updateProgressBar() { // Limpia archivos temporales de audio void Resource::cleanupTempAudioFiles() { - for (const auto& temp_path : temp_audio_files_) { + for (const auto &temp_path : temp_audio_files_) { try { if (std::filesystem::exists(temp_path)) { std::filesystem::remove(temp_path); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Removed temp audio file: %s", temp_path.c_str()); } - } catch (const std::exception& e) { + } catch (const std::exception &e) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to remove temp audio file %s: %s", temp_path.c_str(), e.what()); } } diff --git a/source/resource.h b/source/resource.h index f08291f..df3bb73 100644 --- a/source/resource.h +++ b/source/resource.h @@ -52,7 +52,8 @@ class Resource { JA_Sound_t *sound; // Objeto con el sonido ResourceSound(std::string name, JA_Sound_t *sound = nullptr) - : name(std::move(name)), sound(sound) {} + : name(std::move(name)), + sound(sound) {} }; struct ResourceMusic { @@ -60,7 +61,8 @@ class Resource { JA_Music_t *music; // Objeto con la música ResourceMusic(std::string name, JA_Music_t *music = nullptr) - : name(std::move(name)), music(music) {} + : name(std::move(name)), + music(music) {} }; struct ResourceTexture { @@ -68,7 +70,8 @@ class Resource { std::shared_ptr texture; // Objeto con la textura ResourceTexture(std::string name, std::shared_ptr texture = nullptr) - : name(std::move(name)), texture(std::move(texture)) {} + : name(std::move(name)), + texture(std::move(texture)) {} }; struct ResourceTextFile { @@ -76,7 +79,8 @@ class Resource { std::shared_ptr text_file; // Objeto con los descriptores de la fuente de texto ResourceTextFile(std::string name, std::shared_ptr text_file = nullptr) - : name(std::move(name)), text_file(std::move(text_file)) {} + : name(std::move(name)), + text_file(std::move(text_file)) {} }; struct ResourceText { @@ -84,7 +88,8 @@ class Resource { std::shared_ptr text; // Objeto de texto ResourceText(std::string name, std::shared_ptr text = nullptr) - : name(std::move(name)), text(std::move(text)) {} + : name(std::move(name)), + text(std::move(text)) {} }; struct ResourceAnimation { @@ -92,7 +97,8 @@ class Resource { AnimationsFileBuffer animation; // Objeto con las animaciones ResourceAnimation(std::string name, AnimationsFileBuffer animation = {}) - : name(std::move(name)), animation(std::move(animation)) {} + : name(std::move(name)), + animation(std::move(animation)) {} }; // --- Estructura para el progreso de carga --- @@ -100,8 +106,12 @@ class Resource { size_t total; // Número total de recursos size_t loaded; // Número de recursos cargados - ResourceCount() : total(0), loaded(0) {} - ResourceCount(size_t total) : total(total), loaded(0) {} + ResourceCount() + : total(0), + loaded(0) {} + ResourceCount(size_t total) + : total(total), + loaded(0) {} void add(size_t amount) { loaded += amount; } void increase() { loaded++; } @@ -128,7 +138,7 @@ class Resource { std::string loading_resource_name_; // Nombre del recurso que se está cargando SDL_FRect loading_wired_rect_; SDL_FRect loading_full_rect_; - + // --- Archivos temporales --- std::vector temp_audio_files_; // Rutas de archivos temporales de audio para limpieza diff --git a/source/resource_helper.cpp b/source/resource_helper.cpp index 82af104..62e42a1 100644 --- a/source/resource_helper.cpp +++ b/source/resource_helper.cpp @@ -1,95 +1,96 @@ #include "resource_helper.h" + +#include #include #include #include -#include namespace ResourceHelper { - static bool resource_system_initialized = false; - - bool initializeResourceSystem(const std::string& pack_file) { +static bool resource_system_initialized = false; + +bool initializeResourceSystem(const std::string& pack_file) { + auto& loader = ResourceLoader::getInstance(); + resource_system_initialized = loader.initialize(pack_file, true); + + if (resource_system_initialized) { + std::cout << "Resource system initialized with pack: " << pack_file << std::endl; + } else { + std::cout << "Resource system using fallback mode (filesystem only)" << std::endl; + } + + return true; // Always return true as fallback is acceptable +} + +void shutdownResourceSystem() { + if (resource_system_initialized) { + ResourceLoader::getInstance().shutdown(); + resource_system_initialized = false; + } +} + +std::vector loadFile(const std::string& filepath) { + if (resource_system_initialized && shouldUseResourcePack(filepath)) { auto& loader = ResourceLoader::getInstance(); - resource_system_initialized = loader.initialize(pack_file, true); - - if (resource_system_initialized) { - std::cout << "Resource system initialized with pack: " << pack_file << std::endl; - } else { - std::cout << "Resource system using fallback mode (filesystem only)" << std::endl; - } - - return true; // Always return true as fallback is acceptable - } - - void shutdownResourceSystem() { - if (resource_system_initialized) { - ResourceLoader::getInstance().shutdown(); - resource_system_initialized = false; + std::string pack_path = getPackPath(filepath); + + auto data = loader.loadResource(pack_path); + if (!data.empty()) { + return data; } } - - std::vector loadFile(const std::string& filepath) { - if (resource_system_initialized && shouldUseResourcePack(filepath)) { - auto& loader = ResourceLoader::getInstance(); - std::string pack_path = getPackPath(filepath); - - auto data = loader.loadResource(pack_path); - if (!data.empty()) { - return data; - } - } - - // Fallback a filesystem - std::ifstream file(filepath, std::ios::binary | std::ios::ate); - if (!file) { - return {}; - } - - std::streamsize fileSize = file.tellg(); - file.seekg(0, std::ios::beg); - - std::vector data(fileSize); - if (!file.read(reinterpret_cast(data.data()), fileSize)) { - return {}; - } - - return data; + + // Fallback a filesystem + std::ifstream file(filepath, std::ios::binary | std::ios::ate); + if (!file) { + return {}; } - - bool shouldUseResourcePack(const std::string& filepath) { - // Archivos que NO van al pack: - // - config/ (ahora está fuera de data/) - // - archivos absolutos del sistema - - if (filepath.find("config/") != std::string::npos) { - return false; - } - - // Si contiene "data/" es candidato para el pack - if (filepath.find("data/") != std::string::npos) { - return true; - } - + + std::streamsize fileSize = file.tellg(); + file.seekg(0, std::ios::beg); + + std::vector data(fileSize); + if (!file.read(reinterpret_cast(data.data()), fileSize)) { + return {}; + } + + return data; +} + +bool shouldUseResourcePack(const std::string& filepath) { + // Archivos que NO van al pack: + // - config/ (ahora está fuera de data/) + // - archivos absolutos del sistema + + if (filepath.find("config/") != std::string::npos) { return false; } - - std::string getPackPath(const std::string& asset_path) { - std::string pack_path = asset_path; - - // Normalizar separadores de path a '/' - std::replace(pack_path.begin(), pack_path.end(), '\\', '/'); - - // Remover prefijo "data/" si existe - size_t data_pos = pack_path.find("data/"); - if (data_pos != std::string::npos) { - pack_path = pack_path.substr(data_pos + 5); // +5 para saltar "data/" - } - - // Remover cualquier prefijo de path absoluto - size_t last_data = pack_path.rfind("data/"); - if (last_data != std::string::npos) { - pack_path = pack_path.substr(last_data + 5); - } - - return pack_path; + + // Si contiene "data/" es candidato para el pack + if (filepath.find("data/") != std::string::npos) { + return true; } -} \ No newline at end of file + + return false; +} + +std::string getPackPath(const std::string& asset_path) { + std::string pack_path = asset_path; + + // Normalizar separadores de path a '/' + std::replace(pack_path.begin(), pack_path.end(), '\\', '/'); + + // Remover prefijo "data/" si existe + size_t data_pos = pack_path.find("data/"); + if (data_pos != std::string::npos) { + pack_path = pack_path.substr(data_pos + 5); // +5 para saltar "data/" + } + + // Remover cualquier prefijo de path absoluto + size_t last_data = pack_path.rfind("data/"); + if (last_data != std::string::npos) { + pack_path = pack_path.substr(last_data + 5); + } + + return pack_path; +} +} // namespace ResourceHelper \ No newline at end of file diff --git a/source/resource_helper.h b/source/resource_helper.h index 08ff5ac..ee07c31 100644 --- a/source/resource_helper.h +++ b/source/resource_helper.h @@ -1,46 +1,47 @@ #pragma once -#include "resource_loader.h" -#include -#include -#include #include #include +#include +#include +#include + +#include "resource_loader.h" // Helper functions para integrar ResourceLoader con el sistema existente namespace ResourceHelper { - // Inicializa ResourceLoader (llamar al inicio del programa) - bool initializeResourceSystem(const std::string& pack_file = "resources.pack"); - - // Cierra ResourceLoader - void shutdownResourceSystem(); - - // Carga un archivo usando ResourceLoader o fallback a filesystem - std::vector loadFile(const std::string& filepath); - - // Verifica si un archivo debería cargarse del pack vs filesystem - bool shouldUseResourcePack(const std::string& filepath); - - // Convierte ruta Asset a ruta relativa para ResourceLoader - std::string getPackPath(const std::string& asset_path); - - // Wrappea la carga de archivos para mantener compatibilidad - template - T* loadResourceFile(const std::string& asset_path, T* (*loader_func)(const char*)) { - auto data = loadFile(asset_path); - if (data.empty()) { - return loader_func(asset_path.c_str()); - } - - // Crear archivo temporal para funciones que esperan path - std::string temp_path = "/tmp/ccae_" + std::to_string(std::hash{}(asset_path)); - std::ofstream temp_file(temp_path, std::ios::binary); - temp_file.write(reinterpret_cast(data.data()), data.size()); - temp_file.close(); - - T* result = loader_func(temp_path.c_str()); - std::filesystem::remove(temp_path); - - return result; +// Inicializa ResourceLoader (llamar al inicio del programa) +bool initializeResourceSystem(const std::string& pack_file = "resources.pack"); + +// Cierra ResourceLoader +void shutdownResourceSystem(); + +// Carga un archivo usando ResourceLoader o fallback a filesystem +std::vector loadFile(const std::string& filepath); + +// Verifica si un archivo debería cargarse del pack vs filesystem +bool shouldUseResourcePack(const std::string& filepath); + +// Convierte ruta Asset a ruta relativa para ResourceLoader +std::string getPackPath(const std::string& asset_path); + +// Wrappea la carga de archivos para mantener compatibilidad +template +T* loadResourceFile(const std::string& asset_path, T* (*loader_func)(const char*)) { + auto data = loadFile(asset_path); + if (data.empty()) { + return loader_func(asset_path.c_str()); } -} \ No newline at end of file + + // Crear archivo temporal para funciones que esperan path + std::string temp_path = "/tmp/ccae_" + std::to_string(std::hash{}(asset_path)); + std::ofstream temp_file(temp_path, std::ios::binary); + temp_file.write(reinterpret_cast(data.data()), data.size()); + temp_file.close(); + + T* result = loader_func(temp_path.c_str()); + std::filesystem::remove(temp_path); + + return result; +} +} // namespace ResourceHelper \ No newline at end of file diff --git a/source/resource_loader.cpp b/source/resource_loader.cpp index c654b34..256c5f0 100644 --- a/source/resource_loader.cpp +++ b/source/resource_loader.cpp @@ -1,13 +1,15 @@ #include "resource_loader.h" + +#include +#include #include #include -#include -#include std::unique_ptr ResourceLoader::instance = nullptr; -ResourceLoader::ResourceLoader() - : resourcePack(nullptr), fallbackToFiles(true) {} +ResourceLoader::ResourceLoader() + : resourcePack(nullptr), + fallbackToFiles(true) {} ResourceLoader& ResourceLoader::getInstance() { if (!instance) { @@ -22,10 +24,10 @@ ResourceLoader::~ResourceLoader() { bool ResourceLoader::initialize(const std::string& packFile, bool enableFallback) { shutdown(); - + fallbackToFiles = enableFallback; packPath = packFile; - + if (std::filesystem::exists(packFile)) { resourcePack = new ResourcePack(); if (resourcePack->loadPack(packFile)) { @@ -38,12 +40,12 @@ bool ResourceLoader::initialize(const std::string& packFile, bool enableFallback std::cerr << "Failed to load resource pack: " << packFile << std::endl; } } - + if (fallbackToFiles) { std::cout << "Using fallback mode: loading resources from data/ directory" << std::endl; return true; } - + std::cerr << "Resource pack not found and fallback disabled: " << packFile << std::endl; return false; } @@ -59,11 +61,11 @@ std::vector ResourceLoader::loadResource(const std::string& filename) { if (resourcePack && resourcePack->hasResource(filename)) { return resourcePack->getResource(filename); } - + if (fallbackToFiles) { return loadFromFile(filename); } - + std::cerr << "Resource not found: " << filename << std::endl; return {}; } @@ -72,33 +74,33 @@ bool ResourceLoader::resourceExists(const std::string& filename) { if (resourcePack && resourcePack->hasResource(filename)) { return true; } - + if (fallbackToFiles) { std::string fullPath = getDataPath(filename); return std::filesystem::exists(fullPath); } - + return false; } std::vector ResourceLoader::loadFromFile(const std::string& filename) { std::string fullPath = getDataPath(filename); - + std::ifstream file(fullPath, std::ios::binary | std::ios::ate); if (!file) { std::cerr << "Error: Could not open file: " << fullPath << std::endl; return {}; } - + std::streamsize fileSize = file.tellg(); file.seekg(0, std::ios::beg); - + std::vector data(fileSize); if (!file.read(reinterpret_cast(data.data()), fileSize)) { std::cerr << "Error: Could not read file: " << fullPath << std::endl; return {}; } - + return data; } @@ -117,7 +119,7 @@ std::vector ResourceLoader::getAvailableResources() const { if (resourcePack) { return resourcePack->getResourceList(); } - + std::vector result; if (fallbackToFiles && std::filesystem::exists("data")) { for (const auto& entry : std::filesystem::recursive_directory_iterator("data")) { @@ -128,6 +130,6 @@ std::vector ResourceLoader::getAvailableResources() const { } } } - + return result; } \ No newline at end of file diff --git a/source/resource_loader.h b/source/resource_loader.h index b12337c..130b27d 100644 --- a/source/resource_loader.h +++ b/source/resource_loader.h @@ -1,37 +1,38 @@ #ifndef RESOURCE_LOADER_H #define RESOURCE_LOADER_H -#include "resource_pack.h" #include +#include "resource_pack.h" + class ResourceLoader { -private: - static std::unique_ptr instance; - ResourcePack* resourcePack; - std::string packPath; - bool fallbackToFiles; + private: + static std::unique_ptr instance; + ResourcePack* resourcePack; + std::string packPath; + bool fallbackToFiles; - ResourceLoader(); + ResourceLoader(); -public: - static ResourceLoader& getInstance(); - ~ResourceLoader(); - - bool initialize(const std::string& packFile, bool enableFallback = true); - void shutdown(); - - std::vector loadResource(const std::string& filename); - bool resourceExists(const std::string& filename); - - void setFallbackToFiles(bool enable) { fallbackToFiles = enable; } - bool getFallbackToFiles() const { return fallbackToFiles; } - - size_t getLoadedResourceCount() const; - std::vector getAvailableResources() const; + public: + static ResourceLoader& getInstance(); + ~ResourceLoader(); -private: - std::vector loadFromFile(const std::string& filename); - std::string getDataPath(const std::string& filename); + bool initialize(const std::string& packFile, bool enableFallback = true); + void shutdown(); + + std::vector loadResource(const std::string& filename); + bool resourceExists(const std::string& filename); + + void setFallbackToFiles(bool enable) { fallbackToFiles = enable; } + bool getFallbackToFiles() const { return fallbackToFiles; } + + size_t getLoadedResourceCount() const; + std::vector getAvailableResources() const; + + private: + std::vector loadFromFile(const std::string& filename); + std::string getDataPath(const std::string& filename); }; #endif \ No newline at end of file diff --git a/source/resource_pack.cpp b/source/resource_pack.cpp index bf7ce69..2beb9e8 100644 --- a/source/resource_pack.cpp +++ b/source/resource_pack.cpp @@ -1,12 +1,14 @@ #include "resource_pack.h" + +#include +#include #include #include -#include -#include const std::string ResourcePack::DEFAULT_ENCRYPT_KEY = "CCAE_RESOURCES_2024"; -ResourcePack::ResourcePack() : loaded(false) {} +ResourcePack::ResourcePack() + : loaded(false) {} ResourcePack::~ResourcePack() { clear(); @@ -22,7 +24,7 @@ uint32_t ResourcePack::calculateChecksum(const std::vector& data) { void ResourcePack::encryptData(std::vector& data, const std::string& key) { if (key.empty()) return; - + for (size_t i = 0; i < data.size(); ++i) { data[i] ^= key[i % key.length()]; } @@ -38,51 +40,51 @@ bool ResourcePack::loadPack(const std::string& packFile) { std::cerr << "Error: Could not open pack file: " << packFile << std::endl; return false; } - + char header[4]; file.read(header, 4); if (std::string(header, 4) != "CCAE") { std::cerr << "Error: Invalid pack file format" << std::endl; return false; } - + uint32_t version; file.read(reinterpret_cast(&version), sizeof(version)); if (version != 1) { std::cerr << "Error: Unsupported pack version: " << version << std::endl; return false; } - + uint32_t resourceCount; file.read(reinterpret_cast(&resourceCount), sizeof(resourceCount)); - + resources.clear(); resources.reserve(resourceCount); - + for (uint32_t i = 0; i < resourceCount; ++i) { uint32_t filenameLength; file.read(reinterpret_cast(&filenameLength), sizeof(filenameLength)); - + std::string filename(filenameLength, '\0'); file.read(&filename[0], filenameLength); - + ResourceEntry entry; entry.filename = filename; file.read(reinterpret_cast(&entry.offset), sizeof(entry.offset)); file.read(reinterpret_cast(&entry.size), sizeof(entry.size)); file.read(reinterpret_cast(&entry.checksum), sizeof(entry.checksum)); - + resources[filename] = entry; } - + uint64_t dataSize; file.read(reinterpret_cast(&dataSize), sizeof(dataSize)); - + data.resize(dataSize); file.read(reinterpret_cast(data.data()), dataSize); - + decryptData(data, DEFAULT_ENCRYPT_KEY); - + loaded = true; return true; } @@ -93,32 +95,32 @@ bool ResourcePack::savePack(const std::string& packFile) { std::cerr << "Error: Could not create pack file: " << packFile << std::endl; return false; } - + file.write("CCAE", 4); - + uint32_t version = 1; file.write(reinterpret_cast(&version), sizeof(version)); - + uint32_t resourceCount = static_cast(resources.size()); file.write(reinterpret_cast(&resourceCount), sizeof(resourceCount)); - + for (const auto& [filename, entry] : resources) { uint32_t filenameLength = static_cast(filename.length()); file.write(reinterpret_cast(&filenameLength), sizeof(filenameLength)); file.write(filename.c_str(), filenameLength); - + file.write(reinterpret_cast(&entry.offset), sizeof(entry.offset)); file.write(reinterpret_cast(&entry.size), sizeof(entry.size)); file.write(reinterpret_cast(&entry.checksum), sizeof(entry.checksum)); } - + std::vector encryptedData = data; encryptData(encryptedData, DEFAULT_ENCRYPT_KEY); - + uint64_t dataSize = encryptedData.size(); file.write(reinterpret_cast(&dataSize), sizeof(dataSize)); file.write(reinterpret_cast(encryptedData.data()), dataSize); - + return true; } @@ -128,25 +130,25 @@ bool ResourcePack::addFile(const std::string& filename, const std::string& filep std::cerr << "Error: Could not open file: " << filepath << std::endl; return false; } - + std::streamsize fileSize = file.tellg(); file.seekg(0, std::ios::beg); - + std::vector fileData(fileSize); if (!file.read(reinterpret_cast(fileData.data()), fileSize)) { std::cerr << "Error: Could not read file: " << filepath << std::endl; return false; } - + ResourceEntry entry; entry.filename = filename; entry.offset = data.size(); entry.size = fileData.size(); entry.checksum = calculateChecksum(fileData); - + data.insert(data.end(), fileData.begin(), fileData.end()); resources[filename] = entry; - + return true; } @@ -155,20 +157,20 @@ bool ResourcePack::addDirectory(const std::string& directory) { std::cerr << "Error: Directory does not exist: " << directory << std::endl; return false; } - + for (const auto& entry : std::filesystem::recursive_directory_iterator(directory)) { if (entry.is_regular_file()) { std::string filepath = entry.path().string(); std::string filename = std::filesystem::relative(entry.path(), directory).string(); - + std::replace(filename.begin(), filename.end(), '\\', '/'); - + if (!addFile(filename, filepath)) { return false; } } } - + return true; } @@ -178,21 +180,21 @@ std::vector ResourcePack::getResource(const std::string& filename) { std::cerr << "Error: Resource not found: " << filename << std::endl; return {}; } - + const ResourceEntry& entry = it->second; if (entry.offset + entry.size > data.size()) { std::cerr << "Error: Invalid resource data: " << filename << std::endl; return {}; } - - std::vector result(data.begin() + entry.offset, - data.begin() + entry.offset + entry.size); - + + std::vector result(data.begin() + entry.offset, + data.begin() + entry.offset + entry.size); + uint32_t checksum = calculateChecksum(result); if (checksum != entry.checksum) { std::cerr << "Warning: Checksum mismatch for resource: " << filename << std::endl; } - + return result; } @@ -213,10 +215,10 @@ size_t ResourcePack::getResourceCount() const { std::vector ResourcePack::getResourceList() const { std::vector result; result.reserve(resources.size()); - + for (const auto& [filename, entry] : resources) { result.push_back(filename); } - + return result; } \ No newline at end of file diff --git a/source/resource_pack.h b/source/resource_pack.h index 5bacc32..a17d35c 100644 --- a/source/resource_pack.h +++ b/source/resource_pack.h @@ -1,46 +1,46 @@ #ifndef RESOURCE_PACK_H #define RESOURCE_PACK_H +#include #include #include #include -#include struct ResourceEntry { - std::string filename; - uint64_t offset; - uint64_t size; - uint32_t checksum; + std::string filename; + uint64_t offset; + uint64_t size; + uint32_t checksum; }; class ResourcePack { -private: - std::unordered_map resources; - std::vector data; - bool loaded; - - uint32_t calculateChecksum(const std::vector& data); - void encryptData(std::vector& data, const std::string& key); - void decryptData(std::vector& data, const std::string& key); + private: + std::unordered_map resources; + std::vector data; + bool loaded; -public: - ResourcePack(); - ~ResourcePack(); - - bool loadPack(const std::string& packFile); - bool savePack(const std::string& packFile); - - bool addFile(const std::string& filename, const std::string& filepath); - bool addDirectory(const std::string& directory); - - std::vector getResource(const std::string& filename); - bool hasResource(const std::string& filename) const; - - void clear(); - size_t getResourceCount() const; - std::vector getResourceList() const; - - static const std::string DEFAULT_ENCRYPT_KEY; + uint32_t calculateChecksum(const std::vector& data); + void encryptData(std::vector& data, const std::string& key); + void decryptData(std::vector& data, const std::string& key); + + public: + ResourcePack(); + ~ResourcePack(); + + bool loadPack(const std::string& packFile); + bool savePack(const std::string& packFile); + + bool addFile(const std::string& filename, const std::string& filepath); + bool addDirectory(const std::string& directory); + + std::vector getResource(const std::string& filename); + bool hasResource(const std::string& filename) const; + + void clear(); + size_t getResourceCount() const; + std::vector getResourceList() const; + + static const std::string DEFAULT_ENCRYPT_KEY; }; #endif \ No newline at end of file diff --git a/source/scoreboard.cpp b/source/scoreboard.cpp index 62b239f..bf74486 100644 --- a/source/scoreboard.cpp +++ b/source/scoreboard.cpp @@ -37,7 +37,11 @@ auto Scoreboard::get() -> Scoreboard * { // Constructor Scoreboard::Scoreboard() - : renderer_(Screen::get()->getRenderer()), game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")), power_meter_sprite_(std::make_unique(game_power_meter_texture_)), text_(Resource::get()->getText("8bithud")), enter_name_text_(Resource::get()->getText("smb2")) { + : renderer_(Screen::get()->getRenderer()), + game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")), + power_meter_sprite_(std::make_unique(game_power_meter_texture_)), + text_(Resource::get()->getText("8bithud")), + enter_name_text_(Resource::get()->getText("smb2")) { // Inicializa variables for (size_t i = 0; i < static_cast(Id::SIZE); ++i) { name_.at(i).clear(); diff --git a/source/screen.h b/source/screen.h index 863a097..71f6dbd 100644 --- a/source/screen.h +++ b/source/screen.h @@ -91,7 +91,11 @@ class Screen { Color color; // Color del flash explicit FlashEffect(bool enabled = false, int length = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF)) - : enabled(enabled), length(length), delay(delay), counter(length), color(color) {} + : enabled(enabled), + length(length), + delay(delay), + counter(length), + color(color) {} void update() { (enabled && counter > 0) ? counter-- : static_cast(enabled = false); } [[nodiscard]] auto isRendarable() const -> bool { return enabled && counter < length - delay; } @@ -109,7 +113,14 @@ class Screen { bool enabled; // Indica si el efecto está activo explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int orig_pos = 0, int orig_width = 800) - : desp(dp), delay(dl), counter(cnt), length(len), remaining(rem), original_pos(orig_pos), original_width(orig_width), enabled(en) {} + : desp(dp), + delay(dl), + counter(cnt), + length(len), + remaining(rem), + original_pos(orig_pos), + original_width(orig_width), + enabled(en) {} // Activa el efecto de sacudida y guarda la posición y tamaño originales void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_length = -1) { diff --git a/source/sections/credits.cpp b/source/sections/credits.cpp index 3c69ce9..900d1c0 100644 --- a/source/sections/credits.cpp +++ b/source/sections/credits.cpp @@ -35,7 +35,12 @@ constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner"; // Constructor Credits::Credits() - : balloon_manager_(std::make_unique(nullptr)), tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::DIAGONAL)), fade_in_(std::make_unique()), fade_out_(std::make_unique()), text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast(param.game.width), static_cast(param.game.height))), canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast(param.game.width), static_cast(param.game.height))) { + : balloon_manager_(std::make_unique(nullptr)), + tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::DIAGONAL)), + fade_in_(std::make_unique()), + fade_out_(std::make_unique()), + text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast(param.game.width), static_cast(param.game.height))), + canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, static_cast(param.game.width), static_cast(param.game.height))) { if (text_texture_ == nullptr) { throw std::runtime_error("Failed to create SDL texture for text."); } diff --git a/source/sections/game.cpp b/source/sections/game.cpp index baaa78f..ac7303f 100644 --- a/source/sections/game.cpp +++ b/source/sections/game.cpp @@ -49,7 +49,18 @@ // Constructor Game::Game(Player::Id player_id, int current_stage, bool demo) - : renderer_(Screen::get()->getRenderer()), screen_(Screen::get()), input_(Input::get()), canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)), pause_manager_(std::make_unique([this](bool is_paused) { onPauseStateChanged(is_paused); })), stage_manager_(std::make_unique()), balloon_manager_(std::make_unique(stage_manager_.get())), background_(std::make_unique(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))), fade_in_(std::make_unique()), fade_out_(std::make_unique()), tabe_(std::make_unique()), hit_(Hit(Resource::get()->getTexture("hit.png"))) { + : renderer_(Screen::get()->getRenderer()), + screen_(Screen::get()), + input_(Input::get()), + canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)), + pause_manager_(std::make_unique([this](bool is_paused) { onPauseStateChanged(is_paused); })), + stage_manager_(std::make_unique()), + balloon_manager_(std::make_unique(stage_manager_.get())), + background_(std::make_unique(stage_manager_->getPowerNeededToReachStage(stage_manager_->getTotalStages() - 1))), + fade_in_(std::make_unique()), + fade_out_(std::make_unique()), + tabe_(std::make_unique()), + hit_(Hit(Resource::get()->getTexture("hit.png"))) { // Pasa variables demo_.enabled = demo; diff --git a/source/sections/game.h b/source/sections/game.h index 158f5ee..afc0f2b 100644 --- a/source/sections/game.h +++ b/source/sections/game.h @@ -254,8 +254,8 @@ class Game { // --- Sistema de globos y enemigos --- void handleBalloonDestruction(std::shared_ptr balloon, const std::shared_ptr &player); // Procesa destrucción de globo - void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe - void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso + void handleTabeHitEffects(); // Gestiona efectos al golpear a Tabe + void checkAndUpdateBalloonSpeed(); // Ajusta velocidad de globos según progreso // --- Gestión de fases y progresión --- void updateStage(); // Verifica y actualiza cambio de fase diff --git a/source/sections/hiscore_table.cpp b/source/sections/hiscore_table.cpp index 04b4628..ee7a2ad 100644 --- a/source/sections/hiscore_table.cpp +++ b/source/sections/hiscore_table.cpp @@ -29,7 +29,14 @@ // Constructor HiScoreTable::HiScoreTable() - : renderer_(Screen::get()->getRenderer()), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), fade_(std::make_unique()), background_(std::make_unique()), ticks_(0), view_area_(SDL_FRect{0, 0, param.game.width, param.game.height}), fade_mode_(Fade::Mode::IN), background_fade_color_(Color(0, 0, 0)) { + : renderer_(Screen::get()->getRenderer()), + backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), + fade_(std::make_unique()), + background_(std::make_unique()), + ticks_(0), + view_area_(SDL_FRect{0, 0, param.game.width, param.game.height}), + fade_mode_(Fade::Mode::IN), + background_fade_color_(Color(0, 0, 0)) { // Inicializa el resto Section::name = Section::Name::HI_SCORE_TABLE; SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); diff --git a/source/sections/instructions.cpp b/source/sections/instructions.cpp index d50ab74..7aeb64c 100644 --- a/source/sections/instructions.cpp +++ b/source/sections/instructions.cpp @@ -26,7 +26,12 @@ // Constructor Instructions::Instructions() - : renderer_(Screen::get()->getRenderer()), texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), text_(Resource::get()->getText("smb2")), tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::STATIC)), fade_(std::make_unique()) { + : renderer_(Screen::get()->getRenderer()), + texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), + backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), + text_(Resource::get()->getText("smb2")), + tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::STATIC)), + fade_(std::make_unique()) { // Configura las texturas SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); diff --git a/source/sections/instructions.h b/source/sections/instructions.h index 15a9078..3fa0692 100644 --- a/source/sections/instructions.h +++ b/source/sections/instructions.h @@ -34,7 +34,9 @@ struct Line { // Almacena información de línea animada // Constructor de Line Line(int y, float x, int direction) - : y(y), x(x), direction(direction) {} + : y(y), + x(x), + direction(direction) {} }; // Clase Instructions diff --git a/source/sections/title.cpp b/source/sections/title.cpp index 0f13386..e43ede2 100644 --- a/source/sections/title.cpp +++ b/source/sections/title.cpp @@ -37,7 +37,13 @@ class Texture; // Constructor Title::Title() - : text_(Resource::get()->getText("smb2_grad")), fade_(std::make_unique()), tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::RANDOM)), game_logo_(std::make_unique(param.game.game_area.center_x, param.title.title_c_c_position)), mini_logo_sprite_(std::make_unique(Resource::get()->getTexture("logo_jailgames_mini.png"))), state_(TitleState::LOGO_ANIMATING), num_controllers_(Input::get()->getNumGamepads()) { + : text_(Resource::get()->getText("smb2_grad")), + fade_(std::make_unique()), + tiled_bg_(std::make_unique(param.game.game_area.rect, TiledBGMode::RANDOM)), + game_logo_(std::make_unique(param.game.game_area.center_x, param.title.title_c_c_position)), + mini_logo_sprite_(std::make_unique(Resource::get()->getTexture("logo_jailgames_mini.png"))), + state_(TitleState::LOGO_ANIMATING), + num_controllers_(Input::get()->getNumGamepads()) { // Configura objetos tiled_bg_->setColor(param.title.bg_color); game_logo_->enable(); diff --git a/source/sprite.h b/source/sprite.h index e3edaa1..1eb7001 100644 --- a/source/sprite.h +++ b/source/sprite.h @@ -55,9 +55,9 @@ class Sprite { [[nodiscard]] auto getTexture() const -> std::shared_ptr { return textures_.at(texture_index_); } void setTexture(std::shared_ptr texture) { textures_.at(texture_index_) = std::move(texture); } void addTexture(const std::shared_ptr& texture) { textures_.push_back(texture); } - auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice - [[nodiscard]] auto getActiveTexture() const -> size_t { return texture_index_; } // Alias para getActiveTextureIndex - [[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas + auto setActiveTexture(size_t index) -> bool; // Cambia la textura activa por índice + [[nodiscard]] auto getActiveTexture() const -> size_t { return texture_index_; } // Alias para getActiveTextureIndex + [[nodiscard]] auto getTextureCount() const -> size_t { return textures_.size(); } // Obtiene el número total de texturas protected: // --- Métodos internos --- diff --git a/source/text.cpp b/source/text.cpp index 9f950f8..5cbbc12 100644 --- a/source/text.cpp +++ b/source/text.cpp @@ -8,12 +8,12 @@ #include // Para runtime_error #include // Para string_view -#include "color.h" // Para Color -#include "screen.h" // Para Screen -#include "sprite.h" // Para Sprite -#include "texture.h" // Para Texture -#include "utils.h" // Para getFileName, printWithDots +#include "color.h" // Para Color #include "resource_helper.h" // Para ResourceHelper +#include "screen.h" // Para Screen +#include "sprite.h" // Para Sprite +#include "texture.h" // Para Texture +#include "utils.h" // Para getFileName, printWithDots // Constructor Text::Text(const std::shared_ptr &texture, const std::string &text_file) { @@ -157,7 +157,7 @@ auto Text::writeToTexture(const std::string &text, int zoom, int kerning, int le auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, Color text_color, Uint8 shadow_distance, Color shadow_color, int length) -> std::shared_ptr { auto *renderer = Screen::get()->getRenderer(); auto texture = std::make_shared(renderer); - + // Calcula las dimensiones considerando los efectos auto base_width = Text::length(text, kerning); auto base_height = box_height_; @@ -165,10 +165,10 @@ auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, C auto height = base_height; auto offset_x = 0; auto offset_y = 0; - + const auto STROKED = ((flags & Text::STROKE) == Text::STROKE); const auto SHADOWED = ((flags & Text::SHADOW) == Text::SHADOW); - + if (STROKED) { // Para stroke, el texto se expande en todas las direcciones por shadow_distance width = base_width + (shadow_distance * 2); @@ -180,7 +180,7 @@ auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, C width = base_width + shadow_distance; height = base_height + shadow_distance; } - + auto *temp = SDL_GetRenderTarget(renderer); texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET); @@ -200,18 +200,18 @@ void Text::writeColored(int x, int y, const std::string &text, Color color, int } // Escribe el texto con colores usando un sprite específico -void Text::writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string &text, Color color, int kerning, int length) { +void Text::writeColoredWithSprite(Sprite *sprite, int x, int y, const std::string &text, Color color, int kerning, int length) { int shift = 0; const std::string_view VISIBLE_TEXT = (length == -1) ? std::string_view(text) : std::string_view(text).substr(0, length); auto *texture = sprite->getTexture().get(); - + // Guarda el alpha original y aplica el nuevo Uint8 original_alpha; SDL_GetTextureAlphaMod(texture->getSDLTexture(), &original_alpha); texture->setAlpha(color.a); texture->setColor(color.r, color.g, color.b); - + sprite->setY(y); for (const auto CH : VISIBLE_TEXT) { const auto INDEX = static_cast(CH); @@ -223,7 +223,7 @@ void Text::writeColoredWithSprite(Sprite* sprite, int x, int y, const std::strin shift += offset_[INDEX].w + kerning; } } - + // Restaura los valores originales texture->setColor(255, 255, 255); texture->setAlpha(255); @@ -233,26 +233,26 @@ void Text::writeColoredWithSprite(Sprite* sprite, int x, int y, const std::strin void Text::writeStrokeWithAlpha(int x, int y, const std::string &text, int kerning, Color stroke_color, Uint8 shadow_distance, int length) { auto *renderer = Screen::get()->getRenderer(); auto *original_target = SDL_GetRenderTarget(renderer); - + // Calcula dimensiones de la textura temporal auto text_width = Text::length(text, kerning); auto text_height = box_height_; auto temp_width = text_width + (shadow_distance * 2); auto temp_height = text_height + (shadow_distance * 2); - + // Crea textura temporal auto temp_texture = std::make_shared(renderer); temp_texture->createBlank(temp_width, temp_height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET); temp_texture->setBlendMode(SDL_BLENDMODE_BLEND); - + // Renderiza el stroke en la textura temporal temp_texture->setAsRenderTarget(renderer); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_RenderClear(renderer); - + // Selecciona el sprite apropiado para el stroke auto *stroke_sprite = white_sprite_ ? white_sprite_.get() : sprite_.get(); - + // Renderiza stroke sin alpha (sólido) en textura temporal Color solid_color = Color(stroke_color.r, stroke_color.g, stroke_color.b, 255); for (int dist = 1; dist <= shadow_distance; ++dist) { @@ -262,10 +262,10 @@ void Text::writeStrokeWithAlpha(int x, int y, const std::string &text, int kerni } } } - + // Restaura render target original SDL_SetRenderTarget(renderer, original_target); - + // Renderiza la textura temporal con el alpha deseado temp_texture->setAlpha(stroke_color.a); temp_texture->render(x - shadow_distance, y - shadow_distance); @@ -378,20 +378,20 @@ auto Text::loadFile(const std::string &file_path) -> std::shared_ptr auto resource_data = ResourceHelper::loadFile(file_path); std::istringstream stream; bool using_resource_data = false; - + if (!resource_data.empty()) { std::string content(resource_data.begin(), resource_data.end()); stream.str(content); using_resource_data = true; } - + // Fallback a archivo directo std::ifstream file; if (!using_resource_data) { file.open(file_path); } - - std::istream& input_stream = using_resource_data ? stream : static_cast(file); + + std::istream &input_stream = using_resource_data ? stream : static_cast(file); if ((using_resource_data && stream.good()) || (!using_resource_data && file.is_open() && file.good())) { std::string buffer; diff --git a/source/text.h b/source/text.h index a3a05be..e2943ef 100644 --- a/source/text.h +++ b/source/text.h @@ -84,7 +84,7 @@ class Text { static auto loadFile(const std::string &file_path) -> std::shared_ptr; // Llena una estructura Text::File desde un fichero // --- Métodos privados --- - void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string &text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico + void writeColoredWithSprite(Sprite *sprite, int x, int y, const std::string &text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico void writeStrokeWithAlpha(int x, int y, const std::string &text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto private: diff --git a/source/texture.cpp b/source/texture.cpp index e685b23..ef49a52 100644 --- a/source/texture.cpp +++ b/source/texture.cpp @@ -12,11 +12,11 @@ #include #include // Para vector -#include "color.h" // Para getFileName, Color, printWithDots -#include "external/gif.h" // Para Gif -#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_alpha -#include "utils.h" +#include "color.h" // Para getFileName, Color, printWithDots +#include "external/gif.h" // Para Gif #include "resource_helper.h" // Para ResourceHelper +#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_alpha +#include "utils.h" // Constructor Texture::Texture(SDL_Renderer *renderer, std::string path) @@ -66,18 +66,18 @@ auto Texture::loadFromFile(const std::string &file_path) -> bool { int height; int orig_format; unsigned char *data = nullptr; - + // Intentar cargar desde ResourceHelper primero auto resource_data = ResourceHelper::loadFile(file_path); if (!resource_data.empty()) { data = stbi_load_from_memory(resource_data.data(), resource_data.size(), &width, &height, &orig_format, req_format); } - + // Fallback a filesystem directo if (data == nullptr) { data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format); } - + if (data == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", getFileName(file_path).c_str()); throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path)); @@ -226,7 +226,7 @@ auto Texture::loadSurface(const std::string &file_path) -> std::shared_ptr buffer; - + // Intentar cargar desde ResourceHelper primero auto resource_data = ResourceHelper::loadFile(file_path); if (!resource_data.empty()) { @@ -305,7 +305,7 @@ auto Texture::loadPaletteFromFile(const std::string &file_path) -> Palette { Palette palette; std::vector buffer; - + // Intentar cargar desde ResourceHelper primero auto resource_data = ResourceHelper::loadFile(file_path); if (!resource_data.empty()) { @@ -328,7 +328,7 @@ auto Texture::loadPaletteFromFile(const std::string &file_path) -> Palette { throw std::runtime_error("Error al leer el fichero: " + file_path); } } - + printWithDots("Palette : ", getFileName(file_path), "[ LOADED ]"); // Usar la nueva función loadPalette, que devuelve un vector @@ -380,13 +380,13 @@ auto Texture::readPalFile(const std::string &file_path) -> Palette { auto resource_data = ResourceHelper::loadFile(file_path); std::istringstream stream; bool using_resource_data = false; - + if (!resource_data.empty()) { std::string content(resource_data.begin(), resource_data.end()); stream.str(content); using_resource_data = true; } - + // Fallback a archivo directo std::ifstream file; if (!using_resource_data) { @@ -395,8 +395,8 @@ auto Texture::readPalFile(const std::string &file_path) -> Palette { throw std::runtime_error("No se pudo abrir el archivo .pal"); } } - - std::istream& input_stream = using_resource_data ? stream : static_cast(file); + + std::istream &input_stream = using_resource_data ? stream : static_cast(file); std::string line; int line_number = 0; diff --git a/source/texture.h b/source/texture.h index b018fb8..a5ccaa5 100644 --- a/source/texture.h +++ b/source/texture.h @@ -21,7 +21,9 @@ struct Surface { // Constructor Surface(Uint16 width, Uint16 height, std::shared_ptr pixels) // NOLINT(modernize-avoid-c-arrays) - : data(std::move(pixels)), w(width), h(height) {} + : data(std::move(pixels)), + w(width), + h(height) {} }; // Clase Texture: gestiona texturas, paletas y renderizado diff --git a/source/ui/menu_option.h b/source/ui/menu_option.h index 289d000..b768d3d 100644 --- a/source/ui/menu_option.h +++ b/source/ui/menu_option.h @@ -23,7 +23,9 @@ class MenuOption { // --- Constructor y destructor --- MenuOption(std::string caption, ServiceMenu::SettingsGroup group, bool hidden = false) - : caption_(std::move(caption)), group_(group), hidden_(hidden) {} + : caption_(std::move(caption)), + group_(group), + hidden_(hidden) {} virtual ~MenuOption() = default; // --- Getters --- @@ -52,7 +54,8 @@ class MenuOption { class BoolOption : public MenuOption { public: BoolOption(const std::string &cap, ServiceMenu::SettingsGroup grp, bool *var) - : MenuOption(cap, grp), linked_variable_(var) {} + : MenuOption(cap, grp), + linked_variable_(var) {} [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; } [[nodiscard]] auto getValueAsString() const -> std::string override { @@ -74,7 +77,11 @@ class BoolOption : public MenuOption { class IntOption : public MenuOption { public: IntOption(const std::string &cap, ServiceMenu::SettingsGroup grp, int *var, int min, int max, int step) - : MenuOption(cap, grp), linked_variable_(var), min_value_(min), max_value_(max), step_value_(step) {} + : MenuOption(cap, grp), + linked_variable_(var), + min_value_(min), + max_value_(max), + step_value_(step) {} [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::ADJUST; } [[nodiscard]] auto getValueAsString() const -> std::string override { return std::to_string(*linked_variable_); } @@ -150,7 +157,8 @@ class ListOption : public MenuOption { class FolderOption : public MenuOption { public: FolderOption(const std::string &cap, ServiceMenu::SettingsGroup grp, ServiceMenu::SettingsGroup target) - : MenuOption(cap, grp), target_group_(target) {} + : MenuOption(cap, grp), + target_group_(target) {} [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; } [[nodiscard]] auto getTargetGroup() const -> ServiceMenu::SettingsGroup override { return target_group_; } @@ -162,7 +170,8 @@ class FolderOption : public MenuOption { class ActionOption : public MenuOption { public: ActionOption(const std::string &cap, ServiceMenu::SettingsGroup grp, std::function action, bool hidden = false) - : MenuOption(cap, grp, hidden), action_(std::move(action)) {} + : MenuOption(cap, grp, hidden), + action_(std::move(action)) {} [[nodiscard]] auto getBehavior() const -> Behavior override { return Behavior::SELECT; } void executeAction() override { @@ -183,7 +192,11 @@ class ActionListOption : public MenuOption { using ActionExecutor = std::function; ActionListOption(const std::string &caption, ServiceMenu::SettingsGroup group, std::vector options, ValueGetter getter, ValueSetter setter, ActionExecutor action_executor, bool hidden = false) - : MenuOption(caption, group, hidden), options_(std::move(options)), value_getter_(std::move(getter)), value_setter_(std::move(setter)), action_executor_(std::move(action_executor)) { + : MenuOption(caption, group, hidden), + options_(std::move(options)), + value_getter_(std::move(getter)), + value_setter_(std::move(setter)), + action_executor_(std::move(action_executor)) { updateCurrentIndex(); } diff --git a/source/ui/menu_renderer.cpp b/source/ui/menu_renderer.cpp index c0670a5..a40f6c2 100644 --- a/source/ui/menu_renderer.cpp +++ b/source/ui/menu_renderer.cpp @@ -44,7 +44,8 @@ void MenuRenderer::ShowHideAnimation::stop() { } MenuRenderer::MenuRenderer(const ServiceMenu *menu_state, std::shared_ptr element_text, std::shared_ptr title_text) - : element_text_(std::move(element_text)), title_text_(std::move(title_text)) { + : element_text_(std::move(element_text)), + title_text_(std::move(title_text)) { initializeMaxSizes(); setPosition(param.game.game_area.center_x, param.game.game_area.center_y, PositionMode::CENTERED); } diff --git a/source/ui/notifier.h b/source/ui/notifier.h index 78dd99d..b8d775d 100644 --- a/source/ui/notifier.h +++ b/source/ui/notifier.h @@ -69,7 +69,9 @@ class Notifier { // Constructor explicit Notification() - : texture(nullptr), sprite(nullptr), rect{0, 0, 0, 0} {} + : texture(nullptr), + sprite(nullptr), + rect{0, 0, 0, 0} {} }; // --- Objetos y punteros --- diff --git a/source/ui/service_menu.cpp b/source/ui/service_menu.cpp index 0c68da3..6b51e89 100644 --- a/source/ui/service_menu.cpp +++ b/source/ui/service_menu.cpp @@ -49,7 +49,6 @@ void ServiceMenu::toggle() { return; } - if (!enabled_) { // Si está cerrado, abrir reset(); Options::gamepad_manager.assignAndLinkGamepads(); diff --git a/source/ui/ui_message.cpp b/source/ui/ui_message.cpp index 34e95ba..1c3ceb0 100644 --- a/source/ui/ui_message.cpp +++ b/source/ui/ui_message.cpp @@ -7,7 +7,9 @@ // Constructor: inicializa el renderizador, el texto y el color del mensaje UIMessage::UIMessage(std::shared_ptr text_renderer, std::string message_text, const Color &color) - : text_renderer_(std::move(text_renderer)), text_(std::move(message_text)), color_(color) {} + : text_renderer_(std::move(text_renderer)), + text_(std::move(message_text)), + color_(color) {} // Muestra el mensaje en la posición base_x, base_y con animación de entrada desde arriba void UIMessage::show() { diff --git a/source/utils.cpp b/source/utils.cpp index 95dc4e1..7398ab6 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -12,7 +12,7 @@ #include // Para runtime_error #include // Para basic_string, allocator, string, operator==, operator+, char_traits -#include "lang.h" // Para getText +#include "lang.h" // Para getText #include "resource_helper.h" // Para ResourceHelper // Variables @@ -325,7 +325,7 @@ auto loadDemoDataFromFile(const std::string &file_path) -> DemoData { DemoData dd; SDL_IOStream *file = nullptr; - + // Intentar cargar desde ResourceHelper primero auto resource_data = ResourceHelper::loadFile(file_path); if (!resource_data.empty()) { @@ -334,7 +334,7 @@ auto loadDemoDataFromFile(const std::string &file_path) -> DemoData { // Fallback a filesystem directo file = SDL_IOFromFile(file_path.c_str(), "r+b"); } - + if (file == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str()); throw std::runtime_error("Fichero no encontrado: " + file_path); diff --git a/source/utils.h b/source/utils.h index d8a1bf1..639a1c6 100644 --- a/source/utils.h +++ b/source/utils.h @@ -22,9 +22,14 @@ struct Overrides { struct Circle { int x, y, r; // Coordenadas y radio - Circle() : x(0), y(0), r(0) {} + Circle() + : x(0), + y(0), + r(0) {} Circle(int x_coord, int y_coord, int radius) - : x(x_coord), y(y_coord), r(radius) {} + : x(x_coord), + y(y_coord), + r(radius) {} }; struct DemoKeys { @@ -36,7 +41,12 @@ struct DemoKeys { Uint8 fire_right; explicit DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0) - : left(l), right(r), no_input(ni), fire(f), fire_left(fl), fire_right(fr) {} + : left(l), + right(r), + no_input(ni), + fire(f), + fire_left(fl), + fire_right(fr) {} }; // --- Tipos --- @@ -49,9 +59,16 @@ struct Demo { DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo std::vector data; // Vector con diferentes sets de datos con los movimientos para la demo - Demo() : enabled(false), recording(false), counter(0) {} + Demo() + : enabled(false), + recording(false), + counter(0) {} Demo(bool e, bool r, int c, const DemoKeys &k, const std::vector &d) - : enabled(e), recording(r), counter(c), keys(k), data(d) {} + : enabled(e), + recording(r), + counter(c), + keys(k), + data(d) {} }; struct Zone {