diff --git a/CMakeLists.txt b/CMakeLists.txt index eb8f867..c5024ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ if (NOT SDL3_ttf_FOUND) endif() # Archivos fuente (excluir main_old.cpp) -file(GLOB SOURCE_FILES source/*.cpp source/external/*.cpp source/input/*.cpp source/scene/*.cpp source/shapes/*.cpp source/themes/*.cpp source/text/*.cpp source/ui/*.cpp) +file(GLOB SOURCE_FILES source/*.cpp source/external/*.cpp source/input/*.cpp source/scene/*.cpp source/shapes/*.cpp source/state/*.cpp source/themes/*.cpp source/text/*.cpp source/ui/*.cpp) list(REMOVE_ITEM SOURCE_FILES "${CMAKE_SOURCE_DIR}/source/main_old.cpp") # Comprobar si se encontraron archivos fuente diff --git a/source/engine.cpp b/source/engine.cpp index 68d492e..0103ebe 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -231,6 +231,10 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen) { // NOTA: Debe llamarse DESPUÉS de updatePhysicalWindowSize() y ThemeManager ui_manager_ = std::make_unique(); ui_manager_->initialize(renderer_, theme_manager_.get(), physical_window_width_, physical_window_height_); + + // Inicializar StateManager (gestión de estados DEMO/LOGO) + state_manager_ = std::make_unique(); + state_manager_->initialize(this); // Callback al Engine } return success; diff --git a/source/engine.h b/source/engine.h index a05cb8b..191eb9d 100644 --- a/source/engine.h +++ b/source/engine.h @@ -16,6 +16,7 @@ #include "input/input_handler.h" // for InputHandler #include "scene/scene_manager.h" // for SceneManager #include "shapes/shape.h" // for Shape (interfaz polimórfica) +#include "state/state_manager.h" // for StateManager #include "theme_manager.h" // for ThemeManager #include "ui/ui_manager.h" // for UIManager @@ -72,6 +73,7 @@ class Engine { // === Componentes del sistema (Composición) === std::unique_ptr input_handler_; // Manejo de entradas SDL std::unique_ptr scene_manager_; // Gestión de bolas y física + std::unique_ptr state_manager_; // Gestión de estados (DEMO/LOGO) std::unique_ptr ui_manager_; // Gestión de UI (HUD, FPS, notificaciones) // Recursos SDL diff --git a/source/state/state_manager.cpp b/source/state/state_manager.cpp new file mode 100644 index 0000000..6d5e198 --- /dev/null +++ b/source/state/state_manager.cpp @@ -0,0 +1,82 @@ +#include "state_manager.h" + +#include // for rand + +#include "../defines.h" // for constantes DEMO/LOGO +#include "../engine.h" // for Engine (callbacks) +#include "../shapes/png_shape.h" // for PNGShape flip detection + +StateManager::StateManager() + : engine_(nullptr) + , current_app_mode_(AppMode::SANDBOX) + , previous_app_mode_(AppMode::SANDBOX) + , demo_timer_(0.0f) + , demo_next_action_time_(0.0f) + , logo_convergence_threshold_(0.90f) + , logo_min_time_(3.0f) + , logo_max_time_(5.0f) + , logo_waiting_for_flip_(false) + , logo_target_flip_number_(0) + , logo_target_flip_percentage_(0.0f) + , logo_current_flip_count_(0) + , logo_entered_manually_(false) + , logo_previous_theme_(0) + , logo_previous_texture_index_(0) + , logo_previous_shape_scale_(1.0f) { +} + +StateManager::~StateManager() { +} + +void StateManager::initialize(Engine* engine) { + engine_ = engine; +} + +void StateManager::setLogoPreviousState(int theme, size_t texture_index, float shape_scale) { + logo_previous_theme_ = theme; + logo_previous_texture_index_ = texture_index; + logo_previous_shape_scale_ = shape_scale; +} + +// TODO: Implementar métodos completos +// Por ahora, stubs vacíos para que compile + +void StateManager::update(float delta_time, float shape_convergence, Shape* active_shape) { + // TODO: Migrar updateDemoMode() +} + +void StateManager::setState(AppMode new_mode, int current_screen_width, int current_screen_height) { + // TODO: Migrar setState() +} + +void StateManager::toggleDemoMode(int current_screen_width, int current_screen_height) { + // TODO: Migrar toggleDemoMode() +} + +void StateManager::toggleDemoLiteMode(int current_screen_width, int current_screen_height) { + // TODO: Migrar toggleDemoLiteMode() +} + +void StateManager::toggleLogoMode(int current_screen_width, int current_screen_height, size_t ball_count) { + // TODO: Migrar toggleLogoMode() +} + +void StateManager::performDemoAction(bool is_lite) { + // TODO: Migrar performDemoAction() +} + +void StateManager::randomizeOnDemoStart(bool is_lite) { + // TODO: Migrar randomizeOnDemoStart() +} + +void StateManager::toggleGravityOnOff() { + // TODO: Migrar toggleGravityOnOff() +} + +void StateManager::enterLogoMode(bool from_demo, int current_screen_width, int current_screen_height, size_t ball_count) { + // TODO: Migrar enterLogoMode() +} + +void StateManager::exitLogoMode(bool return_to_demo) { + // TODO: Migrar exitLogoMode() +} diff --git a/source/state/state_manager.h b/source/state/state_manager.h new file mode 100644 index 0000000..d8ae46f --- /dev/null +++ b/source/state/state_manager.h @@ -0,0 +1,191 @@ +#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); + + 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(); + + /** + * @brief Entra al modo LOGO + * @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 + * @param return_to_demo true si debe volver a DEMO/DEMO_LITE + */ + void exitLogoMode(bool return_to_demo); +};