diff --git a/data/sounds/explosion.wav b/data/sounds/explosion.wav index d86a003..f05e108 100644 Binary files a/data/sounds/explosion.wav and b/data/sounds/explosion.wav differ diff --git a/data/sounds/logo.wav b/data/sounds/logo.wav index 8e5d880..f7dca81 100644 Binary files a/data/sounds/logo.wav and b/data/sounds/logo.wav differ diff --git a/source/core/rendering/sdl_manager.cpp b/source/core/rendering/sdl_manager.cpp index f9bde6c..65d419d 100644 --- a/source/core/rendering/sdl_manager.cpp +++ b/source/core/rendering/sdl_manager.cpp @@ -195,8 +195,7 @@ void SDLManager::calculateMaxZoom() { float max_zoom_unrounded = std::min(max_zoom_width, max_zoom_height); // Round DOWN to nearest 0.1 increment (user preference) - max_zoom_ = std::floor(max_zoom_unrounded / Defaults::Window::ZOOM_INCREMENT) - * Defaults::Window::ZOOM_INCREMENT; + max_zoom_ = std::floor(max_zoom_unrounded / Defaults::Window::ZOOM_INCREMENT) * Defaults::Window::ZOOM_INCREMENT; // Safety clamp max_zoom_ = std::max(max_zoom_, Defaults::Window::MIN_ZOOM); @@ -208,11 +207,10 @@ void SDLManager::calculateMaxZoom() { void SDLManager::applyZoom(float new_zoom) { // Clamp to valid range new_zoom = std::max(Defaults::Window::MIN_ZOOM, - std::min(new_zoom, max_zoom_)); + std::min(new_zoom, max_zoom_)); // Round to nearest 0.1 increment - new_zoom = std::round(new_zoom / Defaults::Window::ZOOM_INCREMENT) - * Defaults::Window::ZOOM_INCREMENT; + new_zoom = std::round(new_zoom / Defaults::Window::ZOOM_INCREMENT) * Defaults::Window::ZOOM_INCREMENT; // No change? if (std::abs(new_zoom - zoom_factor_) < 0.01f) { @@ -339,7 +337,7 @@ bool SDLManager::handleWindowEvent(const SDL_Event& event) { // Calculate zoom from actual size (may not align to 0.1 increments) float new_zoom = static_cast(current_width_) / Defaults::Window::WIDTH; zoom_factor_ = std::max(Defaults::Window::MIN_ZOOM, - std::min(new_zoom, max_zoom_)); + std::min(new_zoom, max_zoom_)); // Update windowed cache (if not in fullscreen) if (!is_fullscreen_) { diff --git a/source/core/rendering/sdl_manager.hpp b/source/core/rendering/sdl_manager.hpp index 7068af3..3cfbd07 100644 --- a/source/core/rendering/sdl_manager.hpp +++ b/source/core/rendering/sdl_manager.hpp @@ -63,10 +63,10 @@ class SDLManager { int max_height_; // [ZOOM SYSTEM] - float zoom_factor_; // Current zoom (0.5x to max_zoom_) - int windowed_width_; // Saved size before fullscreen - int windowed_height_; // Saved size before fullscreen - float max_zoom_; // Maximum zoom (calculated from display) + float zoom_factor_; // Current zoom (0.5x to max_zoom_) + int windowed_width_; // Saved size before fullscreen + int windowed_height_; // Saved size before fullscreen + float max_zoom_; // Maximum zoom (calculated from display) // [NUEVO] Funcions internes void calculateMaxWindowSize(); // Llegir resolució del display diff --git a/source/game/constants.hpp b/source/game/constants.hpp index 42453dc..c87700b 100644 --- a/source/game/constants.hpp +++ b/source/game/constants.hpp @@ -41,8 +41,7 @@ inline void obtenir_limits_zona(float& min_x, float& max_x, float& min_y, float& } // Obtenir límits segurs (compensant radi de l'entitat) -inline void obtenir_limits_zona_segurs(float radi, float& min_x, float& max_x, - float& min_y, float& max_y) { +inline void obtenir_limits_zona_segurs(float radi, float& min_x, float& max_x, float& min_y, float& max_y) { const auto& zona = Defaults::Zones::PLAYAREA; constexpr float MARGE_SEGURETAT = 10.0f; // Safety margin diff --git a/source/game/entities/bala.cpp b/source/game/entities/bala.cpp index f77d594..3a97017 100644 --- a/source/game/entities/bala.cpp +++ b/source/game/entities/bala.cpp @@ -91,7 +91,10 @@ void Bala::mou(float delta_time) { // CORRECCIÓ: Usar límits segurs amb radi de la bala float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::BULLET_RADIUS, - min_x, max_x, min_y, max_y); + min_x, + max_x, + min_y, + max_y); if (centre_.x < min_x || centre_.x > max_x || centre_.y < min_y || centre_.y > max_y) { diff --git a/source/game/entities/enemic.cpp b/source/game/entities/enemic.cpp index 5040f05..efe9e18 100644 --- a/source/game/entities/enemic.cpp +++ b/source/game/entities/enemic.cpp @@ -40,7 +40,10 @@ void Enemic::inicialitzar() { // Calcular rangs segurs amb radi de l'enemic float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::ENEMY_RADIUS, - min_x, max_x, min_y, max_y); + min_x, + max_x, + min_y, + max_y); // Spawn aleatori dins dels límits segurs int range_x = static_cast(max_x - min_x); @@ -102,7 +105,10 @@ void Enemic::mou(float delta_time) { // Obtenir límits segurs compensant el radi de l'enemic float min_x, max_x, min_y, max_y; Constants::obtenir_limits_zona_segurs(Defaults::Entities::ENEMY_RADIUS, - min_x, max_x, min_y, max_y); + min_x, + max_x, + min_y, + max_y); // Lògica Pascal: Actualitza Y si dins, sinó ajusta angle aleatòriament // if (dy>marge_dalt) and (dy= i <=) if (dy >= min_y && dy <= max_y) { diff --git a/source/game/escenes/escena_joc.cpp b/source/game/escenes/escena_joc.cpp index e065a52..f3fe9b3 100644 --- a/source/game/escenes/escena_joc.cpp +++ b/source/game/escenes/escena_joc.cpp @@ -293,11 +293,11 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() { // 2. Crear explosió de fragments debris_manager_.explotar( - enemic.get_forma(), // Forma vectorial del pentàgon - pos_enemic, // Posició central - 0.0f, // Angle (enemic té rotació interna) - 1.0f, // Escala normal - VELOCITAT_EXPLOSIO // 50 px/s (explosió suau) + enemic.get_forma(), // Forma vectorial del pentàgon + pos_enemic, // Posició central + 0.0f, // Angle (enemic té rotació interna) + 1.0f, // Escala normal + VELOCITAT_EXPLOSIO // 50 px/s (explosió suau) ); // 3. Desactivar bala diff --git a/source/game/escenes/escena_joc.hpp b/source/game/escenes/escena_joc.hpp index cad086f..a85c59d 100644 --- a/source/game/escenes/escena_joc.hpp +++ b/source/game/escenes/escena_joc.hpp @@ -50,8 +50,8 @@ class EscenaJoc { // Funcions privades void tocado(); void detectar_col·lisions_bales_enemics(); // Col·lisions bala-enemic - void dibuixar_marges() const; // Dibuixar vores de la zona de joc - void dibuixar_marcador(); // Dibuixar marcador de puntuació + void dibuixar_marges() const; // Dibuixar vores de la zona de joc + void dibuixar_marcador(); // Dibuixar marcador de puntuació }; #endif // ESCENA_JOC_HPP diff --git a/source/game/escenes/escena_logo.cpp b/source/game/escenes/escena_logo.cpp index 1bae040..28d3c5b 100644 --- a/source/game/escenes/escena_logo.cpp +++ b/source/game/escenes/escena_logo.cpp @@ -6,12 +6,14 @@ #include #include #include +#include +#include -#include "../../core/audio/audio.hpp" -#include "../../core/graphics/shape_loader.hpp" -#include "../../core/rendering/shape_renderer.hpp" -#include "../../core/system/gestor_escenes.hpp" -#include "../../core/system/global_events.hpp" +#include "core/audio/audio.hpp" +#include "core/graphics/shape_loader.hpp" +#include "core/rendering/shape_renderer.hpp" +#include "core/system/gestor_escenes.hpp" +#include "core/system/global_events.hpp" // Helper: calcular el progrés individual d'una lletra // en funció del progrés global (efecte seqüencial) @@ -181,6 +183,15 @@ void EscenaLogo::canviar_estat(EstatAnimacio nou_estat) { if (nou_estat == EstatAnimacio::EXPLOSION) { lletra_explosio_index_ = 0; temps_des_ultima_explosio_ = 0.0f; + + // Generar ordre aleatori d'explosions + ordre_explosio_.clear(); + for (size_t i = 0; i < lletres_.size(); i++) { + ordre_explosio_.push_back(i); + } + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(ordre_explosio_.begin(), ordre_explosio_.end(), g); } std::cout << "[EscenaLogo] Canvi a estat: " << static_cast(nou_estat) @@ -198,8 +209,9 @@ void EscenaLogo::actualitzar_explosions(float delta_time) { // Comprovar si és el moment d'explotar la següent lletra if (temps_des_ultima_explosio_ >= DELAY_ENTRE_EXPLOSIONS) { if (lletra_explosio_index_ < lletres_.size()) { - // Explotar lletra actual - const auto& lletra = lletres_[lletra_explosio_index_]; + // Explotar lletra actual (en ordre aleatori) + size_t index_actual = ordre_explosio_[lletra_explosio_index_]; + const auto& lletra = lletres_[index_actual]; debris_manager_->explotar( lletra.forma, // Forma a explotar @@ -335,17 +347,26 @@ void EscenaLogo::dibuixar() { // EXPLOSION: Dibuixar només lletres que encara no han explotat if (estat_actual_ == EstatAnimacio::EXPLOSION) { - for (size_t i = lletra_explosio_index_; i < lletres_.size(); i++) { - const auto& lletra = lletres_[i]; + // Crear conjunt de lletres ja explotades + std::set explotades; + for (size_t i = 0; i < lletra_explosio_index_; i++) { + explotades.insert(ordre_explosio_[i]); + } - Rendering::render_shape( - sdl_.obte_renderer(), - lletra.forma, - lletra.posicio, - 0.0f, - ESCALA_FINAL, - true, - 1.0f); + // Dibuixar només lletres que NO han explotat + for (size_t i = 0; i < lletres_.size(); i++) { + if (explotades.find(i) == explotades.end()) { + const auto& lletra = lletres_[i]; + + Rendering::render_shape( + sdl_.obte_renderer(), + lletra.forma, + lletra.posicio, + 0.0f, + ESCALA_FINAL, + true, + 1.0f); + } } } diff --git a/source/game/escenes/escena_logo.hpp b/source/game/escenes/escena_logo.hpp index 21c0668..40564a8 100644 --- a/source/game/escenes/escena_logo.hpp +++ b/source/game/escenes/escena_logo.hpp @@ -39,8 +39,9 @@ class EscenaLogo { std::unique_ptr debris_manager_; // Seguiment d'explosions seqüencials - size_t lletra_explosio_index_; // Índex de la següent lletra a explotar - float temps_des_ultima_explosio_; // Temps des de l'última explosió + size_t lletra_explosio_index_; // Índex de la següent lletra a explotar + float temps_des_ultima_explosio_; // Temps des de l'última explosió + std::vector ordre_explosio_; // Ordre aleatori d'índexs de lletres // Estructura per a cada lletra del logo struct LetraLogo { @@ -60,15 +61,15 @@ class EscenaLogo { static constexpr float DURACIO_ZOOM = 4.0f; // Duració del zoom (segons) static constexpr float DURACIO_POST_ANIMATION = 3.0f; // Duració POST_ANIMATION (logo complet) static constexpr float DURACIO_POST_EXPLOSION = 3.0f; // Duració POST_EXPLOSION (espera final) - static constexpr float DELAY_ENTRE_EXPLOSIONS = 0.15f; // Temps entre explosions de lletres - static constexpr float VELOCITAT_EXPLOSIO = 80.0f; // Velocitat base fragments (px/s) + static constexpr float DELAY_ENTRE_EXPLOSIONS = 0.1f; // Temps entre explosions de lletres + static constexpr float VELOCITAT_EXPLOSIO = 240.0f; // Velocitat base fragments (px/s) static constexpr float ESCALA_INICIAL = 0.1f; // Escala inicial (10%) static constexpr float ESCALA_FINAL = 0.8f; // Escala final (80%) static constexpr float ESPAI_ENTRE_LLETRES = 10.0f; // Espaiat entre lletres // Constants d'animació seqüencial - static constexpr float THRESHOLD_LETRA = 0.6f; // Umbral per activar següent lletra (0.0-1.0) - static constexpr float ORIGEN_ZOOM_X = Defaults::Game::WIDTH * 0.5f; // Punt inicial X del zoom + static constexpr float THRESHOLD_LETRA = 0.6f; // Umbral per activar següent lletra (0.0-1.0) + static constexpr float ORIGEN_ZOOM_X = Defaults::Game::WIDTH * 0.5f; // Punt inicial X del zoom static constexpr float ORIGEN_ZOOM_Y = Defaults::Game::HEIGHT * 0.4f; // Punt inicial Y del zoom // Mètodes privats diff --git a/source/game/options.cpp b/source/game/options.cpp index 5f4e285..46c4e3c 100644 --- a/source/game/options.cpp +++ b/source/game/options.cpp @@ -94,7 +94,8 @@ static void loadWindowConfigFromYaml(const fkyaml::node& yaml) { try { auto val = win["zoom_factor"].get_value(); window.zoom_factor = (val >= Defaults::Window::MIN_ZOOM && val <= 10.0f) - ? val : Defaults::Window::BASE_ZOOM; + ? val + : Defaults::Window::BASE_ZOOM; } catch (...) { window.zoom_factor = Defaults::Window::BASE_ZOOM; }