diff --git a/source/balloon.cpp b/source/balloon.cpp index 71c631e..68a2a88 100644 --- a/source/balloon.cpp +++ b/source/balloon.cpp @@ -343,43 +343,16 @@ void Balloon::shiftSprite() { sprite_->setPosY(y_); } -// Aplica la deformación visual causada por el efecto de rebote -void Balloon::applyBounceEffect() { - sprite_->setHorizontalZoom(bounce_effect_.horizontal_zoom); - sprite_->setVerticalZoom(bounce_effect_.verical_zoom); -} - -// Activa el efecto void Balloon::enableBounceEffect() { - // Los globos pequeños no tienen efecto de rebote - if (size_ == Size::SMALL) { - return; - } - bounce_effect_.enabled = true; - bounce_effect_.reset(); - applyBounceEffect(); + bounce_effect_.enable(sprite_.get(), size_); } -// Detiene el efecto void Balloon::disableBounceEffect() { - bounce_effect_.enabled = false; - bounce_effect_.reset(); - applyBounceEffect(); + bounce_effect_.disable(sprite_.get()); } -// Aplica el efecto void Balloon::updateBounceEffect() { - if (bounce_effect_.enabled) { - const int INDEX = bounce_effect_.counter / bounce_effect_.speed; - bounce_effect_.horizontal_zoom = bounce_effect_.horizontal_zoom_values.at(INDEX); - bounce_effect_.verical_zoom = bounce_effect_.vertical_zoom_values.at(INDEX); - - applyBounceEffect(); - - if (++bounce_effect_.counter / bounce_effect_.speed >= MAX_BOUNCE) { - disableBounceEffect(); - } - } + bounce_effect_.update(sprite_.get()); } // Pone el color alternativo en el globo diff --git a/source/balloon.h b/source/balloon.h index 50c2a0f..4f8c38d 100644 --- a/source/balloon.h +++ b/source/balloon.h @@ -61,7 +61,7 @@ class Balloon { Uint16 creation_timer, SDL_FRect play_area, std::shared_ptr texture, - const std::vector &animation); + const std::vector& animation); ~Balloon() = default; // --- Métodos principales --- @@ -85,7 +85,7 @@ class Balloon { [[nodiscard]] auto getSize() const -> Size { return size_; } [[nodiscard]] auto getType() const -> Type { return type_; } [[nodiscard]] auto getScore() const -> Uint16 { return score_; } - auto getCollider() -> Circle & { return collider_; } + auto getCollider() -> Circle& { return collider_; } [[nodiscard]] auto getMenace() const -> Uint8 { return isEnabled() ? menace_ : 0; } [[nodiscard]] auto getPower() const -> Uint8 { return power_; } [[nodiscard]] auto isStopped() const -> bool { return stopped_; } @@ -106,27 +106,96 @@ class Balloon { private: // --- Estructura para el efecto de rebote --- - struct Bouncing { - bool enabled = false; // Si el efecto está activo - Uint8 counter = 0; // Contador para el efecto - Uint8 speed = 2; // Velocidad del efecto + struct BounceEffect { + private: + static constexpr int BOUNCE_FRAMES = 10; // Cantidad de elementos del vector de deformación + + // Tablas de valores predefinidos para el efecto de rebote + static constexpr std::array horizontal_zoom_values = { + 1.10F, 1.05F, 1.00F, 0.95F, 0.90F, 0.95F, 1.00F, 1.02F, 1.05F, 1.02F}; + + static constexpr std::array vertical_zoom_values = { + 0.90F, 0.95F, 1.00F, 1.05F, 1.10F, 1.05F, 1.00F, 0.98F, 0.95F, 0.98F}; + + // Estado del efecto + bool enabled = false; // Si el efecto está activo + Uint8 counter = 0; // Contador para el efecto + Uint8 speed = 2; // Velocidad del efecto + + // Valores actuales de transformación float horizontal_zoom = 1.0F; // Zoom en anchura float verical_zoom = 1.0F; // Zoom en altura - float desp_x = 0.0F; // Desplazamiento X antes de pintar - float desp_y = 0.0F; // Desplazamiento Y antes de pintar + float x_offset = 0.0F; // Desplazamiento X antes de pintar + float y_offset = 0.0F; // Desplazamiento Y antes de pintar - std::array horizontal_zoom_values = {1.10F, 1.05F, 1.00F, 0.95F, 0.90F, 0.95F, 1.00F, 1.02F, 1.05F, 1.02F}; // Zoom ancho - std::array vertical_zoom_values = {0.90F, 0.95F, 1.00F, 1.05F, 1.10F, 1.05F, 1.00F, 0.98F, 0.95F, 0.98F}; // Zoom alto + public: + // Constructor por defecto + BounceEffect() = default; - Bouncing() = default; + // Reinicia el efecto a sus valores iniciales void reset() { counter = 0; horizontal_zoom = 1.0F; verical_zoom = 1.0F; - desp_x = 0.0F; - desp_y = 0.0F; + x_offset = 0.0F; + y_offset = 0.0F; } - } bounce_effect_; + + // Aplica la deformación visual al sprite + void apply(AnimatedSprite* sprite) { + if (sprite) { + sprite->setHorizontalZoom(horizontal_zoom); + sprite->setVerticalZoom(verical_zoom); + } + } + + // Activa el efecto de rebote + void enable(AnimatedSprite* sprite, Size balloon_size) { + // Los globos pequeños no tienen efecto de rebote + if (balloon_size == Size::SMALL) { + return; + } + enabled = true; + reset(); + apply(sprite); + } + + // Detiene el efecto de rebote + void disable(AnimatedSprite* sprite) { + enabled = false; + reset(); + apply(sprite); + } + + // Actualiza el efecto en cada frame + void update(AnimatedSprite* sprite) { + if (!enabled) { + return; + } + + // Calcula el índice basado en el contador y velocidad + const int INDEX = counter / speed; + + // Actualiza los valores de zoom desde las tablas predefinidas + horizontal_zoom = horizontal_zoom_values.at(INDEX); + verical_zoom = vertical_zoom_values.at(INDEX); + + // Aplica la deformación al sprite + apply(sprite); + + // Incrementa el contador y verifica si el efecto debe terminar + if (++counter / speed >= BOUNCE_FRAMES) { + disable(sprite); + } + } + + // Getters para acceso a los valores actuales + bool isEnabled() const { return enabled; } + float getHorizontalZoom() const { return horizontal_zoom; } + float getVerticalZoom() const { return verical_zoom; } + float GetXOffset() const { return x_offset; } + float GetYOffset() const { return y_offset; } + }; // --- Objetos y punteros --- std::unique_ptr sprite_; // Sprite del objeto globo @@ -163,15 +232,15 @@ class Balloon { bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido + BounceEffect bounce_effect_; // Efecto de rebote // --- Posicionamiento y transformación --- - void shiftColliders(); // Alinea el círculo de colisión con el sprite - void shiftSprite(); // Alinea el sprite en pantalla - void applyBounceEffect(); // Aplica la deformación visual causada por el efecto de rebote + void shiftColliders(); // Alinea el círculo de colisión con el sprite + void shiftSprite(); // Alinea el sprite en pantalla // --- Animación y sonido --- void setAnimation(); // Establece la animación correspondiente - void playSound(const std::string &name) const; // Reproduce un sonido por nombre + void playSound(const std::string& name) const; // Reproduce un sonido por nombre void playBouncingSound(); // Reproduce el sonido de rebote // --- Movimiento y física ---