From ebeec288eedf21b0792054ed108a3ef1c910a1b3 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Sun, 5 Oct 2025 20:31:31 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Crash=20al=20acceder=20a=20themes[]=20co?= =?UTF-8?q?n=20=C3=ADndices=20de=20temas=20din=C3=A1micos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PROBLEMA: Crash (segfault) al activar temas dinámicos OCEAN WAVES (tecla 9) y NEON PULSE (tecla 0). Funcionamiento correcto con SUNRISE (tecla 8). CAUSA: Múltiples lugares del código accedían a themes_[current_theme_] sin verificar si current_theme_ era un tema dinámico (índices 7/8/9). El array themes_[] solo tiene 7 elementos (índices 0-6): - SUNSET, OCEAN, NEON, FOREST, RGB, MONOCHROME, LAVENDER Los temas dinámicos están en dynamic_themes_[] (índices 0-2): - DYNAMIC_1=7 (SUNRISE), DYNAMIC_2=8 (OCEAN WAVES), DYNAMIC_3=9 (NEON PULSE) Acceder a themes_[7/8/9] causaba out-of-bounds → puntero inválido → crash en strlen(name_es). PUNTOS DE FALLO IDENTIFICADOS: 1. render() línea ~738: Mostrar nombre del tema en pantalla 2. render() línea ~808: Debug display "THEME XXX" 3. initBalls() línea ~864: Seleccionar colores para pelotas nuevas SOLUCIÓN: ✅ Añadir verificación dynamic_theme_active_ antes de acceder a arrays ✅ Si tema dinámico: usar dynamic_themes_[current_dynamic_theme_index_] ✅ Si tema estático: usar themes_[static_cast(current_theme_)] CORRECCIONES APLICADAS: - render() (show_text_): Obtener color y nombre desde DynamicTheme - render() (show_debug_): Obtener name_en desde DynamicTheme - initBalls(): Seleccionar colores desde keyframe actual de DynamicTheme RESULTADO: - ✅ SUNRISE (Numpad 8) funciona correctamente - ✅ OCEAN WAVES (Numpad 9) funciona correctamente (antes crasheaba) - ✅ NEON PULSE (Numpad 0) funciona correctamente (antes crasheaba) - ✅ Temas estáticos (1-7) siguen funcionando normalmente 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- source/engine.cpp | 62 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 15 deletions(-) diff --git a/source/engine.cpp b/source/engine.cpp index 1eb4ea0..7e3d87a 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -733,22 +733,38 @@ void Engine::render() { } if (show_text_) { - // Obtener tema actual - int theme_idx = static_cast(current_theme_); - const ThemeColors& current = themes_[theme_idx]; + // Obtener datos del tema actual (estático o dinámico) + int text_color_r, text_color_g, text_color_b; + const char* theme_name_es = nullptr; + + if (dynamic_theme_active_ && current_dynamic_theme_index_ >= 0) { + // Tema dinámico activo + const DynamicTheme& dyn_theme = dynamic_themes_[current_dynamic_theme_index_]; + text_color_r = dyn_theme.text_color_r; + text_color_g = dyn_theme.text_color_g; + text_color_b = dyn_theme.text_color_b; + theme_name_es = dyn_theme.name_es; + } else { + // Tema estático + int theme_idx = static_cast(current_theme_); + const ThemeColors& current = themes_[theme_idx]; + text_color_r = current.text_color_r; + text_color_g = current.text_color_g; + text_color_b = current.text_color_b; + theme_name_es = current.name_es; + } // Texto del número de pelotas con color del tema - dbg_print(text_pos_, 8, text_.c_str(), current.text_color_r, current.text_color_g, current.text_color_b); + dbg_print(text_pos_, 8, text_.c_str(), text_color_r, text_color_g, text_color_b); // Mostrar nombre del tema en castellano debajo del número de pelotas - // (solo si text_ NO es ya el nombre del tema actual o destino, para evitar duplicación durante LERP) - const ThemeColors& target = themes_[static_cast(target_theme_)]; - if (text_ != current.name_es && text_ != target.name_es) { - int theme_text_width = static_cast(strlen(current.name_es) * 8); // 8 píxeles por carácter - int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente + // (solo si text_ NO es ya el nombre del tema, para evitar duplicación) + if (theme_name_es != nullptr && text_ != theme_name_es) { + int theme_text_width = static_cast(strlen(theme_name_es) * 8); // 8 píxeles por carácter + int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente // Texto del nombre del tema con el mismo color - dbg_print(theme_x, 24, current.name_es, current.text_color_r, current.text_color_g, current.text_color_b); + dbg_print(theme_x, 24, theme_name_es, text_color_r, text_color_g, text_color_b); } } @@ -789,7 +805,12 @@ void Engine::render() { } // Debug: Mostrar tema actual - std::string theme_text = std::string("THEME ") + themes_[static_cast(current_theme_)].name_en; + std::string theme_text; + if (dynamic_theme_active_ && current_dynamic_theme_index_ >= 0) { + theme_text = std::string("THEME ") + dynamic_themes_[current_dynamic_theme_index_].name_en; + } else { + theme_text = std::string("THEME ") + themes_[static_cast(current_theme_)].name_en; + } dbg_print(8, 64, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema // Debug: Mostrar modo de simulación actual @@ -844,10 +865,21 @@ void Engine::initBalls(int value) { const float X = (rand() % spawn_zone_width) + margin; // Posición inicial en X const float VX = (((rand() % 20) + 10) * 0.1f) * SIGN; // Velocidad en X const float VY = ((rand() % 60) - 30) * 0.1f; // Velocidad en Y - // Seleccionar color de la paleta del tema actual - ThemeColors& theme = themes_[static_cast(current_theme_)]; - int color_index = rand() % theme.ball_colors.size(); // Cantidad variable de colores por tema - const Color COLOR = theme.ball_colors[color_index]; + + // Seleccionar color de la paleta del tema actual (estático o dinámico) + Color COLOR; + if (dynamic_theme_active_ && current_dynamic_theme_index_ >= 0) { + // Tema dinámico: usar colores del keyframe actual + const DynamicTheme& dyn_theme = dynamic_themes_[current_dynamic_theme_index_]; + const DynamicThemeKeyframe& current_kf = dyn_theme.keyframes[current_keyframe_index_]; + int color_index = rand() % current_kf.ball_colors.size(); + COLOR = current_kf.ball_colors[color_index]; + } else { + // Tema estático + ThemeColors& theme = themes_[static_cast(current_theme_)]; + int color_index = rand() % theme.ball_colors.size(); + COLOR = theme.ball_colors[color_index]; + } // Generar factor de masa aleatorio (0.7 = ligera, 1.3 = pesada) float mass_factor = GRAVITY_MASS_MIN + (rand() % 1000) / 1000.0f * (GRAVITY_MASS_MAX - GRAVITY_MASS_MIN); balls_.emplace_back(std::make_unique(X, VX, VY, COLOR, texture_, current_screen_width_, current_screen_height_, current_ball_size_, current_gravity_, mass_factor));