diff --git a/source/background.cpp b/source/background.cpp index 372a622..a373feb 100644 --- a/source/background.cpp +++ b/source/background.cpp @@ -13,6 +13,7 @@ #include "screen.h" // Para Screen #include "sprite.h" // Para Sprite #include "texture.h" // Para Texture +#include "utils.h" // Para funciones de easing // Constructor Background::Background(float total_progress_to_complete) @@ -29,6 +30,7 @@ Background::Background(float total_progress_to_complete) total_progress_to_complete_(total_progress_to_complete), progress_per_stage_(total_progress_to_complete_ / STAGES), sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR), + minimum_completed_progress_(total_progress_to_complete_ * MINIMUM_COMPLETED_PROGRESS_PERCENTAGE), rect_(SDL_FRect{0, 0, static_cast(gradients_texture_->getWidth() / 2), static_cast(gradients_texture_->getHeight() / 2)}), src_rect_({.x = 0, .y = 0, .w = 320, .h = 240}), @@ -93,20 +95,21 @@ void Background::initializeSprites() { // Configura las propiedades iniciales de los sprites void Background::initializeSpriteProperties() { - constexpr float TOP_CLOUDS_SPEED = 0.1F; - constexpr float BOTTOM_CLOUDS_SPEED = 0.05F; + // Velocidades iniciales que coinciden con updateCloudsSpeed() cuando progress=0 + constexpr float INITIAL_TOP_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (coincide con CLOUDS_INITIAL_SPEED) + constexpr float INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S = 0.05F * 60.0F / 2.0F; // 1.5 píxeles/segundo (mitad de velocidad) top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); - top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED); + top_clouds_sprite_a_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S); top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); - top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED); + top_clouds_sprite_b_->setVelX(-INITIAL_TOP_CLOUDS_SPEED_PX_PER_S); bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight()); - bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED); + bottom_clouds_sprite_a_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S); bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight()); - bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED); + bottom_clouds_sprite_b_->setVelX(-INITIAL_BOTTOM_CLOUDS_SPEED_PX_PER_S); buildings_sprite_->setY(base_ - buildings_sprite_->getHeight()); grass_sprite_->setY(base_ - grass_sprite_->getHeight()); @@ -129,7 +132,7 @@ void Background::initializeTextures() { void Background::update(float delta_time) { // Actualiza la progresión y calcula transiciones if (!manual_mode_) { - updateProgression(); + updateProgression(delta_time); } // Actualiza el valor de alpha @@ -183,6 +186,12 @@ void Background::setProgress(float absolute_progress) { // Cambia el estado del fondo void Background::setState(State new_state) { + // Si entra en estado completado, inicializar variables de transición + if (new_state == State::COMPLETED && state_ != State::COMPLETED) { + completion_initial_progress_ = progress_; + completion_transition_timer_ = 0.0f; + } + state_ = new_state; } @@ -197,6 +206,10 @@ void Background::reset() { sun_index_ = 0; moon_index_ = 0; + // Resetear variables de transición de completado + completion_transition_timer_ = 0.0f; + completion_initial_progress_ = 0.0f; + // Notifica el cambio si hay callback if (progress_callback_ && progress_ != old_progress) { progress_callback_(progress_); @@ -253,13 +266,24 @@ void Background::setMoonProgression(float progress) { } // Actualiza la progresión y calcula las transiciones -void Background::updateProgression() { - // Si el juego está completado, reduce la progresión gradualmente +void Background::updateProgression(float delta_time) { + // Si el juego está completado, hacer transición suave con easing if (state_ == State::COMPLETED) { - if (progress_ > MINIMUM_COMPLETED_PROGRESS) { - progress_ -= COMPLETED_REDUCTION_RATE; + completion_transition_timer_ += delta_time; + + // Calcular progreso normalizado de la transición (0.0 a 1.0) + float t = std::min(completion_transition_timer_ / COMPLETION_TRANSITION_DURATION_S, 1.0f); + + if (t < 1.0f) { + // Usar easeOutCubic para transición suave (rápido al inicio, lento al final) + float eased_t = easeOutCubic(static_cast(t)); + + // Interpolación desde progreso inicial hasta mínimo + float progress_range = completion_initial_progress_ - minimum_completed_progress_; + progress_ = completion_initial_progress_ - (progress_range * eased_t); } else { - progress_ = MINIMUM_COMPLETED_PROGRESS; + // Transición completada, fijar al valor mínimo + progress_ = minimum_completed_progress_; } } @@ -284,18 +308,19 @@ void Background::updateProgression() { // Actualiza la velocidad de las nubes según el estado y progresión void Background::updateCloudsSpeed() { - // Cálculo de velocidad según progreso - constexpr float CLOUDS_INITIAL_SPEED = 0.05F; - constexpr float CLOUDS_FINAL_SPEED = 2.00F - CLOUDS_INITIAL_SPEED; + // Cálculo de velocidad según progreso (convertido de frame-based a time-based) + constexpr float CLOUDS_INITIAL_SPEED_PX_PER_S = 0.05F * 60.0F; // 3.0 píxeles/segundo (era 0.05 px/frame @ 60fps) + constexpr float CLOUDS_TOTAL_SPEED_PX_PER_S = 2.00F * 60.0F; // 120.0 píxeles/segundo (era 2.00 px/frame @ 60fps) + constexpr float CLOUDS_FINAL_SPEED_RANGE_PX_PER_S = CLOUDS_TOTAL_SPEED_PX_PER_S - CLOUDS_INITIAL_SPEED_PX_PER_S; // 117.0 píxeles/segundo - // Velocidad base según progreso (de -0.05 a -2.00) - float base_clouds_speed = (-CLOUDS_INITIAL_SPEED) + - (-CLOUDS_FINAL_SPEED * (progress_ / total_progress_to_complete_)); + // Velocidad base según progreso (de -3.0 a -120.0 píxeles/segundo, igual que la versión original) + float base_clouds_speed = (-CLOUDS_INITIAL_SPEED_PX_PER_S) + + (-CLOUDS_FINAL_SPEED_RANGE_PX_PER_S * (progress_ / total_progress_to_complete_)); // En estado completado, las nubes se ralentizan gradualmente if (state_ == State::COMPLETED) { - float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) / - (total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS); + float completion_factor = (progress_ - minimum_completed_progress_) / + (total_progress_to_complete_ - minimum_completed_progress_); completion_factor = std::max(0.1F, completion_factor); base_clouds_speed *= completion_factor; } diff --git a/source/background.h b/source/background.h index f2db18d..e9894a5 100644 --- a/source/background.h +++ b/source/background.h @@ -27,13 +27,13 @@ class Background { using ProgressCallback = std::function; // Callback para sincronización // --- Constructor y destructor --- - Background(float total_progress_to_complete = 6100.0F); // Constructor principal - ~Background(); // Destructor + Background(float total_progress_to_complete); // Constructor principal + ~Background(); // Destructor // --- Métodos principales --- - void update(float delta_time); // Actualiza la lógica del objeto - void render(); // Dibuja el objeto - void reset(); // Reinicia la progresión + void update(float delta_time); // Actualiza la lógica del objeto + void render(); // Dibuja el objeto + void reset(); // Reinicia la progresión // --- Configuración --- void setPos(SDL_FRect pos); // Establece la posición del objeto @@ -60,10 +60,10 @@ class Background { private: // --- Constantes --- - static constexpr size_t STAGES = 4; // Número de etapas - static constexpr float COMPLETED_REDUCTION_RATE = 25.0F; // Tasa de reducción completada - static constexpr float MINIMUM_COMPLETED_PROGRESS = 200.0F; // Progreso mínimo completado - static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol + static constexpr size_t STAGES = 4; // Número de etapas + static constexpr float MINIMUM_COMPLETED_PROGRESS_PERCENTAGE = 0.05F; // Porcentaje mínimo completado (10%) + static constexpr float SUN_COMPLETION_FACTOR = 0.5F; // Factor de completado del sol + static constexpr float COMPLETION_TRANSITION_DURATION_S = 3.0F; // Duración de la transición de completado en segundos // --- Objetos y punteros --- SDL_Renderer *renderer_; // Renderizador de la ventana @@ -90,47 +90,52 @@ class Background { const float total_progress_to_complete_; // Progreso total para completar const float progress_per_stage_; // Progreso por etapa const float sun_completion_progress_; // Progreso de completado del sol + const float minimum_completed_progress_; // Progreso mínimo calculado dinámicamente ProgressCallback progress_callback_; // Callback para notificar cambios de progreso // --- Variables de estado --- - std::vector sun_path_; // Recorrido del sol - std::vector moon_path_; // Recorrido de la luna - std::array gradient_rect_; // Fondos degradados - std::array top_clouds_rect_; // Nubes superiores - std::array bottom_clouds_rect_; // Nubes inferiores - SDL_FRect rect_; // Tamaño del objeto - SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla - SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto - Color attenuate_color_; // Color de atenuación - State state_ = State::NORMAL; // Estado actual - float progress_ = 0.0F; // Progresión interna - float clouds_speed_ = 0; // Velocidad de las nubes - float transition_ = 0; // Porcentaje de transición - size_t gradient_number_ = 0; // Índice de fondo degradado - float grass_timer_ = 0.0f; // Timer para animación de hierba (ms) + std::vector sun_path_; // Recorrido del sol + std::vector moon_path_; // Recorrido de la luna + std::array gradient_rect_; // Fondos degradados + std::array top_clouds_rect_; // Nubes superiores + std::array bottom_clouds_rect_; // Nubes inferiores + SDL_FRect rect_; // Tamaño del objeto + SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla + SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto + Color attenuate_color_; // Color de atenuación + State state_ = State::NORMAL; // Estado actual + float progress_ = 0.0F; // Progresión interna + float clouds_speed_ = 0; // Velocidad de las nubes + float transition_ = 0; // Porcentaje de transición + size_t gradient_number_ = 0; // Índice de fondo degradado + float grass_timer_ = 0.0f; // Timer para animación de hierba (ms) static constexpr float GRASS_FRAME_DURATION = 333.34f; // Duración por frame de hierba (20 frames * 16.67ms) - size_t alpha_color_texture_ = 0; // Transparencia de atenuación - size_t previous_alpha_color_texture_ = 0; // Transparencia anterior - size_t sun_index_ = 0; // Índice del recorrido del sol - size_t moon_index_ = 0; // Índice del recorrido de la luna - int base_ = 0; // Posición base del fondo - Uint8 alpha_ = 0; // Transparencia entre fases - bool manual_mode_ = false; // Si está en modo manual + size_t alpha_color_texture_ = 0; // Transparencia de atenuación + size_t previous_alpha_color_texture_ = 0; // Transparencia anterior + size_t sun_index_ = 0; // Índice del recorrido del sol + size_t moon_index_ = 0; // Índice del recorrido de la luna + int base_ = 0; // Posición base del fondo + Uint8 alpha_ = 0; // Transparencia entre fases + bool manual_mode_ = false; // Si está en modo manual + + // --- Variables para transición suave de completado --- + float completion_transition_timer_ = 0.0f; // Timer para la transición de completado + float completion_initial_progress_ = 0.0f; // Progreso inicial al entrar en estado completado // --- Métodos internos --- - void initializePaths(); // Inicializa las rutas del sol y la luna - void initializeRects(); // Inicializa los rectángulos de gradientes y nubes - void initializeSprites(); // Crea los sprites - void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites - void initializeTextures(); // Inicializa las texturas de renderizado - void updateProgression(); // Actualiza la progresión y calcula transiciones - void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado - void renderGradient(); // Dibuja el gradiente de fondo - void renderTopClouds(); // Dibuja las nubes superiores - void renderBottomClouds(); // Dibuja las nubes inferiores - void fillCanvas(); // Compone todos los elementos en la textura - void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación - void updateClouds(float deltaTime); // Actualiza el movimiento de las nubes (time-based) - void createSunPath(); // Precalcula el recorrido del sol - void createMoonPath(); // Precalcula el recorrido de la luna + void initializePaths(); // Inicializa las rutas del sol y la luna + void initializeRects(); // Inicializa los rectángulos de gradientes y nubes + void initializeSprites(); // Crea los sprites + void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites + void initializeTextures(); // Inicializa las texturas de renderizado + void updateProgression(float delta_time); // Actualiza la progresión y calcula transiciones + void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado + void renderGradient(); // Dibuja el gradiente de fondo + void renderTopClouds(); // Dibuja las nubes superiores + void renderBottomClouds(); // Dibuja las nubes inferiores + void fillCanvas(); // Compone todos los elementos en la textura + void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación + void updateClouds(float deltaTime); // Actualiza el movimiento de las nubes (time-based) + void createSunPath(); // Precalcula el recorrido del sol + void createMoonPath(); // Precalcula el recorrido de la luna }; \ No newline at end of file