Refactor fase 8: Migrar lógica DEMO/LOGO a StateManager
Implementación: - StateManager::update() ahora maneja timers y triggers DEMO/LOGO - Detección de flips de PNG_SHAPE migrada completamente - Callbacks temporales en Engine para acciones complejas - enterLogoMode() y exitLogoMode() públicos para transiciones automáticas - Toggle methods en Engine delegados a StateManager Callbacks implementados (temporal para Fase 9): - Engine::performLogoAction() - Engine::executeDemoAction() - Engine::executeRandomizeOnDemoStart() - Engine::executeToggleGravityOnOff() - Engine::executeEnterLogoMode() - Engine::executeExitLogoMode() TODO Fase 9: - Eliminar callbacks moviendo lógica completa a StateManager - Limpiar duplicación de estado entre Engine y StateManager 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,15 +38,84 @@ void StateManager::setLogoPreviousState(int theme, size_t texture_index, float s
|
||||
logo_previous_shape_scale_ = shape_scale;
|
||||
}
|
||||
|
||||
// TODO: Implementar métodos completos
|
||||
// Por ahora, stubs vacíos para que compile
|
||||
// ===========================================================================
|
||||
// ACTUALIZACIÓN DE ESTADOS - Migrado desde Engine::updateDemoMode()
|
||||
// ===========================================================================
|
||||
|
||||
void StateManager::update(float delta_time, float shape_convergence, Shape* active_shape) {
|
||||
// Delegar a Engine temporalmente - La lógica compleja queda en Engine por ahora
|
||||
// Este es un wrapper que permite refactorizar gradualmente
|
||||
if (engine_) {
|
||||
// Engine mantiene la implementación de updateDemoMode()
|
||||
// StateManager solo coordina el estado
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +134,27 @@ void StateManager::setState(AppMode new_mode, int current_screen_width, int curr
|
||||
|
||||
// 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) {
|
||||
@@ -72,6 +162,7 @@ void StateManager::toggleDemoMode(int current_screen_width, int current_screen_h
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,34 +171,106 @@ void StateManager::toggleDemoLiteMode(int current_screen_width, int current_scre
|
||||
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) {
|
||||
setState(AppMode::SANDBOX, current_screen_width, current_screen_height);
|
||||
exitLogoMode(false); // Salir de LOGO manualmente
|
||||
} else {
|
||||
setState(AppMode::LOGO, current_screen_width, current_screen_height);
|
||||
logo_entered_manually_ = true;
|
||||
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) {
|
||||
// TODO: Migrar performDemoAction()
|
||||
// ============================================
|
||||
// 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) {
|
||||
// TODO: Migrar randomizeOnDemoStart()
|
||||
// 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() {
|
||||
// TODO: Migrar 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) {
|
||||
// TODO: Migrar enterLogoMode()
|
||||
// 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) {
|
||||
// TODO: Migrar exitLogoMode()
|
||||
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_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,21 @@ class StateManager {
|
||||
*/
|
||||
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_;
|
||||
@@ -173,19 +188,4 @@ class StateManager {
|
||||
* @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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user