#pragma once #include // Para Uint8, Uint16, SDL_FRect, Uint32 #include // Para array #include // Para allocator, shared_ptr, unique_ptr #include // Para basic_string, string #include // Para vector #include "animated_sprite.h" // Para AnimatedSprite #include "utils.h" // Para Circle class Texture; // --- Constantes relacionadas con globos --- constexpr int MAX_BOUNCE = 10; // Cantidad de elementos del vector de deformación constexpr std::array BALLOON_SCORE = {50, 100, 200, 400}; constexpr std::array BALLOON_POWER = {1, 3, 7, 15}; constexpr std::array BALLOON_MENACE = {1, 2, 4, 8}; constexpr std::array BALLOON_SIZE = {10, 16, 26, 48, 49}; const std::array BALLOON_BOUNCING_SOUND = { "bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"}; const std::array BALLOON_POPPING_SOUND = { "balloon1.wav", "balloon2.wav", "balloon3.wav", "balloon4.wav"}; enum class BalloonSize : Uint8 { SIZE1 = 0, SIZE2 = 1, SIZE3 = 2, SIZE4 = 3, }; enum class BalloonType : Uint8 { BALLOON = 0, FLOATER = 1, POWERBALL = 2, }; constexpr float BALLOON_VELX_POSITIVE = 0.7F; constexpr float BALLOON_VELX_NEGATIVE = -0.7F; constexpr int BALLOON_MOVING_ANIMATION = 0; constexpr int BALLOON_POP_ANIMATION = 1; constexpr int BALLOON_BORN_ANIMATION = 2; constexpr std::array BALLOON_SPEED = {0.60F, 0.70F, 0.80F, 0.90F, 1.00F}; constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10; constexpr int POWERBALL_COUNTER = 8; // --- Clase Balloon --- class Balloon { public: // --- Constructores y destructor --- Balloon( float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, std::shared_ptr texture, const std::vector &animation); ~Balloon() = default; // --- Métodos principales --- void alignTo(int x); // Centra el globo en la posición X void render(); // Pinta el globo en la pantalla void move(); // Actualiza la posición y estados del globo void update(); // Actualiza el globo (posición, animación, contadores) void stop(); // Detiene el globo void start(); // Pone el globo en movimiento void pop(bool should_sound = false); // Explota el globo // --- Métodos de color --- void useReverseColor(); // Pone el color alternativo en el globo void useNormalColor(); // Pone el color normal en el globo // --- Getters --- [[nodiscard]] auto getPosX() const -> float { return x_; } [[nodiscard]] auto getPosY() const -> float { return y_; } [[nodiscard]] auto getWidth() const -> int { return w_; } [[nodiscard]] auto getHeight() const -> int { return h_; } [[nodiscard]] auto getSize() const -> BalloonSize { return size_; } [[nodiscard]] auto getType() const -> BalloonType { return type_; } [[nodiscard]] auto getScore() const -> Uint16 { return score_; } 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_; } [[nodiscard]] auto isPowerBall() const -> bool { return type_ == BalloonType::POWERBALL; } [[nodiscard]] auto isInvulnerable() const -> bool { return invulnerable_; } [[nodiscard]] auto isBeingCreated() const -> bool { return being_created_; } [[nodiscard]] auto isEnabled() const -> bool { return enabled_; } [[nodiscard]] auto isUsingReversedColor() const -> bool { return use_reversed_colors_; } [[nodiscard]] auto canBePopped() const -> bool { return !isBeingCreated(); } // --- Setters --- void setVelY(float vel_y) { vy_ = vel_y; } void setSpeed(float speed) { speed_ = speed; } void setInvulnerable(bool value) { invulnerable_ = value; } void setBouncingSound(bool value) { bouncing_sound_enabled_ = value; } void setPoppingSound(bool value) { poping_sound_enabled_ = value; } void setSound(bool value) { sound_enabled_ = value; } 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 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 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 Bouncing() = default; void reset() { counter = 0; horizontal_zoom = 1.0F; verical_zoom = 1.0F; desp_x = 0.0F; desp_y = 0.0F; } } bouncing_; // --- Objetos y punteros --- std::unique_ptr sprite_; // Sprite del objeto globo // --- Variables de estado y físicas --- float x_; // Posición X float y_; // Posición Y float w_; // Ancho float h_; // Alto float vx_; // Velocidad X float vy_; // Velocidad Y float gravity_; // Aceleración en Y float default_vy_; // Velocidad inicial al rebotar float max_vy_; // Máxima velocidad en Y bool being_created_; // Si el globo se está creando bool enabled_ = true; // Si el globo está activo bool invulnerable_; // Si el globo es invulnerable bool stopped_; // Si el globo está parado bool use_reversed_colors_ = false; // Si se usa el color alternativo Circle collider_; // Círculo de colisión Uint16 creation_counter_; // Temporizador de creación Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación Uint16 score_; // Puntos al destruir el globo BalloonType type_; // Tipo de globo BalloonSize size_; // Tamaño de globo Uint8 menace_; // Amenaza que genera el globo Uint32 counter_ = 0; // Contador interno float travel_y_ = 1.0F; // Distancia a recorrer en Y antes de aplicar gravedad float speed_; // Velocidad del globo Uint8 power_; // Poder que alberga el globo SDL_FRect play_area_; // Zona de movimiento del globo std::string bouncing_sound_; // Archivo de sonido al rebotar std::string popping_sound_; // Archivo de sonido al explotar 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 // --- Métodos internos --- void shiftColliders(); // Alinea el círculo de colisión void shiftSprite(); // Alinea el sprite void zoomSprite(); // Establece el nivel de zoom del sprite void enableBounce(); // Activa el efecto de rebote void disableBounce(); // Detiene el efecto de rebote void updateBounce(); // Aplica el efecto de rebote void updateState(); // Actualiza los estados del globo void setAnimation(); // Establece la animación correspondiente void playSound(const std::string &name) const; // Reproduce sonido };