diff --git a/source/defines.h b/source/defines.h index 583f2aa..1a7aa97 100644 --- a/source/defines.h +++ b/source/defines.h @@ -80,6 +80,13 @@ enum class SimulationMode { SHAPE // Modo figura 3D (Shape polimórfico) }; +// Enum para modo de escalado en fullscreen (F5) +enum class ScalingMode { + INTEGER, // Escalado entero con barras negras (mantiene aspecto + píxel perfecto) + LETTERBOX, // Zoom hasta llenar una dimensión (una barra desaparece) + STRETCH // Estirar para llenar pantalla completa (puede distorsionar aspecto) +}; + // Configuración de RotoBall (esfera 3D rotante) constexpr float ROTOBALL_RADIUS_FACTOR = 0.333f; // Radio como proporción de altura de pantalla (80/240 ≈ 0.333) constexpr float ROTOBALL_ROTATION_SPEED_Y = 1.5f; // Velocidad rotación eje Y (rad/s) diff --git a/source/engine.cpp b/source/engine.cpp index 368b5b5..2d25fa3 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -474,6 +474,10 @@ void Engine::handleEvents() { } void Engine::render() { + // Limpiar framebuffer completamente (evita artefactos en barras negras al cambiar modos) + SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255); // Negro para barras de letterbox/integer + SDL_RenderClear(renderer_); + // Renderizar fondo degradado en lugar de color sólido renderGradientBackground(); @@ -541,11 +545,15 @@ void Engine::render() { dbg_print(text_pos_, 8, text_.c_str(), current.text_color_r, current.text_color_g, current.text_color_b); // Mostrar nombre del tema en castellano debajo del número de pelotas - 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 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 - // 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); + // 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); + } } // Debug display (solo si está activado con tecla H) @@ -795,17 +803,43 @@ void Engine::toggleIntegerScaling() { return; // No hacer nada si no estamos en fullscreen } - integer_scaling_enabled_ = !integer_scaling_enabled_; + // Ciclar entre los 3 modos: INTEGER → LETTERBOX → STRETCH → INTEGER + switch (current_scaling_mode_) { + case ScalingMode::INTEGER: + current_scaling_mode_ = ScalingMode::LETTERBOX; + break; + case ScalingMode::LETTERBOX: + current_scaling_mode_ = ScalingMode::STRETCH; + break; + case ScalingMode::STRETCH: + current_scaling_mode_ = ScalingMode::INTEGER; + break; + } // Aplicar el nuevo modo de escalado - SDL_RendererLogicalPresentation presentation = integer_scaling_enabled_ - ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE - : SDL_LOGICAL_PRESENTATION_STRETCH; + SDL_RendererLogicalPresentation presentation = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE; + const char* mode_name = "INTEGER"; + + switch (current_scaling_mode_) { + case ScalingMode::INTEGER: + presentation = SDL_LOGICAL_PRESENTATION_INTEGER_SCALE; + mode_name = "INTEGER"; + break; + case ScalingMode::LETTERBOX: + presentation = SDL_LOGICAL_PRESENTATION_LETTERBOX; + mode_name = "LETTERBOX"; + break; + case ScalingMode::STRETCH: + presentation = SDL_LOGICAL_PRESENTATION_STRETCH; + mode_name = "STRETCH"; + break; + } SDL_SetRenderLogicalPresentation(renderer_, SCREEN_WIDTH, SCREEN_HEIGHT, presentation); // Mostrar texto informativo - text_ = integer_scaling_enabled_ ? "SCALING: INTEGER" : "SCALING: STRETCH"; + text_ = "SCALING: "; + text_ += mode_name; text_pos_ = (current_screen_width_ - static_cast(text_.length() * 8)) / 2; show_text_ = true; text_init_time_ = SDL_GetTicks(); @@ -1102,6 +1136,13 @@ void Engine::startThemeTransition(ColorTheme new_theme) { target_theme_ = 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(); } Color Engine::getInterpolatedColor(size_t ball_index) const { diff --git a/source/engine.h b/source/engine.h index 13d2f50..0e74d6c 100644 --- a/source/engine.h +++ b/source/engine.h @@ -61,7 +61,7 @@ private: std::string vsync_text_ = "VSYNC ON"; bool fullscreen_enabled_ = false; bool real_fullscreen_enabled_ = false; - bool integer_scaling_enabled_ = true; // Escalado entero (mantiene aspecto) por defecto + ScalingMode current_scaling_mode_ = ScalingMode::INTEGER; // Modo de escalado actual (F5) // Auto-restart system Uint64 all_balls_stopped_start_time_ = 0; // Momento cuando todas se pararon