#pragma once #include // Para SDL_FPoint #include // Para function #include // Para shared_ptr #include "moving_sprite.hpp" // Para MovingSprite class Texture; // --- Estados de la tarjeta --- enum class CardState { IDLE, // No activada todavía ENTERING, // Animación de entrada (zoom + rotación + desplazamiento con rebote) LANDED, // En reposo sobre la mesa EXITING, // Saliendo de pantalla girando FINISHED, // Fuera de pantalla }; // --- Clase CardSprite: tarjeta animada con zoom, rotación y sombra integrada --- // // Simula una tarjeta lanzada sobre una mesa desde un borde de la pantalla. // Durante la entrada, interpola posición, zoom y rotación con easing (rebote). // Durante la salida, se desplaza fuera de pantalla girando, sin sombra. class CardSprite : public MovingSprite { public: explicit CardSprite(std::shared_ptr texture); ~CardSprite() override = default; // --- Ciclo principal --- void update(float delta_time) override; void render() override; // --- Control de estado --- void enable(); // Inicia la animación de entrada void startExit(); // Inicia la animación de salida // --- Consultas de estado --- [[nodiscard]] auto hasLanded() const -> bool; // ¿Ha aterrizado definitivamente? [[nodiscard]] auto hasFirstTouch() const -> bool; // ¿Ha tocado la mesa por primera vez? (primer rebote) [[nodiscard]] auto hasFinished() const -> bool; // ¿Ha terminado completamente? [[nodiscard]] auto isExiting() const -> bool; // ¿Está saliendo de pantalla? [[nodiscard]] auto getState() const -> CardState; // Estado actual // --- Configuración de entrada --- void setEntryParams(float start_zoom, double start_angle, float duration_s, std::function easing); void setEntryPosition(float start_x, float start_y); // Posición inicial (borde de pantalla) void setLandingPosition(float x, float y); // Posición final centrada // --- Configuración de salida --- void setExitParams(float vx, float vy, float ax, float ay, double rotate_amount); // --- Sombra --- void setShadowTexture(std::shared_ptr texture); void setShadowOffset(float offset_x, float offset_y); // --- Limites de pantalla (para detectar salida) --- void setScreenBounds(float width, float height); private: // --- Estado --- CardState state_ = CardState::IDLE; bool first_touch_ = false; // Primer contacto con la mesa (eased >= umbral) // --- Umbral para detectar el primer toque --- static constexpr double FIRST_TOUCH_THRESHOLD = 0.98; // --- Parámetros de entrada --- float start_zoom_ = 1.8F; double start_angle_ = 15.0; float entry_duration_s_ = 1.5F; float entry_elapsed_ = 0.0F; std::function entry_easing_; float entry_start_x_ = 0.0F; // Posición inicial X (borde) float entry_start_y_ = 0.0F; // Posición inicial Y (borde) float landing_x_ = 0.0F; float landing_y_ = 0.0F; // --- Parámetros de salida --- float exit_vx_ = 0.0F; float exit_vy_ = 0.0F; float exit_ax_ = 0.0F; float exit_ay_ = 0.0F; double exit_rotate_amount_ = 0.0; // --- Sombra --- std::shared_ptr shadow_texture_; float shadow_offset_x_ = 8.0F; float shadow_offset_y_ = 8.0F; bool shadow_visible_ = true; // --- Límites de pantalla --- float screen_width_ = 320.0F; float screen_height_ = 240.0F; // --- Margen fuera de pantalla para considerar FINISHED --- static constexpr float OFF_SCREEN_MARGIN = 50.0F; // --- Métodos internos --- void updateEntering(float delta_time); void updateExiting(float delta_time); void renderShadow(); [[nodiscard]] auto isOffScreen() const -> bool; };