#pragma once #include // for Uint64 #include // for size_t #include "../defines.h" // for AppMode, ShapeType, GravityDirection // Forward declarations class Engine; class Shape; class PNGShape; /** * @class StateManager * @brief Gestiona los estados de aplicación (SANDBOX/DEMO/DEMO_LITE/LOGO) * * Responsabilidad única: Máquina de estados y lógica de modos automáticos * * Características: * - Control de modo DEMO (auto-play completo) * - Control de modo DEMO_LITE (solo física/figuras) * - Control de modo LOGO (easter egg con convergencia) * - Timers y triggers automáticos * - Sistema de convergencia y espera de flips * - Callbacks al Engine para ejecutar acciones */ class StateManager { public: /** * @brief Constructor */ StateManager(); /** * @brief Destructor */ ~StateManager(); /** * @brief Inicializa el StateManager con referencia al Engine * @param engine Puntero al Engine (para callbacks) */ void initialize(Engine* engine); /** * @brief Actualiza la máquina de estados (timers, triggers, acciones) * @param delta_time Delta time para timers * @param shape_convergence Convergencia actual de la forma (0.0-1.0) * @param active_shape Puntero a la forma activa (para flip detection) */ void update(float delta_time, float shape_convergence, Shape* active_shape); /** * @brief Cambia el estado de aplicación * @param new_mode Nuevo modo (SANDBOX/DEMO/DEMO_LITE/LOGO) * @param current_screen_width Ancho de pantalla (para escalar tiempos) * @param current_screen_height Alto de pantalla (para escalar tiempos) */ void setState(AppMode new_mode, int current_screen_width, int current_screen_height); /** * @brief Toggle del modo DEMO completo (tecla L) * @param current_screen_width Ancho de pantalla * @param current_screen_height Alto de pantalla */ void toggleDemoMode(int current_screen_width, int current_screen_height); /** * @brief Toggle del modo DEMO_LITE (tecla L x2) * @param current_screen_width Ancho de pantalla * @param current_screen_height Alto de pantalla */ void toggleDemoLiteMode(int current_screen_width, int current_screen_height); /** * @brief Toggle del modo LOGO (tecla K) * @param current_screen_width Ancho de pantalla * @param current_screen_height Alto de pantalla * @param ball_count Número de bolas actual */ void toggleLogoMode(int current_screen_width, int current_screen_height, size_t ball_count); // === Getters === /** * @brief Obtiene el modo actual */ AppMode getCurrentMode() const { return current_app_mode_; } /** * @brief Obtiene el modo previo (antes de LOGO) */ AppMode getPreviousMode() const { return previous_app_mode_; } /** * @brief Verifica si LOGO está activo */ bool isLogoModeActive() const { return current_app_mode_ == AppMode::LOGO; } /** * @brief Verifica si DEMO (completo o lite) está activo */ bool isDemoModeActive() const { return current_app_mode_ == AppMode::DEMO || current_app_mode_ == AppMode::DEMO_LITE; } /** * @brief Obtiene índice de tema guardado (para restaurar al salir de LOGO) */ int getLogoPreviousTheme() const { return logo_previous_theme_; } /** * @brief Obtiene índice de textura guardada (para restaurar al salir de LOGO) */ size_t getLogoPreviousTextureIndex() const { return logo_previous_texture_index_; } /** * @brief Obtiene escala de forma guardada (para restaurar al salir de LOGO) */ float getLogoPreviousShapeScale() const { return logo_previous_shape_scale_; } /** * @brief Establece valores previos de LOGO (llamado por Engine antes de entrar) */ void setLogoPreviousState(int theme, size_t texture_index, float shape_scale); /** * @brief Entra al modo LOGO (público para permitir salto automático desde DEMO) * @param from_demo true si viene desde DEMO, false si es manual * @param current_screen_width Ancho de pantalla * @param current_screen_height Alto de pantalla * @param ball_count Número de bolas */ void enterLogoMode(bool from_demo, int current_screen_width, int current_screen_height, size_t ball_count); /** * @brief Sale del modo LOGO (público para permitir salida manual) * @param return_to_demo true si debe volver a DEMO/DEMO_LITE */ void exitLogoMode(bool return_to_demo); private: // === Referencia al Engine (callback) === Engine* engine_; // === Estado de aplicación === AppMode current_app_mode_; AppMode previous_app_mode_; // === Sistema DEMO (timers) === float demo_timer_; float demo_next_action_time_; // === Sistema LOGO (convergencia) === float logo_convergence_threshold_; float logo_min_time_; float logo_max_time_; // === Sistema LOGO (espera de flips) === bool logo_waiting_for_flip_; int logo_target_flip_number_; float logo_target_flip_percentage_; int logo_current_flip_count_; // === Control de entrada LOGO === bool logo_entered_manually_; // === Estado previo LOGO (restauración) === int logo_previous_theme_; size_t logo_previous_texture_index_; float logo_previous_shape_scale_; // === Métodos privados === /** * @brief Ejecuta una acción del modo DEMO * @param is_lite true si es DEMO_LITE, false si es DEMO completo */ void performDemoAction(bool is_lite); /** * @brief Randomiza estado al entrar a modo DEMO * @param is_lite true si es DEMO_LITE, false si es DEMO completo */ void randomizeOnDemoStart(bool is_lite); /** * @brief Toggle de gravedad ON/OFF (para DEMO) */ void toggleGravityOnOff(); };