Files

150 lines
7.1 KiB
C++

#pragma once
#include <SDL3/SDL.h> // Para Uint32, SDL_GetTicks, SDL_FRect
#include <cstdlib> // Para rand
#include <memory> // Para unique_ptr
#include "animated_sprite.h" // 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 deltaTime); // 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<Uint32>(min_time * MINUTES_TO_MILLISECONDS)),
max_spawn_time(static_cast<Uint32>(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<AnimatedSprite> 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 deltaTime); // 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 deltaTime); // Actualiza el estado (time-based)
void updateTimer(); // Actualiza el temporizador
void disable(); // Deshabilita el objeto
};