diff --git a/source/core/defaults.hpp b/source/core/defaults.hpp index 1cc6cd4..bbba5ca 100644 --- a/source/core/defaults.hpp +++ b/source/core/defaults.hpp @@ -102,6 +102,11 @@ constexpr float ROTACIO_MAX = 0.3f; // Rotació màxima (rad/s ~17.2°/ constexpr float TEMPS_VIDA = 2.0f; // Duració màxima (segons) - enemy/bullet debris constexpr float TEMPS_VIDA_NAU = 3.0f; // Ship debris lifetime (matches DEATH_DURATION) constexpr float SHRINK_RATE = 0.5f; // Reducció de mida (factor/s) + +// Herència de velocitat angular (trayectorias curvas) +constexpr float FACTOR_HERENCIA_MIN = 0.7f; // Mínimo 70% del drotacio heredat +constexpr float FACTOR_HERENCIA_MAX = 1.0f; // Màxim 100% del drotacio heredat +constexpr float FRICCIO_ANGULAR = 0.5f; // Desacceleració angular (rad/s²) } // namespace Debris } // namespace Physics diff --git a/source/game/effects/debris.hpp b/source/game/effects/debris.hpp index ab03f84..d31ef30 100644 --- a/source/game/effects/debris.hpp +++ b/source/game/effects/debris.hpp @@ -18,8 +18,9 @@ struct Debris { float acceleracio; // Acceleració negativa (fricció) en px/s² // Rotació - float angle_rotacio; // Angle de rotació acumulat (radians) - float velocitat_rot; // Velocitat de rotació en rad/s + float angle_rotacio; // Angle de rotació acumulat (radians) + float velocitat_rot; // Velocitat de rotació de TRAYECTORIA (rad/s) + float velocitat_rot_visual; // Velocitat de rotació VISUAL del segment (rad/s) // Estat de vida float temps_vida; // Temps transcorregut (segons) diff --git a/source/game/effects/debris_manager.cpp b/source/game/effects/debris_manager.cpp index dd44d02..146c37e 100644 --- a/source/game/effects/debris_manager.cpp +++ b/source/game/effects/debris_manager.cpp @@ -49,7 +49,9 @@ void DebrisManager::explotar(const std::shared_ptr& shape, float escala, float velocitat_base, float brightness, - const Punt& velocitat_objecte) { + const Punt& velocitat_objecte, + float velocitat_angular, + float factor_herencia_visual) { if (!shape || !shape->es_valida()) { return; } @@ -110,16 +112,45 @@ void DebrisManager::explotar(const std::shared_ptr& shape, debris->velocitat.y = direccio.y * speed + velocitat_objecte.y; debris->acceleracio = Defaults::Physics::Debris::ACCELERACIO; - // 6. Rotació lenta aleatòria - debris->velocitat_rot = - Defaults::Physics::Debris::ROTACIO_MIN + - (std::rand() / static_cast(RAND_MAX)) * - (Defaults::Physics::Debris::ROTACIO_MAX - - Defaults::Physics::Debris::ROTACIO_MIN); + // 6. Herència de velocitat angular - // 50% probabilitat de rotació en sentit contrari - if (std::rand() % 2 == 0) { - debris->velocitat_rot = -debris->velocitat_rot; + // 6a. Rotació de TRAYECTORIA (sempre hereda si velocitat_angular > 0) + if (std::abs(velocitat_angular) > 0.01f) { + float factor_herencia = + Defaults::Physics::Debris::FACTOR_HERENCIA_MIN + + (std::rand() / static_cast(RAND_MAX)) * + (Defaults::Physics::Debris::FACTOR_HERENCIA_MAX - + Defaults::Physics::Debris::FACTOR_HERENCIA_MIN); + debris->velocitat_rot = velocitat_angular * factor_herencia; + + float variacio = + (std::rand() / static_cast(RAND_MAX)) * 0.2f - 0.1f; + debris->velocitat_rot *= (1.0f + variacio); + } else { + debris->velocitat_rot = 0.0f; // Nave: sin curvas + } + + // 6b. Rotació VISUAL (proporcional según factor_herencia_visual) + if (factor_herencia_visual > 0.01f && std::abs(velocitat_angular) > 0.01f) { + // Heredar rotación visual con factor proporcional + debris->velocitat_rot_visual = debris->velocitat_rot * factor_herencia_visual; + + // Variació aleatòria petita (±5%) per naturalitat + float variacio_visual = + (std::rand() / static_cast(RAND_MAX)) * 0.1f - 0.05f; + debris->velocitat_rot_visual *= (1.0f + variacio_visual); + } else { + // Rotació visual aleatòria (factor = 0.0 o sin velocidad angular) + debris->velocitat_rot_visual = + Defaults::Physics::Debris::ROTACIO_MIN + + (std::rand() / static_cast(RAND_MAX)) * + (Defaults::Physics::Debris::ROTACIO_MAX - + Defaults::Physics::Debris::ROTACIO_MIN); + + // 50% probabilitat de rotació en sentit contrari + if (std::rand() % 2 == 0) { + debris->velocitat_rot_visual = -debris->velocitat_rot_visual; + } } debris->angle_rotacio = 0.0f; @@ -175,6 +206,35 @@ void DebrisManager::actualitzar(float delta_time) { debris.velocitat.y = 0.0f; } + // 2b. Rotar vector de velocitat (trayectoria curva) + if (std::abs(debris.velocitat_rot) > 0.01f) { + // Calcular angle de rotació aquest frame + float dangle = debris.velocitat_rot * delta_time; + + // Rotar vector de velocitat usant matriu de rotació 2D + float vel_x_old = debris.velocitat.x; + float vel_y_old = debris.velocitat.y; + + float cos_a = std::cos(dangle); + float sin_a = std::sin(dangle); + + debris.velocitat.x = vel_x_old * cos_a - vel_y_old * sin_a; + debris.velocitat.y = vel_x_old * sin_a + vel_y_old * cos_a; + } + + // 2c. Aplicar fricció angular (desacceleració gradual) + if (std::abs(debris.velocitat_rot) > 0.01f) { + float sign = (debris.velocitat_rot > 0) ? 1.0f : -1.0f; + float reduccion = + Defaults::Physics::Debris::FRICCIO_ANGULAR * delta_time; + debris.velocitat_rot -= sign * reduccion; + + // Evitar canvi de signe (no pot passar de CW a CCW) + if ((debris.velocitat_rot > 0) != (sign > 0)) { + debris.velocitat_rot = 0.0f; + } + } + // 3. Calcular centre del segment Punt centre = {(debris.p1.x + debris.p2.x) / 2.0f, (debris.p1.y + debris.p2.y) / 2.0f}; @@ -183,8 +243,8 @@ void DebrisManager::actualitzar(float delta_time) { centre.x += debris.velocitat.x * delta_time; centre.y += debris.velocitat.y * delta_time; - // 5. Actualitzar rotació - debris.angle_rotacio += debris.velocitat_rot * delta_time; + // 5. Actualitzar rotació VISUAL + debris.angle_rotacio += debris.velocitat_rot_visual * delta_time; // 6. Aplicar shrinking (reducció de distància entre punts) float shrink_factor = diff --git a/source/game/effects/debris_manager.hpp b/source/game/effects/debris_manager.hpp index faf09f0..20b1370 100644 --- a/source/game/effects/debris_manager.hpp +++ b/source/game/effects/debris_manager.hpp @@ -27,13 +27,17 @@ class DebrisManager { // - velocitat_base: velocitat inicial dels fragments (px/s) // - brightness: factor de brillantor heretat (0.0-1.0, per defecte 1.0) // - velocitat_objecte: velocitat de l'objecte que explota (px/s, per defecte 0) + // - velocitat_angular: velocitat angular heretada (rad/s, per defecte 0) + // - factor_herencia_visual: factor de herència rotació visual (0.0-1.0, per defecte 0.0) void explotar(const std::shared_ptr& shape, const Punt& centre, float angle, float escala, float velocitat_base, float brightness = 1.0f, - const Punt& velocitat_objecte = {0.0f, 0.0f}); + const Punt& velocitat_objecte = {0.0f, 0.0f}, + float velocitat_angular = 0.0f, + float factor_herencia_visual = 0.0f); // Actualitzar tots els fragments actius void actualitzar(float delta_time); diff --git a/source/game/entities/enemic.hpp b/source/game/entities/enemic.hpp index a17d85a..37ad790 100644 --- a/source/game/entities/enemic.hpp +++ b/source/game/entities/enemic.hpp @@ -50,6 +50,7 @@ class Enemic { const std::shared_ptr& get_forma() const { return forma_; } void destruir() { esta_ = false; } float get_brightness() const { return brightness_; } + float get_drotacio() const { return drotacio_; } Punt get_velocitat_vector() const { return { velocitat_ * std::cos(angle_ - Constants::PI / 2.0f), diff --git a/source/game/escenes/escena_joc.cpp b/source/game/escenes/escena_joc.cpp index 03c9031..c7096fe 100644 --- a/source/game/escenes/escena_joc.cpp +++ b/source/game/escenes/escena_joc.cpp @@ -483,7 +483,9 @@ void EscenaJoc::tocado() { 1.0f, // Normal scale Defaults::Physics::Debris::VELOCITAT_BASE, // 80 px/s nau_.get_brightness(), // Heredar brightness - vel_nau_80 // Heredar 80% velocitat + vel_nau_80, // Heredar 80% velocitat + 0.0f, // Nave: trayectorias rectas (sin drotacio) + 0.0f // Sin herencia visual (rotación aleatoria) ); // Start death timer (non-zero to avoid re-triggering) @@ -546,7 +548,7 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() { constexpr float SUMA_RADIS_QUADRAT = SUMA_RADIS * SUMA_RADIS; // 826.56 // Velocitat d'explosió reduïda per efecte suau - constexpr float VELOCITAT_EXPLOSIO = 50.0f; // px/s (en lloc de 80.0f per defecte) + constexpr float VELOCITAT_EXPLOSIO = 80.0f; // px/s (en lloc de 80.0f per defecte) // Iterar per totes les bales actives for (auto& bala : bales_) { @@ -590,7 +592,9 @@ void EscenaJoc::detectar_col·lisions_bales_enemics() { 1.0f, // Escala normal VELOCITAT_EXPLOSIO, // 50 px/s (explosió suau) enemic.get_brightness(), // Heredar brightness - vel_enemic // Heredar velocitat + vel_enemic, // Heredar velocitat + enemic.get_drotacio(), // Heredar velocitat angular (trayectorias curvas) + 0.0f // Sin herencia visual (rotación aleatoria) ); // 3. Desactivar bala