Fase 9c: extraer InitHudAnimator de GameScene
GameScene::dibuixar_marges_animat, dibuixar_marcador_animat,
calcular_posicio_nau_init_hud y calcular_progress_rango (4 funciones,
~135 LOC) salen a Systems::InitHud en
source/game/systems/init_hud_animator.{hpp,cpp}.
Las funciones son puras (sin estado interno propio). API libre en
namespace:
- computeRangeProgress(global, init, end): normalizacion de la
ventana de progreso de un elemento dentro del global 0..1.
- computeShipPosition(progress, final_position): interpola Y desde
fuera de pantalla con ease_out_quad.
- drawBordersAnimated(renderer, progress): efecto pincel en 3 fases.
- drawScoreboardAnimated(text, scoreboard_text, progress): texto
subiendo desde abajo.
GameScene inyecta lo que cada funcion necesita por parametro
(spawn point desde obtenir_punt_spawn, scoreboard desde
buildScoreboard). Sin estado mutable compartido.
GameScene.cpp acumulado tras 9a/9b/9c: 1429 -> 1043 LOC.
Smoke test xvfb OK.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
// init_hud_animator.cpp - Implementación de la animación inicial del HUD
|
||||
|
||||
#include "game/systems/init_hud_animator.hpp"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "core/defaults.hpp"
|
||||
#include "core/math/easing.hpp"
|
||||
#include "core/rendering/line_renderer.hpp"
|
||||
|
||||
namespace Systems::InitHud {
|
||||
|
||||
auto computeRangeProgress(float global_progress,
|
||||
float ratio_init,
|
||||
float ratio_end) -> float {
|
||||
if (ratio_init >= ratio_end) {
|
||||
return (global_progress >= ratio_end) ? 1.0F : 0.0F;
|
||||
}
|
||||
if (global_progress < ratio_init) {
|
||||
return 0.0F;
|
||||
}
|
||||
if (global_progress > ratio_end) {
|
||||
return 1.0F;
|
||||
}
|
||||
return (global_progress - ratio_init) / (ratio_end - ratio_init);
|
||||
}
|
||||
|
||||
auto computeShipPosition(float progress, const Vec2& final_position) -> Vec2 {
|
||||
const float EASED = Easing::ease_out_quad(progress);
|
||||
const SDL_FRect& ZONA = Defaults::Zones::PLAYAREA;
|
||||
// Y inicial: 50 px bajo la zona de juego.
|
||||
const float Y_INI = ZONA.y + ZONA.h + 50.0F;
|
||||
const float Y_ANIM = Y_INI + ((final_position.y - Y_INI) * EASED);
|
||||
return Vec2{.x = final_position.x, .y = Y_ANIM};
|
||||
}
|
||||
|
||||
void drawBordersAnimated(Rendering::Renderer* renderer, float progress) {
|
||||
const SDL_FRect& ZONA = Defaults::Zones::PLAYAREA;
|
||||
const float EASED = Easing::ease_out_quad(progress);
|
||||
|
||||
const int X1 = static_cast<int>(ZONA.x);
|
||||
const int Y1 = static_cast<int>(ZONA.y);
|
||||
const int X2 = static_cast<int>(ZONA.x + ZONA.w);
|
||||
const int Y2 = static_cast<int>(ZONA.y + ZONA.h);
|
||||
const int CX = (X1 + X2) / 2;
|
||||
|
||||
constexpr float PHASE_1_END = 0.33F;
|
||||
constexpr float PHASE_2_END = 0.66F;
|
||||
|
||||
// Fase 1: línea superior crece desde el centro hacia los lados.
|
||||
if (EASED > 0.0F) {
|
||||
const float P = std::min(EASED / PHASE_1_END, 1.0F);
|
||||
const int X_LEFT = static_cast<int>(CX - ((CX - X1) * P));
|
||||
const int X_RIGHT = static_cast<int>(CX + ((X2 - CX) * P));
|
||||
Rendering::linea(renderer, CX, Y1, X_LEFT, Y1);
|
||||
Rendering::linea(renderer, CX, Y1, X_RIGHT, Y1);
|
||||
}
|
||||
|
||||
// Fase 2: laterales bajan.
|
||||
if (EASED > PHASE_1_END) {
|
||||
const float P = std::min((EASED - PHASE_1_END) / (PHASE_2_END - PHASE_1_END), 1.0F);
|
||||
const int Y_BOTTOM = static_cast<int>(Y1 + ((Y2 - Y1) * P));
|
||||
Rendering::linea(renderer, X1, Y1, X1, Y_BOTTOM);
|
||||
Rendering::linea(renderer, X2, Y1, X2, Y_BOTTOM);
|
||||
}
|
||||
|
||||
// Fase 3: línea inferior crece desde los lados hacia el centro.
|
||||
if (EASED > PHASE_2_END) {
|
||||
const float P = (EASED - PHASE_2_END) / (1.0F - PHASE_2_END);
|
||||
const int X_LEFT = static_cast<int>(X1 + ((CX - X1) * P));
|
||||
const int X_RIGHT = static_cast<int>(X2 - ((X2 - CX) * P));
|
||||
Rendering::linea(renderer, X1, Y2, X_LEFT, Y2);
|
||||
Rendering::linea(renderer, X2, Y2, X_RIGHT, Y2);
|
||||
}
|
||||
}
|
||||
|
||||
void drawScoreboardAnimated(Graphics::VectorText& text,
|
||||
const std::string& scoreboard_text,
|
||||
float progress) {
|
||||
const float EASED = Easing::ease_out_quad(progress);
|
||||
|
||||
constexpr float SCALE = 0.85F;
|
||||
constexpr float SPACING = 0.0F;
|
||||
const SDL_FRect& SCOREBOARD = Defaults::Zones::SCOREBOARD;
|
||||
const float CENTRE_X = SCOREBOARD.w / 2.0F;
|
||||
const float Y_FINAL = SCOREBOARD.y + (SCOREBOARD.h / 2.0F);
|
||||
// Posición inicial: fuera de la pantalla por debajo.
|
||||
const auto Y_INI = static_cast<float>(Defaults::Game::HEIGHT);
|
||||
const float Y_ANIM = Y_INI + ((Y_FINAL - Y_INI) * EASED);
|
||||
|
||||
text.renderCentered(scoreboard_text,
|
||||
Vec2{.x = CENTRE_X, .y = Y_ANIM},
|
||||
SCALE, SPACING);
|
||||
}
|
||||
|
||||
} // namespace Systems::InitHud
|
||||
@@ -0,0 +1,49 @@
|
||||
// init_hud_animator.hpp - Animación inicial del HUD del juego
|
||||
// © 2025 Orni Attack
|
||||
//
|
||||
// Cubre la animación INIT_HUD del comienzo de cada partida/stage:
|
||||
// 1. Crecimiento de los marcos del PLAYAREA con efecto pincel en 3 fases.
|
||||
// 2. Marcador subiendo desde abajo.
|
||||
// 3. Naves entrando desde la zona inferior hacia su spawn.
|
||||
//
|
||||
// Todas las funciones son puras (sin estado interno propio). GameScene aporta
|
||||
// el contexto que necesitan: posiciones finales, texto del scoreboard y el
|
||||
// renderer/VectorText. El timing global (progress 0..1) lo gestiona
|
||||
// StageManager.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "core/graphics/vector_text.hpp"
|
||||
#include "core/rendering/render_context.hpp"
|
||||
#include "core/types.hpp"
|
||||
|
||||
namespace Systems::InitHud {
|
||||
|
||||
// Convierte un progreso global 0..1 al sub-progreso de un elemento que solo
|
||||
// se anima en la ventana [ratio_init, ratio_end].
|
||||
// < ratio_init → 0.0 (no empezó)
|
||||
// > ratio_end → 1.0 (terminó)
|
||||
// en rango → interpolación lineal 0..1
|
||||
[[nodiscard]] auto computeRangeProgress(float global_progress,
|
||||
float ratio_init,
|
||||
float ratio_end) -> float;
|
||||
|
||||
// Calcula posición Y animada de una nave durante INIT_HUD. La nave sube
|
||||
// desde 50 px bajo el PLAYAREA hasta `final_position` con easing.
|
||||
[[nodiscard]] auto computeShipPosition(float progress, const Vec2& final_position) -> Vec2;
|
||||
|
||||
// Dibuja los 4 lados del PLAYAREA con efecto pincel en 3 fases:
|
||||
// 0..33% → línea superior crece desde el centro hacia los lados.
|
||||
// 33..66% → líneas verticales bajan por los laterales.
|
||||
// 66..100% → línea inferior crece desde los lados hacia el centro.
|
||||
void drawBordersAnimated(Rendering::Renderer* renderer, float progress);
|
||||
|
||||
// Dibuja el scoreboard centrado, subiendo desde fuera de la pantalla
|
||||
// hasta su posición final con easing.
|
||||
void drawScoreboardAnimated(Graphics::VectorText& text,
|
||||
const std::string& scoreboard_text,
|
||||
float progress);
|
||||
|
||||
} // namespace Systems::InitHud
|
||||
Reference in New Issue
Block a user