diff --git a/source/defines.h b/source/defines.h index 32e954d..6f1ae65 100644 --- a/source/defines.h +++ b/source/defines.h @@ -153,19 +153,34 @@ constexpr float SHAPE_SCALE_MAX = 3.0f; // Escala máxima (300%) constexpr float SHAPE_SCALE_STEP = 0.1f; // Incremento por pulsación constexpr float SHAPE_SCALE_DEFAULT = 1.0f; // Escala por defecto (100%) -// Configuración de Modo DEMO (auto-play) -constexpr float DEMO_ACTION_INTERVAL_MIN = 3.0f; // Tiempo mínimo entre acciones (segundos) -constexpr float DEMO_ACTION_INTERVAL_MAX = 8.0f; // Tiempo máximo entre acciones (segundos) +// Configuración de Modo DEMO (auto-play completo) +constexpr float DEMO_ACTION_INTERVAL_MIN = 2.0f; // Tiempo mínimo entre acciones (segundos) +constexpr float DEMO_ACTION_INTERVAL_MAX = 6.0f; // Tiempo máximo entre acciones (segundos) -// Pesos de probabilidad para cada tipo de acción (valores relativos, se normalizan) -constexpr int DEMO_WEIGHT_GRAVITY = 15; // Cambiar dirección gravedad (15%) -constexpr int DEMO_WEIGHT_SHAPE = 25; // Activar figura 3D (25%) -constexpr int DEMO_WEIGHT_THEME = 20; // Cambiar tema de colores (20%) -constexpr int DEMO_WEIGHT_SCENARIO = 15; // Cambiar número de pelotas (15%) +// Pesos de probabilidad DEMO MODE (valores relativos, se normalizan) +constexpr int DEMO_WEIGHT_GRAVITY_DIR = 10; // Cambiar dirección gravedad (10%) +constexpr int DEMO_WEIGHT_GRAVITY_TOGGLE = 8; // Toggle gravedad ON/OFF (8%) +constexpr int DEMO_WEIGHT_SHAPE = 20; // Activar figura 3D (20%) +constexpr int DEMO_WEIGHT_TOGGLE_PHYSICS = 12; // Toggle física ↔ figura (12%) +constexpr int DEMO_WEIGHT_REGENERATE_SHAPE = 8; // Re-generar misma figura (8%) +constexpr int DEMO_WEIGHT_THEME = 15; // Cambiar tema de colores (15%) +constexpr int DEMO_WEIGHT_SCENARIO = 10; // Cambiar número de pelotas (10%) constexpr int DEMO_WEIGHT_IMPULSE = 10; // Aplicar impulso (SPACE) (10%) -constexpr int DEMO_WEIGHT_DEPTH_ZOOM = 5; // Toggle profundidad (5%) -constexpr int DEMO_WEIGHT_SHAPE_SCALE = 5; // Cambiar escala figura (5%) -constexpr int DEMO_WEIGHT_SPRITE = 5; // Cambiar sprite (5%) -// TOTAL: 100 (se pueden ajustar para priorizar acciones) +constexpr int DEMO_WEIGHT_DEPTH_ZOOM = 3; // Toggle profundidad (3%) +constexpr int DEMO_WEIGHT_SHAPE_SCALE = 2; // Cambiar escala figura (2%) +constexpr int DEMO_WEIGHT_SPRITE = 2; // Cambiar sprite (2%) +// TOTAL: 100 + +// Configuración de Modo DEMO LITE (solo física/figuras) +constexpr float DEMO_LITE_ACTION_INTERVAL_MIN = 1.5f; // Más rápido que demo completo +constexpr float DEMO_LITE_ACTION_INTERVAL_MAX = 4.0f; + +// Pesos de probabilidad DEMO LITE (solo física/figuras, sin cambios de escenario/tema) +constexpr int DEMO_LITE_WEIGHT_GRAVITY_DIR = 25; // Cambiar dirección gravedad (25%) +constexpr int DEMO_LITE_WEIGHT_GRAVITY_TOGGLE = 20;// Toggle gravedad ON/OFF (20%) +constexpr int DEMO_LITE_WEIGHT_SHAPE = 25; // Activar figura 3D (25%) +constexpr int DEMO_LITE_WEIGHT_TOGGLE_PHYSICS = 20;// Toggle física ↔ figura (20%) +constexpr int DEMO_LITE_WEIGHT_IMPULSE = 10; // Aplicar impulso (10%) +// TOTAL: 100 constexpr float PI = 3.14159265358979323846f; // Constante PI \ No newline at end of file diff --git a/source/engine.cpp b/source/engine.cpp index aad084e..65f06e3 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -469,11 +469,17 @@ void Engine::handleEvents() { toggleIntegerScaling(); break; - // Toggle Modo DEMO (auto-play) + // Toggle Modo DEMO COMPLETO (auto-play) case SDLK_D: demo_mode_enabled_ = !demo_mode_enabled_; if (demo_mode_enabled_) { - // Al activar: inicializar timer con primer intervalo aleatorio + // Desactivar demo lite si estaba activo (mutuamente excluyentes) + demo_lite_enabled_ = false; + + // Randomizar TODO al activar + randomizeOnDemoStart(false); + + // Inicializar timer con primer intervalo aleatorio demo_timer_ = 0.0f; float interval_range = DEMO_ACTION_INTERVAL_MAX - DEMO_ACTION_INTERVAL_MIN; demo_next_action_time_ = DEMO_ACTION_INTERVAL_MIN + (rand() % 1000) / 1000.0f * interval_range; @@ -489,6 +495,33 @@ void Engine::handleEvents() { text_init_time_ = SDL_GetTicks(); } break; + + // Toggle Modo DEMO LITE (solo física/figuras) + case SDLK_L: + demo_lite_enabled_ = !demo_lite_enabled_; + if (demo_lite_enabled_) { + // Desactivar demo completo si estaba activo (mutuamente excluyentes) + demo_mode_enabled_ = false; + + // Randomizar solo física/figura (mantiene escenario y tema) + randomizeOnDemoStart(true); + + // Inicializar timer con primer intervalo aleatorio (más rápido) + demo_timer_ = 0.0f; + float interval_range = DEMO_LITE_ACTION_INTERVAL_MAX - DEMO_LITE_ACTION_INTERVAL_MIN; + demo_next_action_time_ = DEMO_LITE_ACTION_INTERVAL_MIN + (rand() % 1000) / 1000.0f * interval_range; + + // Mostrar texto de activación + text_ = "DEMO LITE ON"; + show_text_ = true; + text_init_time_ = SDL_GetTicks(); + } else { + // Al desactivar: mostrar texto + text_ = "DEMO LITE OFF"; + show_text_ = true; + text_init_time_ = SDL_GetTicks(); + } + break; } } } @@ -629,13 +662,19 @@ void Engine::render() { dbg_print(8, 72, mode_text.c_str(), 0, 255, 128); // Verde claro para modo } - // Mostrar indicador "DEMO MODE" permanente cuando está activo (independiente de show_debug_) + // Mostrar indicador "DEMO MODE" o "DEMO LITE" permanente (independiente de show_debug_) if (demo_mode_enabled_) { // Centrar texto horizontalmente const char* demo_text = "DEMO MODE"; int demo_text_width = static_cast(strlen(demo_text) * 8); // 8 píxeles por carácter int demo_x = (current_screen_width_ - demo_text_width) / 2; dbg_print(demo_x, 8, demo_text, 255, 128, 0); // Naranja brillante + } else if (demo_lite_enabled_) { + // Centrar texto horizontalmente + const char* demo_lite_text = "DEMO LITE"; + int demo_lite_text_width = static_cast(strlen(demo_lite_text) * 8); + int demo_lite_x = (current_screen_width_ - demo_lite_text_width) / 2; + dbg_print(demo_lite_x, 8, demo_lite_text, 128, 200, 255); // Azul claro } SDL_RenderPresent(renderer_); @@ -675,6 +714,9 @@ void Engine::initBalls(int value) { } void Engine::setText() { + // Suprimir textos durante modos demo + if (demo_mode_enabled_ || demo_lite_enabled_) return; + int num_balls = test_.at(scenario_); if (num_balls == 1) { text_ = "1 PELOTA"; @@ -1167,12 +1209,14 @@ void Engine::startThemeTransition(ColorTheme new_theme) { transitioning_ = true; transition_progress_ = 0.0f; - // Mostrar nombre del tema (igual que selección directa con KP_1-6) - ThemeColors& theme = themes_[static_cast(new_theme)]; - text_ = theme.name_es; - text_pos_ = (current_screen_width_ - static_cast(text_.length() * 8)) / 2; - show_text_ = true; - text_init_time_ = SDL_GetTicks(); + // Mostrar nombre del tema (solo si NO estamos en modo demo) + if (!demo_mode_enabled_ && !demo_lite_enabled_) { + ThemeColors& theme = themes_[static_cast(new_theme)]; + text_ = theme.name_es; + text_pos_ = (current_screen_width_ - static_cast(text_.length() * 8)) / 2; + show_text_ = true; + text_init_time_ = SDL_GetTicks(); + } } Color Engine::getInterpolatedColor(size_t ball_index) const { @@ -1199,110 +1243,279 @@ Color Engine::getInterpolatedColor(size_t ball_index) const { // Sistema de Modo DEMO (auto-play) void Engine::updateDemoMode() { - if (!demo_mode_enabled_) return; + // Verificar si algún modo está activo + bool is_demo_active = demo_mode_enabled_ || demo_lite_enabled_; + if (!is_demo_active) return; // Actualizar timer demo_timer_ += delta_time_; // Si es hora de ejecutar acción if (demo_timer_ >= demo_next_action_time_) { - performDemoAction(); + // Ejecutar acción según modo activo + bool is_lite = demo_lite_enabled_; + performDemoAction(is_lite); // Resetear timer y calcular próximo intervalo aleatorio demo_timer_ = 0.0f; - float interval_range = DEMO_ACTION_INTERVAL_MAX - DEMO_ACTION_INTERVAL_MIN; - demo_next_action_time_ = DEMO_ACTION_INTERVAL_MIN + (rand() % 1000) / 1000.0f * interval_range; + + // 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 Engine::performDemoAction() { - // Calcular suma total de pesos - const int TOTAL_WEIGHT = DEMO_WEIGHT_GRAVITY + DEMO_WEIGHT_SHAPE + DEMO_WEIGHT_THEME - + DEMO_WEIGHT_SCENARIO + DEMO_WEIGHT_IMPULSE + DEMO_WEIGHT_DEPTH_ZOOM - + DEMO_WEIGHT_SHAPE_SCALE + DEMO_WEIGHT_SPRITE; - - // Generar número aleatorio entre 0 y TOTAL_WEIGHT - int random_value = rand() % TOTAL_WEIGHT; - - // Determinar acción según pesos acumulados +void Engine::performDemoAction(bool is_lite) { + int TOTAL_WEIGHT; + int random_value; int accumulated_weight = 0; - // Acción: Cambiar gravedad (15%) - accumulated_weight += DEMO_WEIGHT_GRAVITY; - if (random_value < accumulated_weight) { + if (is_lite) { + // DEMO LITE: Solo física/figuras + TOTAL_WEIGHT = DEMO_LITE_WEIGHT_GRAVITY_DIR + DEMO_LITE_WEIGHT_GRAVITY_TOGGLE + + DEMO_LITE_WEIGHT_SHAPE + DEMO_LITE_WEIGHT_TOGGLE_PHYSICS + + DEMO_LITE_WEIGHT_IMPULSE; + random_value = rand() % TOTAL_WEIGHT; + + // Cambiar dirección gravedad (25%) + accumulated_weight += DEMO_LITE_WEIGHT_GRAVITY_DIR; + if (random_value < accumulated_weight) { + GravityDirection new_direction = static_cast(rand() % 4); + changeGravityDirection(new_direction); + return; + } + + // Toggle gravedad ON/OFF (20%) + accumulated_weight += DEMO_LITE_WEIGHT_GRAVITY_TOGGLE; + if (random_value < accumulated_weight) { + toggleGravityOnOff(); + return; + } + + // Activar figura 3D (25%) + accumulated_weight += DEMO_LITE_WEIGHT_SHAPE; + if (random_value < accumulated_weight) { + ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::WAVE_GRID, ShapeType::HELIX, + ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, + ShapeType::ICOSAHEDRON, ShapeType::ATOM}; + int shape_index = rand() % 8; + activateShape(shapes[shape_index]); + return; + } + + // Toggle física ↔ figura (20%) + accumulated_weight += DEMO_LITE_WEIGHT_TOGGLE_PHYSICS; + if (random_value < accumulated_weight) { + toggleShapeMode(false); // NO forzar gravedad al salir + return; + } + + // Aplicar impulso (10%) + accumulated_weight += DEMO_LITE_WEIGHT_IMPULSE; + if (random_value < accumulated_weight) { + pushBallsAwayFromGravity(); + return; + } + + } else { + // DEMO COMPLETO: Todas las acciones + TOTAL_WEIGHT = DEMO_WEIGHT_GRAVITY_DIR + DEMO_WEIGHT_GRAVITY_TOGGLE + DEMO_WEIGHT_SHAPE + + DEMO_WEIGHT_TOGGLE_PHYSICS + DEMO_WEIGHT_REGENERATE_SHAPE + DEMO_WEIGHT_THEME + + DEMO_WEIGHT_SCENARIO + DEMO_WEIGHT_IMPULSE + DEMO_WEIGHT_DEPTH_ZOOM + + DEMO_WEIGHT_SHAPE_SCALE + DEMO_WEIGHT_SPRITE; + random_value = rand() % TOTAL_WEIGHT; + + // Cambiar dirección gravedad (10%) + accumulated_weight += DEMO_WEIGHT_GRAVITY_DIR; + if (random_value < accumulated_weight) { + GravityDirection new_direction = static_cast(rand() % 4); + changeGravityDirection(new_direction); + return; + } + + // Toggle gravedad ON/OFF (8%) + accumulated_weight += DEMO_WEIGHT_GRAVITY_TOGGLE; + if (random_value < accumulated_weight) { + toggleGravityOnOff(); + return; + } + + // Activar figura 3D (20%) + accumulated_weight += DEMO_WEIGHT_SHAPE; + if (random_value < accumulated_weight) { + ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::WAVE_GRID, ShapeType::HELIX, + ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, + ShapeType::ICOSAHEDRON, ShapeType::ATOM}; + int shape_index = rand() % 8; + activateShape(shapes[shape_index]); + return; + } + + // Toggle física ↔ figura (12%) + accumulated_weight += DEMO_WEIGHT_TOGGLE_PHYSICS; + if (random_value < accumulated_weight) { + toggleShapeMode(false); // NO forzar gravedad al salir + return; + } + + // Re-generar misma figura (8%) + accumulated_weight += DEMO_WEIGHT_REGENERATE_SHAPE; + if (random_value < accumulated_weight) { + if (current_mode_ == SimulationMode::SHAPE && active_shape_) { + generateShape(); // Re-generar sin cambiar tipo + } + return; + } + + // Cambiar tema (15%) + accumulated_weight += DEMO_WEIGHT_THEME; + if (random_value < accumulated_weight) { + ColorTheme new_theme = static_cast(rand() % 6); + startThemeTransition(new_theme); + return; + } + + // Cambiar escenario (10%) - EXCLUIR índices 0, 6, 7 (1, 50K, 100K pelotas) + accumulated_weight += DEMO_WEIGHT_SCENARIO; + if (random_value < accumulated_weight) { + // Escenarios válidos: índices 1, 2, 3, 4, 5 (10, 100, 500, 1000, 10000 pelotas) + int valid_scenarios[] = {1, 2, 3, 4, 5}; + scenario_ = valid_scenarios[rand() % 5]; + initBalls(scenario_); + return; + } + + // Aplicar impulso (10%) + accumulated_weight += DEMO_WEIGHT_IMPULSE; + if (random_value < accumulated_weight) { + pushBallsAwayFromGravity(); + return; + } + + // Toggle profundidad (3%) + accumulated_weight += DEMO_WEIGHT_DEPTH_ZOOM; + if (random_value < accumulated_weight) { + if (current_mode_ == SimulationMode::SHAPE) { + depth_zoom_enabled_ = !depth_zoom_enabled_; + } + return; + } + + // Cambiar escala de figura (2%) + accumulated_weight += DEMO_WEIGHT_SHAPE_SCALE; + if (random_value < accumulated_weight) { + if (current_mode_ == SimulationMode::SHAPE) { + int scale_action = rand() % 3; + if (scale_action == 0) { + shape_scale_factor_ += SHAPE_SCALE_STEP; + } else if (scale_action == 1) { + shape_scale_factor_ -= SHAPE_SCALE_STEP; + } else { + shape_scale_factor_ = SHAPE_SCALE_DEFAULT; + } + clampShapeScale(); + generateShape(); + } + return; + } + + // Cambiar sprite (2%) + accumulated_weight += DEMO_WEIGHT_SPRITE; + if (random_value < accumulated_weight) { + switchTexture(); + return; + } + } +} + +// Randomizar todo al iniciar modo DEMO +void Engine::randomizeOnDemoStart(bool is_lite) { + if (is_lite) { + // DEMO LITE: Solo randomizar física/figura + gravedad + // Elegir aleatoriamente entre modo física o figura + if (rand() % 2 == 0) { + // Modo física + if (current_mode_ == SimulationMode::SHAPE) { + toggleShapeMode(false); // Salir a física sin forzar gravedad + } + } else { + // Modo figura: elegir figura aleatoria + ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::WAVE_GRID, ShapeType::HELIX, + ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, + ShapeType::ICOSAHEDRON, ShapeType::ATOM}; + activateShape(shapes[rand() % 8]); + } + + // Randomizar gravedad: dirección + ON/OFF GravityDirection new_direction = static_cast(rand() % 4); changeGravityDirection(new_direction); - return; - } - - // Acción: Activar figura 3D (25%) - accumulated_weight += DEMO_WEIGHT_SHAPE; - if (random_value < accumulated_weight) { - // Elegir figura aleatoria (SPHERE a ATOM = 8 figuras) - ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::WAVE_GRID, ShapeType::HELIX, - ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, - ShapeType::ICOSAHEDRON, ShapeType::ATOM}; - int shape_index = rand() % 8; - activateShape(shapes[shape_index]); - return; - } - - // Acción: Cambiar tema (20%) - accumulated_weight += DEMO_WEIGHT_THEME; - if (random_value < accumulated_weight) { - ColorTheme new_theme = static_cast(rand() % 6); // 6 temas disponibles - startThemeTransition(new_theme); - return; - } - - // Acción: Cambiar escenario/número de pelotas (15%) - accumulated_weight += DEMO_WEIGHT_SCENARIO; - if (random_value < accumulated_weight) { - scenario_ = rand() % test_.size(); - initBalls(scenario_); - return; - } - - // Acción: Aplicar impulso (10%) - accumulated_weight += DEMO_WEIGHT_IMPULSE; - if (random_value < accumulated_weight) { - pushBallsAwayFromGravity(); - return; - } - - // Acción: Toggle profundidad (5%) - accumulated_weight += DEMO_WEIGHT_DEPTH_ZOOM; - if (random_value < accumulated_weight) { - if (current_mode_ == SimulationMode::SHAPE) { - depth_zoom_enabled_ = !depth_zoom_enabled_; + if (rand() % 2 == 0) { + toggleGravityOnOff(); // 50% probabilidad de desactivar gravedad } - return; - } - // Acción: Cambiar escala de figura (5%) - accumulated_weight += DEMO_WEIGHT_SHAPE_SCALE; - if (random_value < accumulated_weight) { - if (current_mode_ == SimulationMode::SHAPE) { - // Aleatorio: +1, -1, o reset - int scale_action = rand() % 3; - if (scale_action == 0) { - shape_scale_factor_ += SHAPE_SCALE_STEP; - } else if (scale_action == 1) { - shape_scale_factor_ -= SHAPE_SCALE_STEP; - } else { - shape_scale_factor_ = SHAPE_SCALE_DEFAULT; + } else { + // DEMO COMPLETO: Randomizar TODO + + // 1. Escenario (excluir índices 0, 6, 7) + int valid_scenarios[] = {1, 2, 3, 4, 5}; + scenario_ = valid_scenarios[rand() % 5]; + initBalls(scenario_); + + // 2. Tema + ColorTheme new_theme = static_cast(rand() % 6); + startThemeTransition(new_theme); + + // 3. Sprite + if (rand() % 2 == 0) { + switchTexture(); + } + + // 4. Física o Figura + if (rand() % 2 == 0) { + // Modo física + if (current_mode_ == SimulationMode::SHAPE) { + toggleShapeMode(false); } + } else { + // Modo figura: elegir figura aleatoria + ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::WAVE_GRID, ShapeType::HELIX, + ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, + ShapeType::ICOSAHEDRON, ShapeType::ATOM}; + activateShape(shapes[rand() % 8]); + + // 5. Profundidad (solo si estamos en figura) + if (rand() % 2 == 0) { + depth_zoom_enabled_ = !depth_zoom_enabled_; + } + + // 6. Escala de figura (aleatoria entre 0.5x y 2.0x) + shape_scale_factor_ = 0.5f + (rand() % 1500) / 1000.0f; clampShapeScale(); generateShape(); } - return; - } - // Acción: Cambiar sprite (5%) - accumulated_weight += DEMO_WEIGHT_SPRITE; - if (random_value < accumulated_weight) { - switchTexture(); - return; + // 7. Gravedad: dirección + ON/OFF + GravityDirection new_direction = static_cast(rand() % 4); + changeGravityDirection(new_direction); + if (rand() % 3 == 0) { // 33% probabilidad de desactivar gravedad + toggleGravityOnOff(); + } + } +} + +// Toggle gravedad ON/OFF para todas las pelotas +void Engine::toggleGravityOnOff() { + // Alternar entre activar/desactivar gravedad + bool first_ball_gravity_enabled = (balls_.empty() || balls_[0]->getGravityForce() > 0.0f); + + if (first_ball_gravity_enabled) { + // Desactivar gravedad + forceBallsGravityOff(); + } else { + // Activar gravedad + forceBallsGravityOn(); } } @@ -1372,12 +1585,14 @@ void Engine::switchTexture() { // Ajustar posiciones según el cambio de tamaño updateBallSizes(old_size, new_size); - // Mostrar texto informativo - std::string texture_name = (current_texture_index_ == 0) ? "NORMAL" : "SMALL"; - text_ = "SPRITE: " + texture_name; - text_pos_ = (current_screen_width_ - static_cast(text_.length() * 8)) / 2; - show_text_ = true; - text_init_time_ = SDL_GetTicks(); + // Mostrar texto informativo (solo si NO estamos en modo demo) + if (!demo_mode_enabled_ && !demo_lite_enabled_) { + std::string texture_name = (current_texture_index_ == 0) ? "NORMAL" : "SMALL"; + text_ = "SPRITE: " + texture_name; + text_pos_ = (current_screen_width_ - static_cast(text_.length() * 8)) / 2; + show_text_ = true; + text_init_time_ = SDL_GetTicks(); + } } // Sistema de Figuras 3D - Alternar entre modo física y última figura (Toggle con tecla F) @@ -1400,12 +1615,14 @@ void Engine::toggleShapeMode(bool force_gravity_on_exit) { forceBallsGravityOn(); } - // Mostrar texto informativo - text_ = "MODO FISICA"; - int text_width = static_cast(text_.length() * 8); - text_pos_ = (current_screen_width_ - text_width) / 2; - text_init_time_ = SDL_GetTicks(); - show_text_ = true; + // Mostrar texto informativo (solo si NO estamos en modo demo) + if (!demo_mode_enabled_ && !demo_lite_enabled_) { + text_ = "MODO FISICA"; + int text_width = static_cast(text_.length() * 8); + text_pos_ = (current_screen_width_ - text_width) / 2; + text_init_time_ = SDL_GetTicks(); + show_text_ = true; + } } } @@ -1460,8 +1677,8 @@ void Engine::activateShape(ShapeType type) { ball->enableRotoBallAttraction(true); } - // Mostrar texto informativo con nombre de figura - if (active_shape_) { + // Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo) + if (active_shape_ && !demo_mode_enabled_ && !demo_lite_enabled_) { text_ = std::string("MODO ") + active_shape_->getName(); int text_width = static_cast(text_.length() * 8); text_pos_ = (current_screen_width_ - text_width) / 2; diff --git a/source/engine.h b/source/engine.h index b3dc353..6315f3e 100644 --- a/source/engine.h +++ b/source/engine.h @@ -96,7 +96,8 @@ private: bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado // Sistema de Modo DEMO (auto-play) - bool demo_mode_enabled_ = false; // ¿Está activo el modo demo? + bool demo_mode_enabled_ = false; // ¿Está activo el modo demo completo? + bool demo_lite_enabled_ = false; // ¿Está activo el modo demo lite? float demo_timer_ = 0.0f; // Contador de tiempo para próxima acción float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos) @@ -128,7 +129,9 @@ private: // Sistema de Modo DEMO void updateDemoMode(); - void performDemoAction(); + void performDemoAction(bool is_lite); + void randomizeOnDemoStart(bool is_lite); + void toggleGravityOnOff(); // Sistema de transiciones LERP float lerp(float a, float b, float t) const { return a + (b - a) * t; }