#pragma once #include // Para Uint32, SDL_GetTicks, SDL_FRect #include // Para rand #include // Para unique_ptr #include "animated_sprite.hpp" // Para AnimatedSprite // --- Clase Tabe --- class Tabe { public: // --- Enumeraciones para dirección y estado --- enum class Direction : int { TO_THE_LEFT = 0, TO_THE_RIGHT = 1, }; enum class State : int { FLY = 0, HIT = 1, }; // --- Constructores y destructor --- Tabe(); ~Tabe() = default; // --- Métodos principales --- void update(float delta_time); // Actualiza la lógica (time-based) void render(); // Dibuja el objeto void enable(); // Habilita el objeto void setState(State state); // Establece el estado auto tryToGetBonus() -> bool; // Intenta obtener el bonus void pauseTimer(bool value); // Detiene/activa el timer void disableSpawning(); // Deshabilita el spawning permanentemente void enableSpawning(); // Habilita el spawning nuevamente // --- Getters --- auto getCollider() -> SDL_FRect& { return sprite_->getRect(); } // Obtiene el área de colisión [[nodiscard]] auto isEnabled() const -> bool { return enabled_; } // Indica si el objeto está activo private: // --- Constantes --- static constexpr int WIDTH = 32; static constexpr int HEIGHT = 32; // --- Estructura para el temporizador del Tabe --- struct Timer { private: static constexpr Uint32 MINUTES_TO_MILLISECONDS = 60000; // Factor de conversión de minutos a milisegundos public: Uint32 time_until_next_spawn; // Tiempo restante para la próxima aparición Uint32 min_spawn_time; // Tiempo mínimo entre apariciones (en milisegundos) Uint32 max_spawn_time; // Tiempo máximo entre apariciones (en milisegundos) Uint32 current_time; // Tiempo actual Uint32 delta_time; // Diferencia de tiempo desde la última actualización Uint32 last_time; // Tiempo de la última actualización bool is_paused{false}; // Indica si el temporizador está pausado (por pausa de juego) bool spawn_disabled{false}; // Indica si el spawning está deshabilitado permanentemente // Constructor - los parámetros min_time y max_time están en mintos Timer(float min_time, float max_time) : min_spawn_time(static_cast(min_time * MINUTES_TO_MILLISECONDS)), max_spawn_time(static_cast(max_time * MINUTES_TO_MILLISECONDS)), current_time(SDL_GetTicks()) { reset(); } // Restablece el temporizador con un nuevo tiempo hasta la próxima aparición void reset() { Uint32 range = max_spawn_time - min_spawn_time; time_until_next_spawn = min_spawn_time + rand() % (range + 1); last_time = SDL_GetTicks(); } // Actualiza el temporizador, decrementando el tiempo hasta la próxima aparición void update() { current_time = SDL_GetTicks(); // Solo actualizar si no está pausado (ni por juego ni por spawn deshabilitado) if (!is_paused && !spawn_disabled) { delta_time = current_time - last_time; if (time_until_next_spawn > delta_time) { time_until_next_spawn -= delta_time; } else { time_until_next_spawn = 0; } } // Siempre actualizar last_time para evitar saltos de tiempo al despausar last_time = current_time; } // Pausa o reanuda el temporizador void setPaused(bool paused) { if (is_paused != paused) { is_paused = paused; // Al despausar, actualizar last_time para evitar saltos if (!paused) { last_time = SDL_GetTicks(); } } } // Pausa o reanuda el spawning void setSpawnDisabled(bool disabled) { if (spawn_disabled != disabled) { spawn_disabled = disabled; // Al reactivar, actualizar last_time para evitar saltos if (!disabled) { last_time = SDL_GetTicks(); } } } // Indica si el temporizador ha finalizado [[nodiscard]] auto shouldSpawn() const -> bool { return time_until_next_spawn == 0 && !is_paused && !spawn_disabled; } }; // --- Objetos y punteros --- std::unique_ptr sprite_; // Sprite con los gráficos y animaciones // --- Variables de estado --- float x_ = 0; // Posición X float y_ = 0; // Posición Y float speed_ = 0.0F; // Velocidad de movimiento float accel_ = 0.0F; // Aceleración int fly_distance_ = 0; // Distancia de vuelo float waiting_counter_ = 0; // Tiempo que pasa quieto bool enabled_ = false; // Indica si el objeto está activo Direction direction_ = Direction::TO_THE_LEFT; // Dirección actual Direction destiny_ = Direction::TO_THE_LEFT; // Destino State state_ = State::FLY; // Estado actual float hit_counter_ = 0; // Contador para el estado HIT int number_of_hits_ = 0; // Cantidad de disparos recibidos bool has_bonus_ = true; // Indica si aún tiene el bonus para soltar Timer timer_; // Temporizador para gestionar la aparición // --- Métodos internos --- void move(float delta_time); // Mueve el objeto (time-based) void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite void setRandomFlyPath(Direction direction, int length); // Establece un vuelo aleatorio void updateState(float delta_time); // Actualiza el estado (time-based) void updateTimer(); // Actualiza el temporizador void disable(); // Deshabilita el objeto };