Modernizar convenciones de código C++ aplicando las siguientes directivas:
## Cambios principales
**1. Renombrar headers (.h → .hpp)**
- 36 archivos renombrados a extensión .hpp (estándar C++)
- Mantenidos como .h: stb_image.h, stb_image_resize2.h (librerías C externas)
**2. Modernizar include guards (#ifndef → #pragma once)**
- resource_manager.hpp: #ifndef RESOURCE_MANAGER_H → #pragma once
- resource_pack.hpp: #ifndef RESOURCE_PACK_H → #pragma once
- spatial_grid.hpp: #ifndef SPATIAL_GRID_H → #pragma once
**3. Sistema de includes desde raíz del proyecto**
- CMakeLists.txt: añadido include_directories(${CMAKE_SOURCE_DIR}/source)
- Eliminadas rutas relativas (../) en todos los includes
- Includes ahora usan rutas absolutas desde source/
**Antes:**
```cpp
#include "../defines.h"
#include "../text/textrenderer.h"
```
**Ahora:**
```cpp
#include "defines.hpp"
#include "text/textrenderer.hpp"
```
## Archivos afectados
- 1 archivo CMakeLists.txt modificado
- 36 archivos renombrados (.h → .hpp)
- 32 archivos .cpp actualizados (includes)
- 36 archivos .hpp actualizados (includes + guards)
- 1 archivo tools/ actualizado
**Total: 70 archivos modificados**
## Verificación
✅ Proyecto compila sin errores
✅ Todas las rutas de includes correctas
✅ Include guards modernizados
✅ Librerías externas C mantienen extensión .h
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
277 lines
11 KiB
C++
277 lines
11 KiB
C++
#include "state_manager.hpp"
|
|
|
|
#include <cstdlib> // for rand
|
|
|
|
#include "defines.hpp" // for constantes DEMO/LOGO
|
|
#include "engine.hpp" // for Engine (callbacks)
|
|
#include "shapes/png_shape.hpp" // 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;
|
|
}
|
|
|
|
// ===========================================================================
|
|
// ACTUALIZACIÓN DE ESTADOS - Migrado desde Engine::updateDemoMode()
|
|
// ===========================================================================
|
|
|
|
void StateManager::update(float delta_time, float shape_convergence, Shape* active_shape) {
|
|
// Verificar si algún modo demo está activo (DEMO, DEMO_LITE o LOGO)
|
|
if (current_app_mode_ == AppMode::SANDBOX) return;
|
|
|
|
// Actualizar timer
|
|
demo_timer_ += delta_time;
|
|
|
|
// Determinar si es hora de ejecutar acción (depende del modo)
|
|
bool should_trigger = false;
|
|
|
|
if (current_app_mode_ == AppMode::LOGO) {
|
|
// LOGO MODE: Dos caminos posibles
|
|
if (logo_waiting_for_flip_) {
|
|
// CAMINO B: Esperando a que ocurran flips
|
|
// Obtener referencia a PNGShape si está activa
|
|
PNGShape* png_shape = dynamic_cast<PNGShape*>(active_shape);
|
|
|
|
if (png_shape) {
|
|
int current_flip_count = png_shape->getFlipCount();
|
|
|
|
// Detectar nuevo flip completado
|
|
if (current_flip_count > logo_current_flip_count_) {
|
|
logo_current_flip_count_ = current_flip_count;
|
|
}
|
|
|
|
// Si estamos EN o DESPUÉS del flip objetivo
|
|
// +1 porque queremos actuar DURANTE el flip N, no después de completarlo
|
|
if (logo_current_flip_count_ + 1 >= logo_target_flip_number_) {
|
|
// Monitorear progreso del flip actual
|
|
if (png_shape->isFlipping()) {
|
|
float flip_progress = png_shape->getFlipProgress();
|
|
if (flip_progress >= logo_target_flip_percentage_) {
|
|
should_trigger = true; // ¡Trigger durante el flip!
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// CAMINO A: Esperar convergencia + tiempo (comportamiento original)
|
|
bool min_time_reached = demo_timer_ >= logo_min_time_;
|
|
bool max_time_reached = demo_timer_ >= logo_max_time_;
|
|
bool convergence_ok = shape_convergence >= logo_convergence_threshold_;
|
|
|
|
should_trigger = (min_time_reached && convergence_ok) || max_time_reached;
|
|
}
|
|
} else {
|
|
// DEMO/DEMO_LITE: Timer simple como antes
|
|
should_trigger = demo_timer_ >= demo_next_action_time_;
|
|
}
|
|
|
|
// Si es hora de ejecutar acción
|
|
if (should_trigger) {
|
|
// MODO LOGO: Sistema de acciones variadas con gravedad dinámica
|
|
if (current_app_mode_ == AppMode::LOGO) {
|
|
// Llamar a Engine para ejecutar acciones de LOGO
|
|
// TODO FASE 9: Mover lógica de acciones LOGO desde Engine a StateManager
|
|
if (engine_) {
|
|
engine_->performLogoAction(logo_waiting_for_flip_);
|
|
}
|
|
}
|
|
// MODO DEMO/DEMO_LITE: Acciones normales
|
|
else {
|
|
bool is_lite = (current_app_mode_ == AppMode::DEMO_LITE);
|
|
performDemoAction(is_lite);
|
|
|
|
// Resetear timer y calcular próximo intervalo aleatorio
|
|
demo_timer_ = 0.0f;
|
|
|
|
// Usar intervalos diferentes según modo
|
|
float interval_min = is_lite ? DEMO_LITE_ACTION_INTERVAL_MIN : DEMO_ACTION_INTERVAL_MIN;
|
|
float interval_max = is_lite ? DEMO_LITE_ACTION_INTERVAL_MAX : DEMO_ACTION_INTERVAL_MAX;
|
|
float interval_range = interval_max - interval_min;
|
|
demo_next_action_time_ = interval_min + (rand() % 1000) / 1000.0f * interval_range;
|
|
}
|
|
}
|
|
}
|
|
|
|
void StateManager::setState(AppMode new_mode, int current_screen_width, int current_screen_height) {
|
|
if (current_app_mode_ == new_mode) return;
|
|
|
|
if (current_app_mode_ == AppMode::LOGO && new_mode != AppMode::LOGO) {
|
|
previous_app_mode_ = new_mode;
|
|
}
|
|
|
|
if (new_mode == AppMode::LOGO) {
|
|
previous_app_mode_ = current_app_mode_;
|
|
}
|
|
|
|
current_app_mode_ = new_mode;
|
|
|
|
// Resetear timer al cambiar modo
|
|
demo_timer_ = 0.0f;
|
|
|
|
// Configurar timer de demo según el modo
|
|
if (new_mode == AppMode::DEMO || new_mode == AppMode::DEMO_LITE || new_mode == AppMode::LOGO) {
|
|
float min_interval, max_interval;
|
|
|
|
if (new_mode == AppMode::LOGO) {
|
|
// Escalar tiempos con resolución (720p como base)
|
|
float resolution_scale = current_screen_height / 720.0f;
|
|
logo_min_time_ = LOGO_ACTION_INTERVAL_MIN * resolution_scale;
|
|
logo_max_time_ = LOGO_ACTION_INTERVAL_MAX * resolution_scale;
|
|
|
|
min_interval = logo_min_time_;
|
|
max_interval = logo_max_time_;
|
|
} else {
|
|
bool is_lite = (new_mode == AppMode::DEMO_LITE);
|
|
min_interval = is_lite ? DEMO_LITE_ACTION_INTERVAL_MIN : DEMO_ACTION_INTERVAL_MIN;
|
|
max_interval = is_lite ? DEMO_LITE_ACTION_INTERVAL_MAX : DEMO_ACTION_INTERVAL_MAX;
|
|
}
|
|
|
|
demo_next_action_time_ = min_interval + (rand() % 1000) / 1000.0f * (max_interval - min_interval);
|
|
}
|
|
}
|
|
|
|
void StateManager::toggleDemoMode(int current_screen_width, int current_screen_height) {
|
|
if (current_app_mode_ == AppMode::DEMO) {
|
|
setState(AppMode::SANDBOX, current_screen_width, current_screen_height);
|
|
} else {
|
|
setState(AppMode::DEMO, current_screen_width, current_screen_height);
|
|
randomizeOnDemoStart(false); // Randomizar estado al entrar
|
|
}
|
|
}
|
|
|
|
void StateManager::toggleDemoLiteMode(int current_screen_width, int current_screen_height) {
|
|
if (current_app_mode_ == AppMode::DEMO_LITE) {
|
|
setState(AppMode::SANDBOX, current_screen_width, current_screen_height);
|
|
} else {
|
|
setState(AppMode::DEMO_LITE, current_screen_width, current_screen_height);
|
|
randomizeOnDemoStart(true); // Randomizar estado al entrar
|
|
}
|
|
}
|
|
|
|
void StateManager::toggleLogoMode(int current_screen_width, int current_screen_height, size_t ball_count) {
|
|
if (current_app_mode_ == AppMode::LOGO) {
|
|
exitLogoMode(false); // Salir de LOGO manualmente
|
|
} else {
|
|
enterLogoMode(false, current_screen_width, current_screen_height, ball_count); // Entrar manualmente
|
|
}
|
|
}
|
|
|
|
// ===========================================================================
|
|
// ACCIONES DE DEMO - Migrado desde Engine::performDemoAction()
|
|
// ===========================================================================
|
|
|
|
void StateManager::performDemoAction(bool is_lite) {
|
|
// ============================================
|
|
// SALTO AUTOMÁTICO A LOGO MODE (Easter Egg)
|
|
// ============================================
|
|
|
|
// Obtener información necesaria desde Engine via callbacks
|
|
// (En el futuro, se podría pasar como parámetros al método)
|
|
if (!engine_) return;
|
|
|
|
// TODO FASE 9: Eliminar callbacks a Engine y pasar parámetros necesarios
|
|
|
|
// Por ahora, delegar las acciones DEMO completas a Engine
|
|
// ya que necesitan acceso a múltiples componentes (SceneManager, ThemeManager, etc.)
|
|
engine_->executeDemoAction(is_lite);
|
|
}
|
|
|
|
// ===========================================================================
|
|
// RANDOMIZACIÓN AL INICIAR DEMO - Migrado desde Engine::randomizeOnDemoStart()
|
|
// ===========================================================================
|
|
|
|
void StateManager::randomizeOnDemoStart(bool is_lite) {
|
|
// Delegar a Engine para randomización completa
|
|
// TODO FASE 9: Implementar lógica completa aquí
|
|
if (engine_) {
|
|
engine_->executeRandomizeOnDemoStart(is_lite);
|
|
}
|
|
}
|
|
|
|
// ===========================================================================
|
|
// TOGGLE GRAVEDAD (para DEMO) - Migrado desde Engine::toggleGravityOnOff()
|
|
// ===========================================================================
|
|
|
|
void StateManager::toggleGravityOnOff() {
|
|
// Delegar a Engine temporalmente
|
|
if (engine_) {
|
|
engine_->executeToggleGravityOnOff();
|
|
}
|
|
}
|
|
|
|
// ===========================================================================
|
|
// ENTRAR AL MODO LOGO - Migrado desde Engine::enterLogoMode()
|
|
// ===========================================================================
|
|
|
|
void StateManager::enterLogoMode(bool from_demo, int current_screen_width, int current_screen_height, size_t ball_count) {
|
|
// Guardar si entrada fue manual (tecla K) o automática (desde DEMO)
|
|
logo_entered_manually_ = !from_demo;
|
|
|
|
// Resetear variables de espera de flips
|
|
logo_waiting_for_flip_ = false;
|
|
logo_target_flip_number_ = 0;
|
|
logo_target_flip_percentage_ = 0.0f;
|
|
logo_current_flip_count_ = 0;
|
|
|
|
// Cambiar a modo LOGO (guarda previous_app_mode_ automáticamente)
|
|
setState(AppMode::LOGO, current_screen_width, current_screen_height);
|
|
|
|
// Delegar configuración visual a Engine
|
|
// TODO FASE 9: Mover configuración completa aquí
|
|
if (engine_) {
|
|
engine_->executeEnterLogoMode(ball_count);
|
|
}
|
|
}
|
|
|
|
// ===========================================================================
|
|
// SALIR DEL MODO LOGO - Migrado desde Engine::exitLogoMode()
|
|
// ===========================================================================
|
|
|
|
void StateManager::exitLogoMode(bool return_to_demo) {
|
|
if (current_app_mode_ != AppMode::LOGO) return;
|
|
|
|
// Resetear flag de entrada manual
|
|
logo_entered_manually_ = false;
|
|
|
|
// Delegar restauración visual a Engine
|
|
// TODO FASE 9: Mover lógica completa aquí
|
|
if (engine_) {
|
|
engine_->executeExitLogoMode();
|
|
}
|
|
|
|
if (!return_to_demo) {
|
|
// Salida manual (tecla K): volver a SANDBOX
|
|
setState(AppMode::SANDBOX, 0, 0);
|
|
} else {
|
|
// Volver al modo previo (DEMO o DEMO_LITE)
|
|
current_app_mode_ = previous_app_mode_;
|
|
}
|
|
}
|