Fix: Corregir inicialización de figuras en modo DEMO

Solucionar bug donde las pelotas aparecían en el centro sin formar
la figura geométrica al entrar en modo DEMO con SimulationMode::SHAPE.

## Problema
Al randomizar el estado en modo DEMO, si se elegía una figura:
1. Se configuraba el modo SHAPE
2. Se llamaba a changeScenario() que creaba pelotas en el centro
3. NO se llamaba a generateShape() para calcular los puntos de la figura
4. Resultado: pelotas amontonadas en el centro sin formar figura

## Solución
Reordenar operaciones en executeRandomizeOnDemoStart():
1. Decidir PRIMERO el modo (PHYSICS o SHAPE) antes de changeScenario
2. Si SHAPE: configurar figura manualmente sin generar puntos
3. Llamar a changeScenario() con el modo ya establecido
4. Después de changeScenario(), generar figura y activar atracción

Cambios adicionales:
- Arreglar warning de formato %zu en textrenderer.cpp (MinGW)
- Usar %lu con cast para size_t en logs

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-23 13:22:03 +02:00
parent 3f027d953c
commit a929df6b73

View File

@@ -1504,21 +1504,7 @@ void Engine::executeRandomizeOnDemoStart(bool is_lite) {
} else { } else {
// DEMO COMPLETO: Randomizar TODO // DEMO COMPLETO: Randomizar TODO
// 1. Escenario (excluir índices 0, 6, 7) // 1. Física o Figura (decidir PRIMERO antes de cambiar escenario)
int valid_scenarios[] = {1, 2, 3, 4, 5};
int new_scenario = valid_scenarios[rand() % 5];
scene_manager_->changeScenario(new_scenario, current_mode_);
// 2. Tema (elegir entre TODOS los 15 temas)
int random_theme_index = rand() % 15;
theme_manager_->switchToTheme(random_theme_index);
// 3. Sprite
if (rand() % 2 == 0) {
switchTextureInternal(false); // Suprimir notificación al activar modo DEMO
}
// 4. Física o Figura
if (rand() % 2 == 0) { if (rand() % 2 == 0) {
// Modo física // Modo física
if (current_mode_ == SimulationMode::SHAPE) { if (current_mode_ == SimulationMode::SHAPE) {
@@ -1527,20 +1513,83 @@ void Engine::executeRandomizeOnDemoStart(bool is_lite) {
} else { } else {
// Modo figura: elegir figura aleatoria (excluir PNG_SHAPE - es logo especial) // Modo figura: elegir figura aleatoria (excluir PNG_SHAPE - es logo especial)
ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::LISSAJOUS, ShapeType::HELIX, ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, ShapeType::ICOSAHEDRON, ShapeType::ATOM}; ShapeType shapes[] = {ShapeType::SPHERE, ShapeType::LISSAJOUS, ShapeType::HELIX, ShapeType::TORUS, ShapeType::CUBE, ShapeType::CYLINDER, ShapeType::ICOSAHEDRON, ShapeType::ATOM};
activateShapeInternal(shapes[rand() % 8]); ShapeType selected_shape = shapes[rand() % 8];
// 5. Profundidad (solo si estamos en figura) // Configurar figura SIN generar puntos (changeScenario lo hará después)
last_shape_type_ = selected_shape;
current_shape_type_ = selected_shape;
current_mode_ = SimulationMode::SHAPE;
// Crear instancia de la figura sin generar puntos todavía
switch (selected_shape) {
case ShapeType::SPHERE:
active_shape_ = std::make_unique<SphereShape>();
break;
case ShapeType::CUBE:
active_shape_ = std::make_unique<CubeShape>();
break;
case ShapeType::HELIX:
active_shape_ = std::make_unique<HelixShape>();
break;
case ShapeType::TORUS:
active_shape_ = std::make_unique<TorusShape>();
break;
case ShapeType::LISSAJOUS:
active_shape_ = std::make_unique<LissajousShape>();
break;
case ShapeType::CYLINDER:
active_shape_ = std::make_unique<CylinderShape>();
break;
case ShapeType::ICOSAHEDRON:
active_shape_ = std::make_unique<IcosahedronShape>();
break;
case ShapeType::ATOM:
active_shape_ = std::make_unique<AtomShape>();
break;
default:
active_shape_ = std::make_unique<SphereShape>();
break;
}
// Profundidad (solo si estamos en figura)
if (rand() % 2 == 0) { if (rand() % 2 == 0) {
depth_zoom_enabled_ = !depth_zoom_enabled_; depth_zoom_enabled_ = !depth_zoom_enabled_;
} }
// 6. Escala de figura (aleatoria entre 0.5x y 2.0x) // Escala de figura (aleatoria entre 0.5x y 2.0x)
shape_scale_factor_ = 0.5f + (rand() % 1500) / 1000.0f; shape_scale_factor_ = 0.5f + (rand() % 1500) / 1000.0f;
clampShapeScale(); clampShapeScale();
generateShape();
// NOTA: NO llamar a generateShape() ni activar atracción aquí
// changeScenario() creará las pelotas y luego llamará a generateShape()
} }
// 7. Gravedad: dirección + ON/OFF // 2. Escenario (excluir índices 0, 6, 7) - AHORA con current_mode_ ya establecido correctamente
int valid_scenarios[] = {1, 2, 3, 4, 5};
int new_scenario = valid_scenarios[rand() % 5];
scene_manager_->changeScenario(new_scenario, current_mode_);
// Si estamos en modo SHAPE, generar la figura y activar atracción
if (current_mode_ == SimulationMode::SHAPE) {
generateShape();
// Activar atracción física en las bolas nuevas
auto& balls = scene_manager_->getBallsMutable();
for (auto& ball : balls) {
ball->enableShapeAttraction(true);
}
}
// 3. Tema (elegir entre TODOS los 15 temas)
int random_theme_index = rand() % 15;
theme_manager_->switchToTheme(random_theme_index);
// 4. Sprite
if (rand() % 2 == 0) {
switchTextureInternal(false); // Suprimir notificación al activar modo DEMO
}
// 5. Gravedad: dirección + ON/OFF
GravityDirection new_direction = static_cast<GravityDirection>(rand() % 4); GravityDirection new_direction = static_cast<GravityDirection>(rand() % 4);
scene_manager_->changeGravityDirection(new_direction); scene_manager_->changeGravityDirection(new_direction);
if (rand() % 3 == 0) { // 33% probabilidad de desactivar gravedad if (rand() % 3 == 0) { // 33% probabilidad de desactivar gravedad