Mejorar DEMO MODE + Añadir DEMO LITE MODE (Tecla L)

MEJORAS DEMO MODE (Tecla D):
 **Randomización completa al activar**: escenario, tema, sprite, física/figura, gravedad, profundidad, escala
 **Excluye escenarios problemáticos**: 1, 50K, 100K pelotas (índices 0, 6, 7)
 **Nuevas acciones dinámicas**:
   - Toggle gravedad ON/OFF (8%)
   - Toggle física ↔ figura (12%)
   - Re-generar misma figura (8%)
 **Intervalos más rápidos**: 2-6s (antes 3-8s)
 **SIN TEXTOS** durante demo (solo "DEMO MODE")
 **Pesos rebalanceados**: Más variedad y dinamismo

NUEVO: DEMO LITE MODE (Tecla L):
 **Solo física/figuras**: NO cambia escenario, tema, sprite, profundidad, escala
 **Randomización inicial lite**: física/figura + gravedad
 **Acciones lite**:
   - Cambiar dirección gravedad (25%)
   - Toggle gravedad ON/OFF (20%)
   - Activar figura 3D (25%)
   - Toggle física ↔ figura (20%)
   - Aplicar impulso (10%)
 **Intervalos ultra-rápidos**: 1.5-4s
 **Display visual**: "DEMO LITE" en azul claro (128, 200, 255)
 **Mutuamente excluyente**: D y L no pueden estar activos a la vez

CAMBIOS TÉCNICOS:
- Nuevas constantes en defines.h: DEMO_LITE_* (intervalos + pesos)
- Nuevos métodos:
  * `randomizeOnDemoStart(bool is_lite)` - Randomización inicial
  * `toggleGravityOnOff()` - Activar/desactivar gravedad
- `performDemoAction()` ahora recibe parámetro `is_lite`
- Suprimidos textos en: setText(), startThemeTransition(), switchTexture(), toggleShapeMode(), activateShape()
- DEMO MODE nunca cambia dimensiones de ventana ni modo pantalla

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 11:47:20 +02:00
parent d0b144dddc
commit 0d49a6e814
3 changed files with 353 additions and 118 deletions

View File

@@ -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_STEP = 0.1f; // Incremento por pulsación
constexpr float SHAPE_SCALE_DEFAULT = 1.0f; // Escala por defecto (100%) constexpr float SHAPE_SCALE_DEFAULT = 1.0f; // Escala por defecto (100%)
// Configuración de Modo DEMO (auto-play) // Configuración de Modo DEMO (auto-play completo)
constexpr float DEMO_ACTION_INTERVAL_MIN = 3.0f; // Tiempo mínimo entre acciones (segundos) constexpr float DEMO_ACTION_INTERVAL_MIN = 2.0f; // Tiempo mínimo entre acciones (segundos)
constexpr float DEMO_ACTION_INTERVAL_MAX = 8.0f; // Tiempo máximo 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) // Pesos de probabilidad DEMO MODE (valores relativos, se normalizan)
constexpr int DEMO_WEIGHT_GRAVITY = 15; // Cambiar dirección gravedad (15%) constexpr int DEMO_WEIGHT_GRAVITY_DIR = 10; // Cambiar dirección gravedad (10%)
constexpr int DEMO_WEIGHT_SHAPE = 25; // Activar figura 3D (25%) constexpr int DEMO_WEIGHT_GRAVITY_TOGGLE = 8; // Toggle gravedad ON/OFF (8%)
constexpr int DEMO_WEIGHT_THEME = 20; // Cambiar tema de colores (20%) constexpr int DEMO_WEIGHT_SHAPE = 20; // Activar figura 3D (20%)
constexpr int DEMO_WEIGHT_SCENARIO = 15; // Cambiar número de pelotas (15%) 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_IMPULSE = 10; // Aplicar impulso (SPACE) (10%)
constexpr int DEMO_WEIGHT_DEPTH_ZOOM = 5; // Toggle profundidad (5%) constexpr int DEMO_WEIGHT_DEPTH_ZOOM = 3; // Toggle profundidad (3%)
constexpr int DEMO_WEIGHT_SHAPE_SCALE = 5; // Cambiar escala figura (5%) constexpr int DEMO_WEIGHT_SHAPE_SCALE = 2; // Cambiar escala figura (2%)
constexpr int DEMO_WEIGHT_SPRITE = 5; // Cambiar sprite (5%) constexpr int DEMO_WEIGHT_SPRITE = 2; // Cambiar sprite (2%)
// TOTAL: 100 (se pueden ajustar para priorizar acciones) // 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 constexpr float PI = 3.14159265358979323846f; // Constante PI

View File

@@ -469,11 +469,17 @@ void Engine::handleEvents() {
toggleIntegerScaling(); toggleIntegerScaling();
break; break;
// Toggle Modo DEMO (auto-play) // Toggle Modo DEMO COMPLETO (auto-play)
case SDLK_D: case SDLK_D:
demo_mode_enabled_ = !demo_mode_enabled_; demo_mode_enabled_ = !demo_mode_enabled_;
if (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; demo_timer_ = 0.0f;
float interval_range = DEMO_ACTION_INTERVAL_MAX - DEMO_ACTION_INTERVAL_MIN; 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; 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(); text_init_time_ = SDL_GetTicks();
} }
break; 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 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_) { if (demo_mode_enabled_) {
// Centrar texto horizontalmente // Centrar texto horizontalmente
const char* demo_text = "DEMO MODE"; const char* demo_text = "DEMO MODE";
int demo_text_width = static_cast<int>(strlen(demo_text) * 8); // 8 píxeles por carácter int demo_text_width = static_cast<int>(strlen(demo_text) * 8); // 8 píxeles por carácter
int demo_x = (current_screen_width_ - demo_text_width) / 2; int demo_x = (current_screen_width_ - demo_text_width) / 2;
dbg_print(demo_x, 8, demo_text, 255, 128, 0); // Naranja brillante 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<int>(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_); SDL_RenderPresent(renderer_);
@@ -675,6 +714,9 @@ void Engine::initBalls(int value) {
} }
void Engine::setText() { void Engine::setText() {
// Suprimir textos durante modos demo
if (demo_mode_enabled_ || demo_lite_enabled_) return;
int num_balls = test_.at(scenario_); int num_balls = test_.at(scenario_);
if (num_balls == 1) { if (num_balls == 1) {
text_ = "1 PELOTA"; text_ = "1 PELOTA";
@@ -1167,12 +1209,14 @@ void Engine::startThemeTransition(ColorTheme new_theme) {
transitioning_ = true; transitioning_ = true;
transition_progress_ = 0.0f; transition_progress_ = 0.0f;
// Mostrar nombre del tema (igual que selección directa con KP_1-6) // Mostrar nombre del tema (solo si NO estamos en modo demo)
ThemeColors& theme = themes_[static_cast<int>(new_theme)]; if (!demo_mode_enabled_ && !demo_lite_enabled_) {
text_ = theme.name_es; ThemeColors& theme = themes_[static_cast<int>(new_theme)];
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_ = theme.name_es;
show_text_ = true; text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2;
text_init_time_ = SDL_GetTicks(); show_text_ = true;
text_init_time_ = SDL_GetTicks();
}
} }
Color Engine::getInterpolatedColor(size_t ball_index) const { 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) // Sistema de Modo DEMO (auto-play)
void Engine::updateDemoMode() { 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 // Actualizar timer
demo_timer_ += delta_time_; demo_timer_ += delta_time_;
// Si es hora de ejecutar acción // Si es hora de ejecutar acción
if (demo_timer_ >= demo_next_action_time_) { 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 // Resetear timer y calcular próximo intervalo aleatorio
demo_timer_ = 0.0f; 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() { void Engine::performDemoAction(bool is_lite) {
// Calcular suma total de pesos int TOTAL_WEIGHT;
const int TOTAL_WEIGHT = DEMO_WEIGHT_GRAVITY + DEMO_WEIGHT_SHAPE + DEMO_WEIGHT_THEME int random_value;
+ 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
int accumulated_weight = 0; int accumulated_weight = 0;
// Acción: Cambiar gravedad (15%) if (is_lite) {
accumulated_weight += DEMO_WEIGHT_GRAVITY; // DEMO LITE: Solo física/figuras
if (random_value < accumulated_weight) { 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<GravityDirection>(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<GravityDirection>(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<ColorTheme>(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<GravityDirection>(rand() % 4); GravityDirection new_direction = static_cast<GravityDirection>(rand() % 4);
changeGravityDirection(new_direction); changeGravityDirection(new_direction);
return; if (rand() % 2 == 0) {
} toggleGravityOnOff(); // 50% probabilidad de desactivar gravedad
// 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<ColorTheme>(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_;
} }
return;
}
// Acción: Cambiar escala de figura (5%) } else {
accumulated_weight += DEMO_WEIGHT_SHAPE_SCALE; // DEMO COMPLETO: Randomizar TODO
if (random_value < accumulated_weight) {
if (current_mode_ == SimulationMode::SHAPE) { // 1. Escenario (excluir índices 0, 6, 7)
// Aleatorio: +1, -1, o reset int valid_scenarios[] = {1, 2, 3, 4, 5};
int scale_action = rand() % 3; scenario_ = valid_scenarios[rand() % 5];
if (scale_action == 0) { initBalls(scenario_);
shape_scale_factor_ += SHAPE_SCALE_STEP;
} else if (scale_action == 1) { // 2. Tema
shape_scale_factor_ -= SHAPE_SCALE_STEP; ColorTheme new_theme = static_cast<ColorTheme>(rand() % 6);
} else { startThemeTransition(new_theme);
shape_scale_factor_ = SHAPE_SCALE_DEFAULT;
// 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(); clampShapeScale();
generateShape(); generateShape();
} }
return;
}
// Acción: Cambiar sprite (5%) // 7. Gravedad: dirección + ON/OFF
accumulated_weight += DEMO_WEIGHT_SPRITE; GravityDirection new_direction = static_cast<GravityDirection>(rand() % 4);
if (random_value < accumulated_weight) { changeGravityDirection(new_direction);
switchTexture(); if (rand() % 3 == 0) { // 33% probabilidad de desactivar gravedad
return; 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 // Ajustar posiciones según el cambio de tamaño
updateBallSizes(old_size, new_size); updateBallSizes(old_size, new_size);
// Mostrar texto informativo // Mostrar texto informativo (solo si NO estamos en modo demo)
std::string texture_name = (current_texture_index_ == 0) ? "NORMAL" : "SMALL"; if (!demo_mode_enabled_ && !demo_lite_enabled_) {
text_ = "SPRITE: " + texture_name; std::string texture_name = (current_texture_index_ == 0) ? "NORMAL" : "SMALL";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_ = "SPRITE: " + texture_name;
show_text_ = true; text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2;
text_init_time_ = SDL_GetTicks(); show_text_ = true;
text_init_time_ = SDL_GetTicks();
}
} }
// Sistema de Figuras 3D - Alternar entre modo física y última figura (Toggle con tecla F) // 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(); forceBallsGravityOn();
} }
// Mostrar texto informativo // Mostrar texto informativo (solo si NO estamos en modo demo)
text_ = "MODO FISICA"; if (!demo_mode_enabled_ && !demo_lite_enabled_) {
int text_width = static_cast<int>(text_.length() * 8); text_ = "MODO FISICA";
text_pos_ = (current_screen_width_ - text_width) / 2; int text_width = static_cast<int>(text_.length() * 8);
text_init_time_ = SDL_GetTicks(); text_pos_ = (current_screen_width_ - text_width) / 2;
show_text_ = true; text_init_time_ = SDL_GetTicks();
show_text_ = true;
}
} }
} }
@@ -1460,8 +1677,8 @@ void Engine::activateShape(ShapeType type) {
ball->enableRotoBallAttraction(true); ball->enableRotoBallAttraction(true);
} }
// Mostrar texto informativo con nombre de figura // Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo)
if (active_shape_) { if (active_shape_ && !demo_mode_enabled_ && !demo_lite_enabled_) {
text_ = std::string("MODO ") + active_shape_->getName(); text_ = std::string("MODO ") + active_shape_->getName();
int text_width = static_cast<int>(text_.length() * 8); int text_width = static_cast<int>(text_.length() * 8);
text_pos_ = (current_screen_width_ - text_width) / 2; text_pos_ = (current_screen_width_ - text_width) / 2;

View File

@@ -96,7 +96,8 @@ private:
bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado bool depth_zoom_enabled_ = true; // Zoom por profundidad Z activado
// Sistema de Modo DEMO (auto-play) // 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_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) float demo_next_action_time_ = 0.0f; // Tiempo aleatorio hasta próxima acción (segundos)
@@ -128,7 +129,9 @@ private:
// Sistema de Modo DEMO // Sistema de Modo DEMO
void updateDemoMode(); void updateDemoMode();
void performDemoAction(); void performDemoAction(bool is_lite);
void randomizeOnDemoStart(bool is_lite);
void toggleGravityOnOff();
// Sistema de transiciones LERP // Sistema de transiciones LERP
float lerp(float a, float b, float t) const { return a + (b - a) * t; } float lerp(float a, float b, float t) const { return a + (b - a) * t; }