diff --git a/source/core/defaults/game.hpp b/source/core/defaults/game.hpp index 64d86ab..bc85c45 100644 --- a/source/core/defaults/game.hpp +++ b/source/core/defaults/game.hpp @@ -10,9 +10,13 @@ namespace Defaults::Game { constexpr int HEIGHT = 720; // Regles de partida - constexpr int STARTING_LIVES = 3; // Initial lives - constexpr float DEATH_DURATION = 3.0F; // Seconds of death animation - constexpr float GAME_OVER_DURATION = 5.0F; // Seconds to display game over + constexpr int STARTING_LIVES = 3; // Initial lives + constexpr float DEATH_DURATION = 3.0F; // Seconds of death animation + constexpr float GAME_OVER_DURATION = 5.0F; // Seconds to display game over + + // Valores centinela del temporitzador de mort per-jugador. + constexpr float HIT_TIMER_INACTIVE_PLAYER = 999.0F; // Jugador permanentment inactiu + constexpr float HIT_TIMER_TRIGGER_DEATH = 0.001F; // Trigger inicial post-impacte (>0 sense disparar regla) constexpr float COLLISION_SHIP_ENEMY_AMPLIFIER = 0.80F; // 80% hitbox (generous) constexpr float COLLISION_BULLET_ENEMY_AMPLIFIER = 1.15F; // 115% hitbox (generous) diff --git a/source/core/defaults/hud.hpp b/source/core/defaults/hud.hpp index f97843c..072a536 100644 --- a/source/core/defaults/hud.hpp +++ b/source/core/defaults/hud.hpp @@ -10,4 +10,32 @@ namespace Defaults::Hud { constexpr float SCOREBOARD_TEXT_SCALE = 0.85F; constexpr float SCOREBOARD_TEXT_SPACING = 0.0F; + // Animación de entrada del HUD (init_hud_animator). + namespace InitAnim { + // Spawn vertical de la nave: 50 px bajo la PLAYAREA (sale desde fuera). + constexpr float SHIP_SPAWN_Y_OFFSET = 50.0F; + + // Bordes: ratios de las tres fases (top → laterales → bottom). + constexpr float BORDER_PHASE_1_END = 0.33F; // Fin de la fase top + constexpr float BORDER_PHASE_2_END = 0.66F; // Fin de la fase laterales + } // namespace InitAnim + + // Indicadores ("tips") sobre los enemigos enganchados a la nave. + // Offset local al frame de la nave (apunta hacia delante, eje Y negativo). + namespace Tips { + constexpr float LOCAL_X = 0.0F; + constexpr float LOCAL_Y = -12.0F; + } // namespace Tips + + // Overlay de debug (FPS, métriques) en coordenades lògiques (1280×720). + namespace DebugOverlay { + constexpr float X = 12.0F; + constexpr float Y_FPS = 12.0F; + constexpr float LINE_HEIGHT = 18.0F; // separació entre línies (scale 0.4 → ~16 px alt) + constexpr float TEXT_SCALE = 0.4F; + constexpr float TEXT_SPACING = 2.0F; + constexpr float BRIGHTNESS = 1.0F; + constexpr float FPS_UPDATE_INTERVAL = 0.5F; // Cadencia d'actualització del FPS visible + } // namespace DebugOverlay + } // namespace Defaults::Hud diff --git a/source/core/defaults/physics.hpp b/source/core/defaults/physics.hpp index 77704f5..7a204ba 100644 --- a/source/core/defaults/physics.hpp +++ b/source/core/defaults/physics.hpp @@ -26,6 +26,9 @@ namespace Defaults::Physics { constexpr float FACTOR_HERENCIA_MAX = 1.0F; // Màxim 100% del drotacio heredat constexpr float FRICCIO_ANGULAR = 0.5F; // Desacceleració angular (rad/s²) + // Velocity heredada de la nau a l'explosió (80% del feel original). + constexpr float SHIP_VELOCITY_INHERITANCE = 0.8F; + // Angular velocity sin for trajectory inheritance // Excess above this threshold is converted to tangential linear velocity // Prevents "vortex trap" problem with high-rotation enemies diff --git a/source/core/defaults/rendering.hpp b/source/core/defaults/rendering.hpp index 0480516..c87d119 100644 --- a/source/core/defaults/rendering.hpp +++ b/source/core/defaults/rendering.hpp @@ -11,6 +11,10 @@ namespace Defaults::Rendering { constexpr int VSYNC_DEFAULT = 1; // 0=disabled, 1=enabled constexpr int ANTIALIAS_DEFAULT = 1; // 0=disabled, 1=enabled (AA geomètric a les línies) + // Grosor global per defecte de les línies. 1.5 dóna línia visible i crujent; + // 1.0 es veu massa fi en pantalles grans. Configurable via setLineThickness. + constexpr float LINE_THICKNESS_DEFAULT = 1.5F; + // Resolució del render target offscreen. El tamany lògic del joc roman a // 1280×720 (coordenades dels objectes); aquesta és la resolució física a // la qual es rasteritzen les línies abans de la composició final. diff --git a/source/core/rendering/line_renderer.cpp b/source/core/rendering/line_renderer.cpp index 1e27e94..1f079b3 100644 --- a/source/core/rendering/line_renderer.cpp +++ b/source/core/rendering/line_renderer.cpp @@ -3,52 +3,56 @@ #include "core/rendering/line_renderer.hpp" +#include "core/defaults.hpp" + namespace Rendering { -// Color global compartido para líneas sin paleta propia (HUD, debug, texto -// genérico). Equivale al "color máximo" de la antigua oscilación CPU: verde -// fósforo CRT. El pulso de brillo lo aplica ahora el shader de postpro. -SDL_Color g_current_line_color = {100, 255, 100, 255}; + // Color global compartido para líneas sin paleta propia (HUD, debug, texto + // genérico). Equivale al "color máximo" de la antigua oscilación CPU: verde + // fósforo CRT. El pulso de brillo lo aplica ahora el shader de postpro. + SDL_Color g_current_line_color = {100, 255, 100, 255}; -// Grosor global por defecto. Configurable via setLineThickness. -// 1.5 da una línea visible y crujiente; 1.0 se ve demasiado fino en pantallas grandes. -float g_current_line_thickness = 1.5F; + // Grosor global por defecto. Configurable via setLineThickness. + float g_current_line_thickness = Defaults::Rendering::LINE_THICKNESS_DEFAULT; -void linea(Renderer* renderer, - int x1, int y1, int x2, int y2, - float brightness, - float thickness, - SDL_Color color) { - if (renderer == nullptr) { - return; + void linea(Renderer* renderer, + int x1, + int y1, + int x2, + int y2, + float brightness, + float thickness, + SDL_Color color) { + if (renderer == nullptr) { + return; + } + + // Coords lógicas (1280×720). El shader hace el mapeo a NDC; el viewport + // del SDLManager hace el letterbox a píxeles físicos. + const auto FX1 = static_cast(x1); + const auto FY1 = static_cast(y1); + const auto FX2 = static_cast(x2); + const auto FY2 = static_cast(y2); + + // color.alpha==0 → usar color global (verde fósforo). alpha>0 → color directo. + const SDL_Color SOURCE = (color.a > 0) ? color : g_current_line_color; + const float R = (static_cast(SOURCE.r) * brightness) / 255.0F; + const float G = (static_cast(SOURCE.g) * brightness) / 255.0F; + const float B = (static_cast(SOURCE.b) * brightness) / 255.0F; + + const float W = (thickness > 0.0F) ? thickness : g_current_line_thickness; + + renderer->pushLine(FX1, FY1, FX2, FY2, W, R, G, B, 1.0F); } - // Coords lógicas (1280×720). El shader hace el mapeo a NDC; el viewport - // del SDLManager hace el letterbox a píxeles físicos. - const auto FX1 = static_cast(x1); - const auto FY1 = static_cast(y1); - const auto FX2 = static_cast(x2); - const auto FY2 = static_cast(y2); + void setLineColor(SDL_Color color) { g_current_line_color = color; } - // color.alpha==0 → usar color global (verde fósforo). alpha>0 → color directo. - const SDL_Color SOURCE = (color.a > 0) ? color : g_current_line_color; - const float R = (static_cast(SOURCE.r) * brightness) / 255.0F; - const float G = (static_cast(SOURCE.g) * brightness) / 255.0F; - const float B = (static_cast(SOURCE.b) * brightness) / 255.0F; - - const float W = (thickness > 0.0F) ? thickness : g_current_line_thickness; - - renderer->pushLine(FX1, FY1, FX2, FY2, W, R, G, B, 1.0F); -} - -void setLineColor(SDL_Color color) { g_current_line_color = color; } - -void setLineThickness(float thickness) { - if (thickness > 0.0F) { - g_current_line_thickness = thickness; + void setLineThickness(float thickness) { + if (thickness > 0.0F) { + g_current_line_thickness = thickness; + } } -} -auto getLineThickness() -> float { return g_current_line_thickness; } + auto getLineThickness() -> float { return g_current_line_thickness; } } // namespace Rendering diff --git a/source/core/system/debug_overlay.cpp b/source/core/system/debug_overlay.cpp index e8f2577..5434143 100644 --- a/source/core/system/debug_overlay.cpp +++ b/source/core/system/debug_overlay.cpp @@ -4,21 +4,13 @@ #include +#include "core/defaults.hpp" #include "core/types.hpp" namespace System { namespace { - // Posición y tamaño del overlay en coordenadas lógicas (1280×720). - constexpr float OVERLAY_X = 12.0F; - constexpr float OVERLAY_Y_FPS = 12.0F; - constexpr float OVERLAY_LINE_HEIGHT = 18.0F; // separación entre líneas (scale 0.4 → ~16 px alto) - constexpr float OVERLAY_SCALE = 0.4F; - constexpr float OVERLAY_SPACING = 2.0F; - constexpr float OVERLAY_BRIGHTNESS = 1.0F; - - // Cadencia de actualización del valor de FPS mostrado. - constexpr float FPS_UPDATE_INTERVAL = 0.5F; + namespace Cfg = Defaults::Hud::DebugOverlay; } // namespace DebugOverlay::DebugOverlay(Rendering::Renderer* renderer, @@ -30,7 +22,7 @@ namespace System { fps_accumulator_ += delta_time; fps_frame_count_++; - if (fps_accumulator_ >= FPS_UPDATE_INTERVAL) { + if (fps_accumulator_ >= Cfg::FPS_UPDATE_INTERVAL) { fps_display_ = static_cast(fps_frame_count_ / fps_accumulator_); fps_frame_count_ = 0; fps_accumulator_ = 0.0F; @@ -47,20 +39,20 @@ namespace System { const std::string AA_TEXT = std::string("AA: ") + (rendering_cfg_->antialias == 1 ? "ON" : "OFF"); text_.render(FPS_TEXT, - Vec2{.x = OVERLAY_X, .y = OVERLAY_Y_FPS}, - OVERLAY_SCALE, - OVERLAY_SPACING, - OVERLAY_BRIGHTNESS); + Vec2{.x = Cfg::X, .y = Cfg::Y_FPS}, + Cfg::TEXT_SCALE, + Cfg::TEXT_SPACING, + Cfg::BRIGHTNESS); text_.render(VSYNC_TEXT, - Vec2{.x = OVERLAY_X, .y = OVERLAY_Y_FPS + OVERLAY_LINE_HEIGHT}, - OVERLAY_SCALE, - OVERLAY_SPACING, - OVERLAY_BRIGHTNESS); + Vec2{.x = Cfg::X, .y = Cfg::Y_FPS + Cfg::LINE_HEIGHT}, + Cfg::TEXT_SCALE, + Cfg::TEXT_SPACING, + Cfg::BRIGHTNESS); text_.render(AA_TEXT, - Vec2{.x = OVERLAY_X, .y = OVERLAY_Y_FPS + (2.0F * OVERLAY_LINE_HEIGHT)}, - OVERLAY_SCALE, - OVERLAY_SPACING, - OVERLAY_BRIGHTNESS); + Vec2{.x = Cfg::X, .y = Cfg::Y_FPS + (2.0F * Cfg::LINE_HEIGHT)}, + Cfg::TEXT_SCALE, + Cfg::TEXT_SPACING, + Cfg::BRIGHTNESS); } } // namespace System diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 136b833..9bdb281 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -107,8 +107,8 @@ GameScene::GameScene(SDLManager& sdl, SceneContext& context) } else { // Jugador inactiu: marcar como a mort permanent ships_[i].markHit(); - hit_timer_per_player_[i] = 999.0F; // Valor sentinella (permanent inactiu) - lives_per_player_[i] = 0; // Sin vides + hit_timer_per_player_[i] = Defaults::Game::HIT_TIMER_INACTIVE_PLAYER; + lives_per_player_[i] = 0; // Sin vides std::cout << "[GameScene] Jugador " << (i + 1) << " inactiu\n"; } } @@ -628,8 +628,9 @@ void GameScene::tocado(uint8_t player_id) { const Vec2& ship_pos = ships_[player_id].getCenter(); float ship_angle = ships_[player_id].getAngle(); Vec2 vel_nau = ships_[player_id].getVelocityVector(); - // Reduir a 80% la velocity heretada per la ship (més realista) - Vec2 vel_nau_80 = {.x = vel_nau.x * 0.8F, .y = vel_nau.y * 0.8F}; + // Reduir la velocity heretada per la ship segons defaults (més realista) + constexpr float INHERIT = Defaults::Physics::Debris::SHIP_VELOCITY_INHERITANCE; + Vec2 vel_nau_80 = {.x = vel_nau.x * INHERIT, .y = vel_nau.y * INHERIT}; debris_manager_.explode( ships_[player_id].getShape(), // Ship shape (3 lines) @@ -646,7 +647,7 @@ void GameScene::tocado(uint8_t player_id) { ); // Start death timer (non-zero to avoid re-triggering) - hit_timer_per_player_[player_id] = 0.001F; + hit_timer_per_player_[player_id] = Defaults::Game::HIT_TIMER_TRIGGER_DEATH; } // Phase 2 is automatic (debris updates in update()) // Phase 3 is handled in update() when hit_timer_per_player_ >= DEATH_DURATION @@ -828,8 +829,8 @@ void GameScene::fireBullet(uint8_t player_id) { const Vec2& ship_centre = ships_[player_id].getCenter(); float ship_angle = ships_[player_id].getAngle(); - constexpr float LOCAL_TIP_X = 0.0F; - constexpr float LOCAL_TIP_Y = -12.0F; + constexpr float LOCAL_TIP_X = Defaults::Hud::Tips::LOCAL_X; + constexpr float LOCAL_TIP_Y = Defaults::Hud::Tips::LOCAL_Y; float cos_a = std::cos(ship_angle); float sin_a = std::sin(ship_angle); float tip_x = (LOCAL_TIP_X * cos_a) - (LOCAL_TIP_Y * sin_a) + ship_centre.x; diff --git a/source/game/systems/init_hud_animator.cpp b/source/game/systems/init_hud_animator.cpp index 480315a..75e81eb 100644 --- a/source/game/systems/init_hud_animator.cpp +++ b/source/game/systems/init_hud_animator.cpp @@ -31,8 +31,8 @@ namespace Systems::InitHud { auto computeShipPosition(float progress, const Vec2& final_position) -> Vec2 { const float EASED = Easing::easeOutQuad(progress); const SDL_FRect& zone = Defaults::Zones::PLAYAREA; - // Y inicial: 50 px bajo la zona de juego. - const float Y_INI = zone.y + zone.h + 50.0F; + // Y inicial: bajo la zona de juego (sale desde fuera). + const float Y_INI = zone.y + zone.h + Defaults::Hud::InitAnim::SHIP_SPAWN_Y_OFFSET; const float Y_ANIM = Y_INI + ((final_position.y - Y_INI) * EASED); return Vec2{.x = final_position.x, .y = Y_ANIM}; } @@ -47,8 +47,8 @@ namespace Systems::InitHud { const int Y2 = static_cast(zone.y + zone.h); const int CX = (X1 + X2) / 2; - constexpr float PHASE_1_END = 0.33F; - constexpr float PHASE_2_END = 0.66F; + constexpr float PHASE_1_END = Defaults::Hud::InitAnim::BORDER_PHASE_1_END; + constexpr float PHASE_2_END = Defaults::Hud::InitAnim::BORDER_PHASE_2_END; // Fase 1: línea superior crece desde el centro hacia los lados. if (EASED > 0.0F) {