animacions de INIT_HUD amb control d'inici i final

This commit is contained in:
2025-12-16 09:39:53 +01:00
parent 8b896912b2
commit c959e0e3a0
4 changed files with 139 additions and 46 deletions

View File

@@ -132,9 +132,23 @@ constexpr float LEVEL_COMPLETED_TYPING_RATIO = 0.0f; // 0.0 = sin typewriter (d
// Transición INIT_HUD (animación inicial del HUD)
constexpr float INIT_HUD_DURATION = 3.0f; // Duración total del estado
constexpr float INIT_HUD_RECT_RATIO = 0.67f; // Proporción animación rectángulo
constexpr float INIT_HUD_SCORE_RATIO = 0.83f; // Proporción animación marcador
constexpr float INIT_HUD_SHIP_RATIO = 1.0f; // Proporción animación nave
// Ratios de animación (inicio y fin como porcentajes del tiempo total)
// RECT (rectángulo de marges)
constexpr float INIT_HUD_RECT_RATIO_INIT = 0.33f;
constexpr float INIT_HUD_RECT_RATIO_END = 1.0f;
// SCORE (marcador de puntuación)
constexpr float INIT_HUD_SCORE_RATIO_INIT = 0.17f;
constexpr float INIT_HUD_SCORE_RATIO_END = 1.0f;
// SHIP1 (nave jugador 1)
constexpr float INIT_HUD_SHIP1_RATIO_INIT = 0.0f;
constexpr float INIT_HUD_SHIP1_RATIO_END = 1.0f;
// SHIP2 (nave jugador 2)
constexpr float INIT_HUD_SHIP2_RATIO_INIT = 0.20f;
constexpr float INIT_HUD_SHIP2_RATIO_END = 1.0f;
// Posición inicial de la nave en INIT_HUD (75% de altura de zona de juego)
constexpr float INIT_HUD_SHIP_START_Y_RATIO = 0.75f; // 75% desde el top de PLAYAREA

View File

@@ -12,6 +12,30 @@ inline float ease_out_quad(float t) {
return 1.0f - (1.0f - t) * (1.0f - t);
}
// Ease-in quadratic: empieza lento, acelera
// t = progreso normalizado [0.0 - 1.0]
// retorna valor interpolado [0.0 - 1.0]
inline float ease_in_quad(float t) {
return t * t;
}
// Ease-in-out quadratic: acelera al inicio, desacelera al final
// t = progreso normalizado [0.0 - 1.0]
// retorna valor interpolado [0.0 - 1.0]
inline float ease_in_out_quad(float t) {
return (t < 0.5f)
? 2.0f * t * t
: 1.0f - (-2.0f * t + 2.0f) * (-2.0f * t + 2.0f) / 2.0f;
}
// Ease-out cubic: desaceleración más suave que quadratic
// t = progreso normalizado [0.0 - 1.0]
// retorna valor interpolado [0.0 - 1.0]
inline float ease_out_cubic(float t) {
float t1 = 1.0f - t;
return 1.0f - t1 * t1 * t1;
}
// Interpolación lineal básica (para referencia)
inline float lerp(float start, float end, float t) {
return start + (end - start) * t;

View File

@@ -160,10 +160,10 @@ void EscenaJoc::inicialitzar() {
puntuacio_per_jugador_[1] = 0;
gestor_puntuacio_.reiniciar();
// Set spawn point to center X, 75% Y (legacy, for INIT_HUD animation)
const SDL_FRect& zona = Defaults::Zones::PLAYAREA;
punt_spawn_.x = zona.x + zona.w * 0.5f;
punt_spawn_.y = zona.y + zona.h * Defaults::Game::INIT_HUD_SHIP_START_Y_RATIO;
// DEPRECATED: punt_spawn_ ja no s'usa, es calcula dinàmicament amb obtenir_punt_spawn(player_id)
// const SDL_FRect& zona = Defaults::Zones::PLAYAREA;
// punt_spawn_.x = zona.x + zona.w * 0.5f;
// punt_spawn_.y = zona.y + zona.h * Defaults::Game::INIT_HUD_SHIP_START_Y_RATIO;
// Inicialitzar naus segons configuració (només jugadors actius)
for (uint8_t i = 0; i < 2; i++) {
@@ -318,22 +318,33 @@ void EscenaJoc::actualitzar(float delta_time) {
break;
}
// Calcular progrés de l'animació de la nau
float ship_progress = 1.0f - (stage_manager_->get_timer_transicio() /
// Calcular global progress (0.0 al inicio → 1.0 al final)
float global_progress = 1.0f - (stage_manager_->get_timer_transicio() /
Defaults::Game::INIT_HUD_DURATION);
ship_progress = std::min(1.0f, ship_progress);
global_progress = std::min(1.0f, global_progress);
// Calcular quant ha avançat l'animació de la nau
float ship_anim_progress = ship_progress / Defaults::Game::INIT_HUD_SHIP_RATIO;
ship_anim_progress = std::min(1.0f, ship_anim_progress);
// [NEW] Calcular progress independiente para cada nave
float ship1_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
Defaults::Game::INIT_HUD_SHIP1_RATIO_END
);
// [NOU] Determinar quina nau ha d'animar-se (jugador actiu)
uint8_t ship_to_animate = config_partida_.jugador1_actiu ? 0 : 1;
float ship2_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
Defaults::Game::INIT_HUD_SHIP2_RATIO_END
);
// Actualitzar posició de la nau activa segons animació
if (ship_anim_progress < 1.0f) {
Punt pos_animada = calcular_posicio_nau_init_hud(ship_anim_progress);
naus_[ship_to_animate].set_centre(pos_animada); // Nau del jugador actiu
// [MODIFICAT] Animar AMBAS naus con sus progress respectivos
if (config_partida_.jugador1_actiu && ship1_progress < 1.0f) {
Punt pos_p1 = calcular_posicio_nau_init_hud(ship1_progress, 0);
naus_[0].set_centre(pos_p1);
}
if (config_partida_.jugador2_actiu && ship2_progress < 1.0f) {
Punt pos_p2 = calcular_posicio_nau_init_hud(ship2_progress, 1);
naus_[1].set_centre(pos_p2);
}
// Una vegada l'animació acaba, permetre control normal
@@ -482,17 +493,30 @@ void EscenaJoc::dibuixar() {
float total_time = Defaults::Game::INIT_HUD_DURATION;
float global_progress = 1.0f - (timer / total_time);
// Progrés del rectangle (empieza inmediatament)
float rect_progress = global_progress / Defaults::Game::INIT_HUD_RECT_RATIO;
rect_progress = std::min(1.0f, rect_progress);
// [NEW] Calcular progress independiente para cada elemento
float rect_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_RECT_RATIO_INIT,
Defaults::Game::INIT_HUD_RECT_RATIO_END
);
// Progrés del marcador (empieza inmediatament)
float score_progress = global_progress / Defaults::Game::INIT_HUD_SCORE_RATIO;
score_progress = std::min(1.0f, score_progress);
float score_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_SCORE_RATIO_INIT,
Defaults::Game::INIT_HUD_SCORE_RATIO_END
);
// Progrés de la nau (empieza inmediatament)
float ship_progress = global_progress / Defaults::Game::INIT_HUD_SHIP_RATIO;
ship_progress = std::min(1.0f, ship_progress);
float ship1_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_SHIP1_RATIO_INIT,
Defaults::Game::INIT_HUD_SHIP1_RATIO_END
);
float ship2_progress = calcular_progress_rango(
global_progress,
Defaults::Game::INIT_HUD_SHIP2_RATIO_INIT,
Defaults::Game::INIT_HUD_SHIP2_RATIO_END
);
// Dibuixar elements animats
if (rect_progress > 0.0f) {
@@ -503,10 +527,13 @@ void EscenaJoc::dibuixar() {
dibuixar_marcador_animat(score_progress);
}
// Dibuixar nau del jugador actiu (posició ja actualitzada en actualitzar())
uint8_t ship_to_draw = config_partida_.jugador1_actiu ? 0 : 1;
if (ship_progress > 0.0f && !naus_[ship_to_draw].esta_tocada()) {
naus_[ship_to_draw].dibuixar();
// [MODIFICAT] Dibuixar naus amb progress independent
if (ship1_progress > 0.0f && config_partida_.jugador1_actiu && !naus_[0].esta_tocada()) {
naus_[0].dibuixar();
}
if (ship2_progress > 0.0f && config_partida_.jugador2_actiu && !naus_[1].esta_tocada()) {
naus_[1].dibuixar();
}
break;
@@ -759,30 +786,55 @@ void EscenaJoc::dibuixar_marcador_animat(float progress) {
text_.render(text, {x_final, y_animada}, escala, spacing);
}
Punt EscenaJoc::calcular_posicio_nau_init_hud(float progress) const {
Punt EscenaJoc::calcular_posicio_nau_init_hud(float progress, uint8_t player_id) const {
// Animació de la nau pujant des de baix amb easing
// [MODIFICAT] Ambas naves usan ease_out_quad (desfase temporal via INIT/END)
// Calcular progrés amb easing
// Aplicar easing (uniforme para ambas naves)
float eased_progress = Easing::ease_out_quad(progress);
const SDL_FRect& zona = Defaults::Zones::PLAYAREA;
// Posició X final (centre de la zona de joc)
float x_final = zona.x + zona.w / 2.0f;
// Calcular posició final segons jugador (reutilitza obtenir_punt_spawn)
Punt spawn_final = obtenir_punt_spawn(player_id);
float x_final = spawn_final.x;
float y_final = spawn_final.y;
// Posició Y final (75% de l'altura de la zona de joc)
float y_final = zona.y + zona.h * Defaults::Game::INIT_HUD_SHIP_START_Y_RATIO;
// Y inicial: offscreen, 50px sota la zona de joc
float y_inicial = zona.y + zona.h + 50.0f;
// Posició Y inicial (offscreen, sota de la zona de joc)
float y_inicial = zona.y + zona.h + 50.0f; // 50px sota
// X no canvia (sempre centrada)
// X no canvia (destí segons player_id)
// Y interpola amb easing
float y_animada = y_inicial + (y_final - y_inicial) * eased_progress;
return {x_final, y_animada};
}
float EscenaJoc::calcular_progress_rango(float global_progress, float ratio_init, float ratio_end) const {
// Convierte global_progress (0.0→1.0) a element_progress usando ventana [INIT, END]
//
// Casos:
// - global_progress < INIT → 0.0 (no ha empezado)
// - global_progress > END → 1.0 (completado)
// - INIT ≤ global_progress ≤ END → interpola linealmente 0.0→1.0
// Validación de parámetros (evita división por cero)
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;
}
// Normalizar rango [INIT, END] a [0.0, 1.0]
return (global_progress - ratio_init) / (ratio_end - ratio_init);
}
std::string EscenaJoc::construir_marcador() const {
// Puntuació P1 (6 dígits) - mostrar zeros si inactiu
std::string score_p1;

View File

@@ -56,7 +56,7 @@ class EscenaJoc {
std::array<int, 2> vides_per_jugador_; // [0]=P1, [1]=P2
bool game_over_; // Game over state flag
float game_over_timer_; // Countdown timer for auto-return (seconds)
Punt punt_spawn_; // Configurable spawn point (legacy)
// Punt punt_spawn_; // DEPRECATED: usar obtenir_punt_spawn(player_id)
Punt punt_mort_; // Death position (for respawn, legacy)
std::array<int, 2> puntuacio_per_jugador_; // [0]=P1, [1]=P2
@@ -82,7 +82,10 @@ class EscenaJoc {
// [NEW] Funcions d'animació per INIT_HUD
void dibuixar_marges_animat(float progress) const; // Rectangle amb creixement uniforme
void dibuixar_marcador_animat(float progress); // Marcador que puja des de baix
Punt calcular_posicio_nau_init_hud(float progress) const; // Posició animada de la nau
Punt calcular_posicio_nau_init_hud(float progress, uint8_t player_id) const; // Posició animada de la nau
// [NEW] Función helper del sistema de animación INIT_HUD
float calcular_progress_rango(float global_progress, float ratio_init, float ratio_end) const;
// [NEW] Funció helper del marcador
std::string construir_marcador() const;