Migración de dbgtxt a SDL_TTF + conversión de textos a mixed case

Sistema de texto:
- Reemplazado dbgtxt.cpp (bitmap 8x8) por TextRenderer (SDL_TTF)
- Creado source/text/ con TextRenderer class
- Añadidas fuentes TrueType en data/fonts/
- Implementados dos TextRenderer (display + debug) con escalado dinámico
- Constantes configurables: TEXT_FONT_PATH, TEXT_BASE_SIZE, TEXT_ANTIALIASING

Correcciones de centrado:
- Reemplazado text.length() * 8 por text_renderer_.getTextWidth() en ~25 lugares
- Texto de tecla F ahora se centra correctamente
- Texto de modo (Demo/Logo/Lite) fijo en tercera fila del HUD debug
- Implementado espaciado dinámico con getTextHeight()

Conversión a mixed case:
- ~26 textos de display cambiados de ALL CAPS a mixed case
- 15 nombres de temas en theme_manager.cpp convertidos a mixed case
- Ejemplos: "FPS" → "fps", "MODO FISICA" → "Modo Física", "DEMO MODE ON" → "Modo Demo: On"
- Temas: "SUNSET" → "Sunset", "OCEANO" → "Océano", etc.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-09 20:18:01 +02:00
parent c50ecbc02a
commit f00b08b6be
14 changed files with 338 additions and 138 deletions
+14 -6
View File
@@ -16,8 +16,16 @@ if (NOT SDL3_FOUND)
message(FATAL_ERROR "SDL3 no encontrado. Por favor, verifica su instalación.") message(FATAL_ERROR "SDL3 no encontrado. Por favor, verifica su instalación.")
endif() endif()
# Buscar SDL3_ttf
find_package(SDL3_ttf REQUIRED)
# Si no se encuentra SDL3_ttf, generar un error
if (NOT SDL3_ttf_FOUND)
message(FATAL_ERROR "SDL3_ttf no encontrado. Por favor, verifica su instalación.")
endif()
# Archivos fuente (excluir main_old.cpp) # Archivos fuente (excluir main_old.cpp)
file(GLOB SOURCE_FILES source/*.cpp source/external/*.cpp source/shapes/*.cpp source/themes/*.cpp) file(GLOB SOURCE_FILES source/*.cpp source/external/*.cpp source/shapes/*.cpp source/themes/*.cpp source/text/*.cpp)
list(REMOVE_ITEM SOURCE_FILES "${CMAKE_SOURCE_DIR}/source/main_old.cpp") list(REMOVE_ITEM SOURCE_FILES "${CMAKE_SOURCE_DIR}/source/main_old.cpp")
# Comprobar si se encontraron archivos fuente # Comprobar si se encontraron archivos fuente
@@ -28,17 +36,17 @@ endif()
# Detectar la plataforma y configuraciones específicas # Detectar la plataforma y configuraciones específicas
if(WIN32) if(WIN32)
set(PLATFORM windows) set(PLATFORM windows)
set(LINK_LIBS ${SDL3_LIBRARIES} mingw32 ws2_32) set(LINK_LIBS SDL3::SDL3 SDL3_ttf::SDL3_ttf mingw32 ws2_32)
elseif(UNIX AND NOT APPLE) elseif(UNIX AND NOT APPLE)
set(PLATFORM linux) set(PLATFORM linux)
set(LINK_LIBS ${SDL3_LIBRARIES}) set(LINK_LIBS SDL3::SDL3 SDL3_ttf::SDL3_ttf)
elseif(APPLE) elseif(APPLE)
set(PLATFORM macos) set(PLATFORM macos)
set(LINK_LIBS ${SDL3_LIBRARIES}) set(LINK_LIBS SDL3::SDL3 SDL3_ttf::SDL3_ttf)
endif() endif()
# Incluir directorios de SDL3 # Incluir directorios de SDL3 y SDL3_ttf
include_directories(${SDL3_INCLUDE_DIRS}) include_directories(${SDL3_INCLUDE_DIRS} ${SDL3_ttf_INCLUDE_DIRS})
# Añadir el ejecutable reutilizando el nombre del proyecto # Añadir el ejecutable reutilizando el nombre del proyecto
add_executable(${PROJECT_NAME} ${SOURCE_FILES}) add_executable(${PROJECT_NAME} ${SOURCE_FILES})
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+115 -79
View File
@@ -22,7 +22,6 @@
#endif #endif
#include "ball.h" // for Ball #include "ball.h" // for Ball
#include "external/dbgtxt.h" // for dbg_init, dbg_print
#include "external/mouse.h" // for Mouse namespace #include "external/mouse.h" // for Mouse namespace
#include "external/texture.h" // for Texture #include "external/texture.h" // for Texture
#include "shapes/atom_shape.h" // for AtomShape #include "shapes/atom_shape.h" // for AtomShape
@@ -203,7 +202,22 @@ bool Engine::initialize(int width, int height, int zoom, bool fullscreen) {
current_ball_size_ = texture_->getWidth(); // Obtener tamaño dinámicamente current_ball_size_ = texture_->getWidth(); // Obtener tamaño dinámicamente
srand(static_cast<unsigned>(time(nullptr))); srand(static_cast<unsigned>(time(nullptr)));
dbg_init(renderer_);
// Calcular tamaño de fuente escalado según resolución
// Usa las constantes configurables de la clase
int font_size = (base_screen_height_ * TEXT_BASE_SIZE) / 240;
// Inicializar TextRenderer para display (texto centrado)
if (!text_renderer_.init(renderer_, TEXT_FONT_PATH, font_size, TEXT_ANTIALIASING)) {
SDL_Log("Error al inicializar TextRenderer (display)");
return false;
}
// Inicializar TextRenderer para debug (HUD)
if (!text_renderer_debug_.init(renderer_, TEXT_FONT_PATH, font_size, TEXT_ANTIALIASING)) {
SDL_Log("Error al inicializar TextRenderer (debug)");
return false;
}
// Inicializar ThemeManager // Inicializar ThemeManager
theme_manager_ = std::make_unique<ThemeManager>(); theme_manager_ = std::make_unique<ThemeManager>();
@@ -270,7 +284,7 @@ void Engine::update() {
fps_current_ = fps_frame_count_; fps_current_ = fps_frame_count_;
fps_frame_count_ = 0; fps_frame_count_ = 0;
fps_last_time_ = current_time; fps_last_time_ = current_time;
fps_text_ = "FPS: " + std::to_string(fps_current_); fps_text_ = "fps: " + std::to_string(fps_current_);
} }
// Bifurcar actualización según modo activo // Bifurcar actualización según modo activo
@@ -435,7 +449,7 @@ void Engine::handleEvents() {
// Mostrar nombre del tema (solo si NO estamos en modo demo) // Mostrar nombre del tema (solo si NO estamos en modo demo)
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -450,7 +464,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(theme_index); theme_manager_->switchToTheme(theme_index);
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -464,7 +478,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(theme_index); theme_manager_->switchToTheme(theme_index);
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -478,7 +492,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(theme_index); theme_manager_->switchToTheme(theme_index);
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -492,7 +506,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(theme_index); theme_manager_->switchToTheme(theme_index);
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -506,7 +520,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(theme_index); theme_manager_->switchToTheme(theme_index);
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -519,7 +533,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(5); // MONOCHROME theme_manager_->switchToTheme(5); // MONOCHROME
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -532,7 +546,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(6); // LAVENDER theme_manager_->switchToTheme(6); // LAVENDER
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -545,7 +559,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(7); // CRIMSON theme_manager_->switchToTheme(7); // CRIMSON
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -558,7 +572,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(8); // EMERALD theme_manager_->switchToTheme(8); // EMERALD
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -571,7 +585,7 @@ void Engine::handleEvents() {
theme_manager_->switchToTheme(9); // SUNRISE theme_manager_->switchToTheme(9); // SUNRISE
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = theme_manager_->getCurrentThemeNameES(); text_ = theme_manager_->getCurrentThemeNameES();
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -585,8 +599,8 @@ void Engine::handleEvents() {
// Mostrar feedback visual (solo si NO estamos en modo demo) // Mostrar feedback visual (solo si NO estamos en modo demo)
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = (theme_page_ == 0) ? "PAGINA 1" : "PAGINA 2"; text_ = (theme_page_ == 0) ? "Página 1" : "Página 2";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -602,7 +616,7 @@ void Engine::handleEvents() {
if (current_mode_ == SimulationMode::SHAPE) { if (current_mode_ == SimulationMode::SHAPE) {
shape_scale_factor_ += SHAPE_SCALE_STEP; shape_scale_factor_ += SHAPE_SCALE_STEP;
clampShapeScale(); clampShapeScale();
text_ = "SCALE " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%"; text_ = "Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
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;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
@@ -614,7 +628,7 @@ void Engine::handleEvents() {
if (current_mode_ == SimulationMode::SHAPE) { if (current_mode_ == SimulationMode::SHAPE) {
shape_scale_factor_ -= SHAPE_SCALE_STEP; shape_scale_factor_ -= SHAPE_SCALE_STEP;
clampShapeScale(); clampShapeScale();
text_ = "SCALE " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%"; text_ = "Escala " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
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;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
@@ -625,7 +639,7 @@ void Engine::handleEvents() {
case SDLK_KP_MULTIPLY: case SDLK_KP_MULTIPLY:
if (current_mode_ == SimulationMode::SHAPE) { if (current_mode_ == SimulationMode::SHAPE) {
shape_scale_factor_ = SHAPE_SCALE_DEFAULT; shape_scale_factor_ = SHAPE_SCALE_DEFAULT;
text_ = "SCALE RESET (100%)"; text_ = "Escala reiniciada (100%)";
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;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
@@ -636,7 +650,7 @@ void Engine::handleEvents() {
case SDLK_KP_DIVIDE: case SDLK_KP_DIVIDE:
if (current_mode_ == SimulationMode::SHAPE) { if (current_mode_ == SimulationMode::SHAPE) {
depth_zoom_enabled_ = !depth_zoom_enabled_; depth_zoom_enabled_ = !depth_zoom_enabled_;
text_ = depth_zoom_enabled_ ? "DEPTH ZOOM ON" : "DEPTH ZOOM OFF"; text_ = depth_zoom_enabled_ ? "Zoom profundidad: On" : "Zoom profundidad: Off";
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;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
@@ -722,16 +736,16 @@ void Engine::handleEvents() {
if (current_app_mode_ == AppMode::DEMO) { if (current_app_mode_ == AppMode::DEMO) {
// Desactivar DEMO → MANUAL // Desactivar DEMO → MANUAL
setState(AppMode::MANUAL); setState(AppMode::MANUAL);
text_ = "DEMO MODE OFF"; text_ = "Modo Demo: Off";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} else { } else {
// Activar DEMO (desde cualquier otro modo) // Activar DEMO (desde cualquier otro modo)
setState(AppMode::DEMO); setState(AppMode::DEMO);
randomizeOnDemoStart(false); randomizeOnDemoStart(false);
text_ = "DEMO MODE ON"; text_ = "Modo Demo: On";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -743,16 +757,16 @@ void Engine::handleEvents() {
if (current_app_mode_ == AppMode::DEMO_LITE) { if (current_app_mode_ == AppMode::DEMO_LITE) {
// Desactivar DEMO_LITE → MANUAL // Desactivar DEMO_LITE → MANUAL
setState(AppMode::MANUAL); setState(AppMode::MANUAL);
text_ = "DEMO LITE OFF"; text_ = "Modo Demo Lite: Off";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} else { } else {
// Activar DEMO_LITE (desde cualquier otro modo) // Activar DEMO_LITE (desde cualquier otro modo)
setState(AppMode::DEMO_LITE); setState(AppMode::DEMO_LITE);
randomizeOnDemoStart(true); randomizeOnDemoStart(true);
text_ = "DEMO LITE ON"; text_ = "Modo Demo Lite: On";
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -763,11 +777,11 @@ void Engine::handleEvents() {
toggleLogoMode(); toggleLogoMode();
// Mostrar texto informativo // Mostrar texto informativo
if (current_app_mode_ == AppMode::LOGO) { if (current_app_mode_ == AppMode::LOGO) {
text_ = "LOGO MODE ON"; text_ = "Modo Logo: On";
} else { } else {
text_ = "LOGO MODE OFF"; text_ = "Modo Logo: Off";
} }
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
break; break;
@@ -875,91 +889,115 @@ void Engine::render() {
theme_manager_->getCurrentThemeTextColor(text_color_r, text_color_g, text_color_b); theme_manager_->getCurrentThemeTextColor(text_color_r, text_color_g, text_color_b);
const char* theme_name_es = theme_manager_->getCurrentThemeNameES(); const char* theme_name_es = theme_manager_->getCurrentThemeNameES();
// Calcular espaciado dinámico
int line_height = text_renderer_.getTextHeight();
int margin = 8;
// Texto del número de pelotas con color del tema // Texto del número de pelotas con color del tema
dbg_print(text_pos_, 8, text_.c_str(), text_color_r, text_color_g, text_color_b); text_renderer_.print(text_pos_, margin, text_.c_str(), text_color_r, text_color_g, text_color_b);
// Mostrar nombre del tema en castellano debajo del número de pelotas // Mostrar nombre del tema en castellano debajo del número de pelotas
// (solo si text_ NO es ya el nombre del tema, para evitar duplicación) // (solo si text_ NO es ya el nombre del tema, para evitar duplicación)
if (theme_name_es != nullptr && text_ != theme_name_es) { if (theme_name_es != nullptr && text_ != theme_name_es) {
int theme_text_width = static_cast<int>(strlen(theme_name_es) * 8); // 8 píxeles por carácter int theme_text_width = text_renderer_.getTextWidth(theme_name_es);
int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente int theme_x = (current_screen_width_ - theme_text_width) / 2; // Centrar horizontalmente
int theme_y = margin + line_height; // Espaciado dinámico
// Texto del nombre del tema con el mismo color // Texto del nombre del tema con el mismo color
dbg_print(theme_x, 24, theme_name_es, text_color_r, text_color_g, text_color_b); text_renderer_.print(theme_x, theme_y, theme_name_es, text_color_r, text_color_g, text_color_b);
} }
} }
// Debug display (solo si está activado con tecla H) // Debug display (solo si está activado con tecla H)
if (show_debug_) { if (show_debug_) {
// Obtener altura de línea para espaciado dinámico (usando fuente debug)
int line_height = text_renderer_debug_.getTextHeight();
int margin = 8; // Margen constante
int current_y = margin; // Y inicial
// Mostrar contador de FPS en esquina superior derecha // Mostrar contador de FPS en esquina superior derecha
int fps_text_width = static_cast<int>(fps_text_.length() * 8); // 8 píxeles por carácter int fps_text_width = text_renderer_debug_.getTextWidth(fps_text_.c_str());
int fps_x = current_screen_width_ - fps_text_width - 8; // 8 píxeles de margen int fps_x = current_screen_width_ - fps_text_width - margin;
dbg_print(fps_x, 8, fps_text_.c_str(), 255, 255, 0); // Amarillo para distinguir text_renderer_debug_.print(fps_x, current_y, fps_text_.c_str(), 255, 255, 0); // Amarillo
// Mostrar estado V-Sync en esquina superior izquierda // Mostrar estado V-Sync en esquina superior izquierda
dbg_print(8, 8, vsync_text_.c_str(), 0, 255, 255); // Cian para distinguir text_renderer_debug_.print(margin, current_y, vsync_text_.c_str(), 0, 255, 255); // Cian
current_y += line_height;
// Debug: Mostrar valores de la primera pelota (si existe) // Debug: Mostrar valores de la primera pelota (si existe)
if (!balls_.empty()) { if (!balls_.empty()) {
// Línea 1: Gravedad (solo números enteros) // Línea 1: Gravedad
int grav_int = static_cast<int>(balls_[0]->getGravityForce()); int grav_int = static_cast<int>(balls_[0]->getGravityForce());
std::string grav_text = "GRAV " + std::to_string(grav_int); std::string grav_text = "Gravedad: " + std::to_string(grav_int);
dbg_print(8, 24, grav_text.c_str(), 255, 0, 255); // Magenta para debug text_renderer_debug_.print(margin, current_y, grav_text.c_str(), 255, 0, 255); // Magenta
current_y += line_height;
// Línea 2: Velocidad Y (solo números enteros) // Línea 2: Velocidad Y
int vy_int = static_cast<int>(balls_[0]->getVelocityY()); int vy_int = static_cast<int>(balls_[0]->getVelocityY());
std::string vy_text = "VY " + std::to_string(vy_int); std::string vy_text = "Velocidad Y: " + std::to_string(vy_int);
dbg_print(8, 32, vy_text.c_str(), 255, 0, 255); // Magenta para debug text_renderer_debug_.print(margin, current_y, vy_text.c_str(), 255, 0, 255); // Magenta
current_y += line_height;
// Línea 3: Estado superficie // Línea 3: Estado superficie
std::string surface_text = balls_[0]->isOnSurface() ? "SURFACE YES" : "SURFACE NO"; std::string surface_text = balls_[0]->isOnSurface() ? "Superficie: Sí" : "Superficie: No";
dbg_print(8, 40, surface_text.c_str(), 255, 0, 255); // Magenta para debug text_renderer_debug_.print(margin, current_y, surface_text.c_str(), 255, 0, 255); // Magenta
current_y += line_height;
// Línea 4: Coeficiente de rebote (loss) // Línea 4: Coeficiente de rebote (loss)
float loss_val = balls_[0]->getLossCoefficient(); float loss_val = balls_[0]->getLossCoefficient();
std::string loss_text = "LOSS " + std::to_string(loss_val).substr(0, 4); // Solo 2 decimales std::string loss_text = "Rebote: " + std::to_string(loss_val).substr(0, 4);
dbg_print(8, 48, loss_text.c_str(), 255, 0, 255); // Magenta para debug text_renderer_debug_.print(margin, current_y, loss_text.c_str(), 255, 0, 255); // Magenta
current_y += line_height;
// Línea 5: Dirección de gravedad // Línea 5: Dirección de gravedad
std::string gravity_dir_text = "GRAVITY " + gravityDirectionToString(current_gravity_); std::string gravity_dir_text = "Dirección: " + gravityDirectionToString(current_gravity_);
dbg_print(8, 56, gravity_dir_text.c_str(), 255, 255, 0); // Amarillo para dirección text_renderer_debug_.print(margin, current_y, gravity_dir_text.c_str(), 255, 255, 0); // Amarillo
current_y += line_height;
} }
// Debug: Mostrar tema actual (delegado a ThemeManager) // Debug: Mostrar tema actual (delegado a ThemeManager)
std::string theme_text = std::string("THEME ") + theme_manager_->getCurrentThemeNameEN(); std::string theme_text = std::string("Tema: ") + theme_manager_->getCurrentThemeNameEN();
dbg_print(8, 64, theme_text.c_str(), 255, 255, 128); // Amarillo claro para tema text_renderer_debug_.print(margin, current_y, theme_text.c_str(), 255, 255, 128); // Amarillo claro
current_y += line_height;
// Debug: Mostrar modo de simulación actual // Debug: Mostrar modo de simulación actual
std::string mode_text; std::string mode_text;
if (current_mode_ == SimulationMode::PHYSICS) { if (current_mode_ == SimulationMode::PHYSICS) {
mode_text = "MODE PHYSICS"; mode_text = "Modo: Física";
} else if (active_shape_) { } else if (active_shape_) {
mode_text = std::string("MODE ") + active_shape_->getName(); mode_text = std::string("Modo: ") + active_shape_->getName();
} else { } else {
mode_text = "MODE SHAPE"; mode_text = "Modo: Forma";
} }
dbg_print(8, 72, mode_text.c_str(), 0, 255, 128); // Verde claro para modo text_renderer_debug_.print(margin, current_y, mode_text.c_str(), 0, 255, 128); // Verde claro
current_y += line_height;
// Debug: Mostrar convergencia en modo LOGO (solo cuando está activo) // Debug: Mostrar convergencia en modo LOGO (solo cuando está activo)
if (current_app_mode_ == AppMode::LOGO && current_mode_ == SimulationMode::SHAPE) { if (current_app_mode_ == AppMode::LOGO && current_mode_ == SimulationMode::SHAPE) {
int convergence_percent = static_cast<int>(shape_convergence_ * 100.0f); int convergence_percent = static_cast<int>(shape_convergence_ * 100.0f);
std::string convergence_text = "CONV " + std::to_string(convergence_percent); std::string convergence_text = "Convergencia: " + std::to_string(convergence_percent) + "%";
dbg_print(8, 80, convergence_text.c_str(), 255, 128, 0); // Naranja para convergencia text_renderer_debug_.print(margin, current_y, convergence_text.c_str(), 255, 128, 0); // Naranja
current_y += line_height;
} }
// Debug: Mostrar modo DEMO/LOGO activo (siempre visible cuando debug está ON) // Debug: Mostrar modo DEMO/LOGO activo (siempre visible cuando debug está ON)
// FIJO en tercera fila (no se mueve con otros elementos del HUD)
int fixed_y = margin + (line_height * 2); // Tercera fila fija
if (current_app_mode_ == AppMode::LOGO) { if (current_app_mode_ == AppMode::LOGO) {
int logo_text_width = 9 * 8; // "LOGO MODE" = 9 caracteres × 8 píxeles const char* logo_text = "Modo Logo";
int logo_text_width = text_renderer_debug_.getTextWidth(logo_text);
int logo_x = (current_screen_width_ - logo_text_width) / 2; int logo_x = (current_screen_width_ - logo_text_width) / 2;
dbg_print(logo_x, 80, "LOGO MODE", 255, 128, 0); // Naranja para Logo Mode text_renderer_debug_.print(logo_x, fixed_y, logo_text, 255, 128, 0); // Naranja
} else if (current_app_mode_ == AppMode::DEMO) { } else if (current_app_mode_ == AppMode::DEMO) {
int demo_text_width = 9 * 8; // "DEMO MODE" = 9 caracteres × 8 píxeles const char* demo_text = "Modo Demo";
int demo_text_width = text_renderer_debug_.getTextWidth(demo_text);
int demo_x = (current_screen_width_ - demo_text_width) / 2; int demo_x = (current_screen_width_ - demo_text_width) / 2;
dbg_print(demo_x, 80, "DEMO MODE", 255, 165, 0); // Naranja para DEMO text_renderer_debug_.print(demo_x, fixed_y, demo_text, 255, 165, 0); // Naranja
} else if (current_app_mode_ == AppMode::DEMO_LITE) { } else if (current_app_mode_ == AppMode::DEMO_LITE) {
int lite_text_width = 14 * 8; // "DEMO LITE MODE" = 14 caracteres × 8 píxeles const char* lite_text = "Modo Demo Lite";
int lite_text_width = text_renderer_debug_.getTextWidth(lite_text);
int lite_x = (current_screen_width_ - lite_text_width) / 2; int lite_x = (current_screen_width_ - lite_text_width) / 2;
dbg_print(lite_x, 80, "DEMO LITE MODE", 255, 200, 0); // Amarillo-naranja para DEMO LITE text_renderer_debug_.print(lite_x, fixed_y, lite_text, 255, 200, 0); // Amarillo-naranja
} }
} }
@@ -1006,11 +1044,11 @@ void Engine::setText() {
int num_balls = BALL_COUNT_SCENARIOS[scenario_]; int num_balls = BALL_COUNT_SCENARIOS[scenario_];
if (num_balls == 1) { if (num_balls == 1) {
text_ = "1 PELOTA"; text_ = "1 pelota";
} else { } else {
text_ = std::to_string(num_balls) + " PELOTAS"; text_ = std::to_string(num_balls) + " pelotas";
} }
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; // Centrar texto text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2; // Centrar texto
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -1093,7 +1131,7 @@ void Engine::changeGravityDirection(GravityDirection direction) {
void Engine::toggleVSync() { void Engine::toggleVSync() {
vsync_enabled_ = !vsync_enabled_; vsync_enabled_ = !vsync_enabled_;
vsync_text_ = vsync_enabled_ ? "VSYNC ON" : "VSYNC OFF"; vsync_text_ = vsync_enabled_ ? "V-Sync: On" : "V-Sync: Off";
// Aplicar el cambio de V-Sync al renderizador // Aplicar el cambio de V-Sync al renderizador
SDL_SetRenderVSync(renderer_, vsync_enabled_ ? 1 : 0); SDL_SetRenderVSync(renderer_, vsync_enabled_ ? 1 : 0);
@@ -1199,9 +1237,9 @@ void Engine::toggleIntegerScaling() {
SDL_SetRenderLogicalPresentation(renderer_, current_screen_width_, current_screen_height_, presentation); SDL_SetRenderLogicalPresentation(renderer_, current_screen_width_, current_screen_height_, presentation);
// Mostrar texto informativo // Mostrar texto informativo
text_ = "SCALING: "; text_ = "Escalado: ";
text_ += mode_name; text_ += mode_name;
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -2021,8 +2059,8 @@ void Engine::switchTexture() {
std::string texture_name = texture_names_[current_texture_index_]; std::string texture_name = texture_names_[current_texture_index_];
std::transform(texture_name.begin(), texture_name.end(), texture_name.begin(), ::toupper); std::transform(texture_name.begin(), texture_name.end(), texture_name.begin(), ::toupper);
text_ = "SPRITE: " + texture_name; text_ = "Sprite: " + texture_name;
text_pos_ = (current_screen_width_ - static_cast<int>(text_.length() * 8)) / 2; text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
show_text_ = true; show_text_ = true;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
} }
@@ -2067,9 +2105,8 @@ void Engine::toggleShapeMode(bool force_gravity_on_exit) {
// Mostrar texto informativo (solo si NO estamos en modo demo o logo) // Mostrar texto informativo (solo si NO estamos en modo demo o logo)
if (current_app_mode_ == AppMode::MANUAL) { if (current_app_mode_ == AppMode::MANUAL) {
text_ = "MODO FISICA"; text_ = "Modo Física";
int text_width = static_cast<int>(text_.length() * 8); text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
text_pos_ = (current_screen_width_ - text_width) / 2;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
show_text_ = true; show_text_ = true;
} }
@@ -2132,9 +2169,8 @@ void Engine::activateShape(ShapeType type) {
// Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo o logo) // Mostrar texto informativo con nombre de figura (solo si NO estamos en modo demo o logo)
if (active_shape_ && current_app_mode_ == AppMode::MANUAL) { if (active_shape_ && current_app_mode_ == AppMode::MANUAL) {
text_ = std::string("MODO ") + active_shape_->getName(); text_ = std::string("Modo ") + active_shape_->getName();
int text_width = static_cast<int>(text_.length() * 8); text_pos_ = (current_screen_width_ - text_renderer_.getTextWidth(text_.c_str())) / 2;
text_pos_ = (current_screen_width_ - text_width) / 2;
text_init_time_ = SDL_GetTicks(); text_init_time_ = SDL_GetTicks();
show_text_ = true; show_text_ = true;
} }
+33 -25
View File
@@ -10,18 +10,19 @@
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "ball.h" // for Ball #include "ball.h" // for Ball
#include "defines.h" // for GravityDirection, ColorTheme, ShapeType #include "defines.h" // for GravityDirection, ColorTheme, ShapeType
#include "external/texture.h" // for Texture #include "external/texture.h" // for Texture
#include "shapes/shape.h" // for Shape (interfaz polimórfica) #include "shapes/shape.h" // for Shape (interfaz polimórfica)
#include "theme_manager.h" // for ThemeManager #include "text/textrenderer.h" // for TextRenderer
#include "theme_manager.h" // for ThemeManager
// Modos de aplicación mutuamente excluyentes // Modos de aplicación mutuamente excluyentes
enum class AppMode { enum class AppMode {
MANUAL, // Control manual del usuario MANUAL, // Control manual del usuario
DEMO, // Modo demo completo (auto-play) DEMO, // Modo demo completo (auto-play)
DEMO_LITE, // Modo demo lite (solo física/figuras) DEMO_LITE, // Modo demo lite (solo física/figuras)
LOGO // Modo logo (easter egg) LOGO // Modo logo (easter egg)
}; };
class Engine { class Engine {
@@ -54,6 +55,8 @@ class Engine {
// UI y debug // UI y debug
bool show_debug_ = false; bool show_debug_ = false;
bool show_text_ = true; bool show_text_ = true;
TextRenderer text_renderer_; // Sistema de renderizado de texto para display (centrado)
TextRenderer text_renderer_debug_; // Sistema de renderizado de texto para debug (HUD)
// Sistema de zoom dinámico // Sistema de zoom dinámico
int current_window_zoom_ = DEFAULT_WINDOW_ZOOM; int current_window_zoom_ = DEFAULT_WINDOW_ZOOM;
@@ -93,22 +96,22 @@ class Engine {
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)
AppMode current_app_mode_ = AppMode::MANUAL; // Modo actual (mutuamente excluyente) AppMode current_app_mode_ = AppMode::MANUAL; // Modo actual (mutuamente excluyente)
AppMode previous_app_mode_ = AppMode::MANUAL; // Modo previo antes de entrar a LOGO AppMode previous_app_mode_ = AppMode::MANUAL; // Modo previo antes de entrar a LOGO
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)
// Sistema de convergencia para LOGO MODE (escala con resolución) // Sistema de convergencia para LOGO MODE (escala con resolución)
float shape_convergence_ = 0.0f; // % de pelotas cerca del objetivo (0.0-1.0) float shape_convergence_ = 0.0f; // % de pelotas cerca del objetivo (0.0-1.0)
float logo_convergence_threshold_ = 0.90f; // Threshold aleatorio (75-100%) float logo_convergence_threshold_ = 0.90f; // Threshold aleatorio (75-100%)
float logo_min_time_ = 3.0f; // Tiempo mínimo escalado con resolución float logo_min_time_ = 3.0f; // Tiempo mínimo escalado con resolución
float logo_max_time_ = 5.0f; // Tiempo máximo escalado (backup) float logo_max_time_ = 5.0f; // Tiempo máximo escalado (backup)
// Sistema de espera de flips en LOGO MODE (camino alternativo) // Sistema de espera de flips en LOGO MODE (camino alternativo)
bool logo_waiting_for_flip_ = false; // true si eligió el camino "esperar flip" bool logo_waiting_for_flip_ = false; // true si eligió el camino "esperar flip"
int logo_target_flip_number_ = 0; // En qué flip actuar (1, 2 o 3) int logo_target_flip_number_ = 0; // En qué flip actuar (1, 2 o 3)
float logo_target_flip_percentage_ = 0.0f; // % de flip a esperar (0.2-0.8) float logo_target_flip_percentage_ = 0.0f; // % de flip a esperar (0.2-0.8)
int logo_current_flip_count_ = 0; // Flips observados hasta ahora int logo_current_flip_count_ = 0; // Flips observados hasta ahora
// Estado previo antes de entrar a Logo Mode (para restaurar al salir) // Estado previo antes de entrar a Logo Mode (para restaurar al salir)
int logo_previous_theme_ = 0; // Índice de tema (0-9) int logo_previous_theme_ = 0; // Índice de tema (0-9)
@@ -119,6 +122,11 @@ class Engine {
std::vector<SDL_Vertex> batch_vertices_; std::vector<SDL_Vertex> batch_vertices_;
std::vector<int> batch_indices_; std::vector<int> batch_indices_;
// Configuración del sistema de texto (constantes configurables)
static constexpr const char* TEXT_FONT_PATH = "data/fonts/determination.ttf";
static constexpr int TEXT_BASE_SIZE = 8; // Tamaño base para 240p
static constexpr bool TEXT_ANTIALIASING = true; // true = suavizado, false = píxeles nítidos
// Métodos principales del loop // Métodos principales del loop
void calculateDeltaTime(); void calculateDeltaTime();
void update(); void update();
@@ -141,7 +149,7 @@ class Engine {
std::string gravityDirectionToString(GravityDirection direction) const; std::string gravityDirectionToString(GravityDirection direction) const;
// Sistema de gestión de estados (MANUAL/DEMO/DEMO_LITE/LOGO) // Sistema de gestión de estados (MANUAL/DEMO/DEMO_LITE/LOGO)
void setState(AppMode new_mode); // Cambiar modo de aplicación (mutuamente excluyente) void setState(AppMode new_mode); // Cambiar modo de aplicación (mutuamente excluyente)
// Sistema de Modo DEMO // Sistema de Modo DEMO
void updateDemoMode(); void updateDemoMode();
@@ -150,9 +158,9 @@ class Engine {
void toggleGravityOnOff(); void toggleGravityOnOff();
// Sistema de Modo Logo (easter egg) // Sistema de Modo Logo (easter egg)
void toggleLogoMode(); // Activar/desactivar modo logo manual (tecla K) void toggleLogoMode(); // Activar/desactivar modo logo manual (tecla K)
void enterLogoMode(bool from_demo = false); // Entrar al modo logo (manual o automático) void enterLogoMode(bool from_demo = false); // Entrar al modo logo (manual o automático)
void exitLogoMode(bool return_to_demo = false); // Salir del modo logo void exitLogoMode(bool return_to_demo = false); // Salir del modo logo
// Sistema de cambio de sprites dinámico // Sistema de cambio de sprites dinámico
void switchTexture(); // Cambia a siguiente textura disponible void switchTexture(); // Cambia a siguiente textura disponible
+112
View File
@@ -0,0 +1,112 @@
#include "textrenderer.h"
#include <SDL3/SDL.h>
#include <SDL3_ttf/SDL_ttf.h>
TextRenderer::TextRenderer() : renderer_(nullptr), font_(nullptr), font_size_(0), use_antialiasing_(true) {
}
TextRenderer::~TextRenderer() {
cleanup();
}
bool TextRenderer::init(SDL_Renderer* renderer, const char* font_path, int font_size, bool use_antialiasing) {
renderer_ = renderer;
font_size_ = font_size;
use_antialiasing_ = use_antialiasing;
// Inicializar SDL_ttf si no está inicializado
if (!TTF_WasInit()) {
if (!TTF_Init()) {
SDL_Log("Error al inicializar SDL_ttf: %s", SDL_GetError());
return false;
}
}
// Cargar la fuente
font_ = TTF_OpenFont(font_path, font_size);
if (font_ == nullptr) {
SDL_Log("Error al cargar fuente '%s': %s", font_path, SDL_GetError());
return false;
}
return true;
}
void TextRenderer::cleanup() {
if (font_ != nullptr) {
TTF_CloseFont(font_);
font_ = nullptr;
}
renderer_ = nullptr;
}
void TextRenderer::print(int x, int y, const char* text, uint8_t r, uint8_t g, uint8_t b) {
if (!isInitialized() || text == nullptr || text[0] == '\0') {
return;
}
// Crear superficie con el texto renderizado
SDL_Color color = {r, g, b, 255};
SDL_Surface* text_surface = nullptr;
if (use_antialiasing_) {
// Con antialiasing (suave, mejor calidad)
text_surface = TTF_RenderText_Blended(font_, text, strlen(text), color);
} else {
// Sin antialiasing (píxeles nítidos, estilo retro)
text_surface = TTF_RenderText_Solid(font_, text, strlen(text), color);
}
if (text_surface == nullptr) {
SDL_Log("Error al renderizar texto: %s", SDL_GetError());
return;
}
// Crear textura desde la superficie
SDL_Texture* text_texture = SDL_CreateTextureFromSurface(renderer_, text_surface);
if (text_texture == nullptr) {
SDL_Log("Error al crear textura: %s", SDL_GetError());
SDL_DestroySurface(text_surface);
return;
}
// Preparar rectángulo de destino
SDL_FRect dest_rect;
dest_rect.x = static_cast<float>(x);
dest_rect.y = static_cast<float>(y);
dest_rect.w = static_cast<float>(text_surface->w);
dest_rect.h = static_cast<float>(text_surface->h);
// Renderizar la textura
SDL_RenderTexture(renderer_, text_texture, nullptr, &dest_rect);
// Limpiar recursos
SDL_DestroyTexture(text_texture);
SDL_DestroySurface(text_surface);
}
void TextRenderer::print(int x, int y, const std::string& text, uint8_t r, uint8_t g, uint8_t b) {
print(x, y, text.c_str(), r, g, b);
}
int TextRenderer::getTextWidth(const char* text) {
if (!isInitialized() || text == nullptr) {
return 0;
}
int width = 0;
int height = 0;
if (!TTF_GetStringSize(font_, text, strlen(text), &width, &height)) {
return 0;
}
return width;
}
int TextRenderer::getTextHeight() {
if (!isInitialized()) {
return 0;
}
return TTF_GetFontHeight(font_);
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <SDL3/SDL.h>
#include <SDL3_ttf/SDL_ttf.h>
#include <string>
class TextRenderer {
public:
TextRenderer();
~TextRenderer();
// Inicializa el renderizador de texto con una fuente
bool init(SDL_Renderer* renderer, const char* font_path, int font_size, bool use_antialiasing = true);
// Libera recursos
void cleanup();
// Renderiza texto en la posición especificada con color RGB
void print(int x, int y, const char* text, uint8_t r, uint8_t g, uint8_t b);
void print(int x, int y, const std::string& text, uint8_t r, uint8_t g, uint8_t b);
// Obtiene el ancho de un texto renderizado
int getTextWidth(const char* text);
// Obtiene la altura de la fuente
int getTextHeight();
// Verifica si está inicializado correctamente
bool isInitialized() const { return font_ != nullptr && renderer_ != nullptr; }
private:
SDL_Renderer* renderer_;
TTF_Font* font_;
int font_size_;
bool use_antialiasing_;
};
+28 -28
View File
@@ -17,8 +17,8 @@ void ThemeManager::initialize() {
// 0: SUNSET (Atardecer) - Naranjas, rojos, amarillos, rosas // 0: SUNSET (Atardecer) - Naranjas, rojos, amarillos, rosas
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"SUNSET", "Sunset",
"ATARDECER", "Atardecer",
255, 140, 60, // Color texto: naranja cálido 255, 140, 60, // Color texto: naranja cálido
180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior: naranja suave 180.0f / 255.0f, 140.0f / 255.0f, 100.0f / 255.0f, // Fondo superior: naranja suave
40.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior: púrpura oscuro 40.0f / 255.0f, 20.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior: púrpura oscuro
@@ -30,8 +30,8 @@ void ThemeManager::initialize() {
// 1: OCEAN (Océano) - Azules, turquesas, blancos // 1: OCEAN (Océano) - Azules, turquesas, blancos
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"OCEAN", "Ocean",
"OCEANO", "Océano",
80, 200, 255, // Color texto: azul océano 80, 200, 255, // Color texto: azul océano
100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior: azul cielo 100.0f / 255.0f, 150.0f / 255.0f, 200.0f / 255.0f, // Fondo superior: azul cielo
20.0f / 255.0f, 40.0f / 255.0f, 80.0f / 255.0f, // Fondo inferior: azul marino 20.0f / 255.0f, 40.0f / 255.0f, 80.0f / 255.0f, // Fondo inferior: azul marino
@@ -43,8 +43,8 @@ void ThemeManager::initialize() {
// 2: NEON - Cian, magenta, verde lima, amarillo vibrante // 2: NEON - Cian, magenta, verde lima, amarillo vibrante
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"NEON", "Neon",
"NEON", "Neón",
255, 60, 255, // Color texto: magenta brillante 255, 60, 255, // Color texto: magenta brillante
20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior: negro azulado 20.0f / 255.0f, 20.0f / 255.0f, 40.0f / 255.0f, // Fondo superior: negro azulado
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro 0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro
@@ -56,8 +56,8 @@ void ThemeManager::initialize() {
// 3: FOREST (Bosque) - Verdes, marrones, amarillos otoño // 3: FOREST (Bosque) - Verdes, marrones, amarillos otoño
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"FOREST", "Forest",
"BOSQUE", "Bosque",
100, 255, 100, // Color texto: verde natural 100, 255, 100, // Color texto: verde natural
144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior: verde claro 144.0f / 255.0f, 238.0f / 255.0f, 144.0f / 255.0f, // Fondo superior: verde claro
101.0f / 255.0f, 67.0f / 255.0f, 33.0f / 255.0f, // Fondo inferior: marrón tierra 101.0f / 255.0f, 67.0f / 255.0f, 33.0f / 255.0f, // Fondo inferior: marrón tierra
@@ -104,8 +104,8 @@ void ThemeManager::initialize() {
// 5: MONOCHROME (Monocromo) - Fondo negro degradado, sprites blancos // 5: MONOCHROME (Monocromo) - Fondo negro degradado, sprites blancos
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"MONOCHROME", "Monochrome",
"MONOCROMO", "Monocromo",
200, 200, 200, // Color texto: gris claro 200, 200, 200, // Color texto: gris claro
20.0f / 255.0f, 20.0f / 255.0f, 20.0f / 255.0f, // Fondo superior: gris muy oscuro 20.0f / 255.0f, 20.0f / 255.0f, 20.0f / 255.0f, // Fondo superior: gris muy oscuro
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro 0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro
@@ -117,8 +117,8 @@ void ThemeManager::initialize() {
// 6: LAVENDER (Lavanda) - Degradado violeta oscuro → azul medianoche, pelotas amarillo dorado // 6: LAVENDER (Lavanda) - Degradado violeta oscuro → azul medianoche, pelotas amarillo dorado
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"LAVENDER", "Lavender",
"LAVANDA", "Lavanda",
255, 200, 100, // Color texto: amarillo cálido 255, 200, 100, // Color texto: amarillo cálido
120.0f / 255.0f, 80.0f / 255.0f, 140.0f / 255.0f, // Fondo superior: violeta oscuro 120.0f / 255.0f, 80.0f / 255.0f, 140.0f / 255.0f, // Fondo superior: violeta oscuro
25.0f / 255.0f, 30.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior: azul medianoche 25.0f / 255.0f, 30.0f / 255.0f, 60.0f / 255.0f, // Fondo inferior: azul medianoche
@@ -130,8 +130,8 @@ void ThemeManager::initialize() {
// 7: CRIMSON (Carmesí) - Fondo negro-rojo oscuro, pelotas rojas uniformes // 7: CRIMSON (Carmesí) - Fondo negro-rojo oscuro, pelotas rojas uniformes
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"CRIMSON", "Crimson",
"CARMESI", "Carmesí",
255, 100, 100, // Color texto: rojo claro 255, 100, 100, // Color texto: rojo claro
40.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo superior: rojo muy oscuro 40.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo superior: rojo muy oscuro
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro puro 0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro puro
@@ -143,8 +143,8 @@ void ThemeManager::initialize() {
// 8: EMERALD (Esmeralda) - Fondo negro-verde oscuro, pelotas verdes uniformes // 8: EMERALD (Esmeralda) - Fondo negro-verde oscuro, pelotas verdes uniformes
themes_.push_back(std::make_unique<StaticTheme>( themes_.push_back(std::make_unique<StaticTheme>(
"EMERALD", "Emerald",
"ESMERALDA", "Esmeralda",
100, 255, 100, // Color texto: verde claro 100, 255, 100, // Color texto: verde claro
0.0f / 255.0f, 40.0f / 255.0f, 0.0f / 255.0f, // Fondo superior: verde muy oscuro 0.0f / 255.0f, 40.0f / 255.0f, 0.0f / 255.0f, // Fondo superior: verde muy oscuro
0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro puro 0.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f, // Fondo inferior: negro puro
@@ -160,8 +160,8 @@ void ThemeManager::initialize() {
// 9: SUNRISE (Amanecer) - Noche → Alba → Día (loop) // 9: SUNRISE (Amanecer) - Noche → Alba → Día (loop)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"SUNRISE", "Sunrise",
"AMANECER", "Amanecer",
255, 200, 100, // Color texto: amarillo cálido 255, 200, 100, // Color texto: amarillo cálido
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Noche oscura (estado inicial) // Keyframe 0: Noche oscura (estado inicial)
@@ -201,8 +201,8 @@ void ThemeManager::initialize() {
// 10: OCEAN WAVES (Olas Oceánicas) - Azul oscuro ↔ Turquesa (loop) // 10: OCEAN WAVES (Olas Oceánicas) - Azul oscuro ↔ Turquesa (loop)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"OCEAN WAVES", "Ocean Waves",
"OLAS OCEANICAS", "Olas Oceánicas",
100, 220, 255, // Color texto: cian claro 100, 220, 255, // Color texto: cian claro
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Profundidad oceánica (azul oscuro) // Keyframe 0: Profundidad oceánica (azul oscuro)
@@ -232,8 +232,8 @@ void ThemeManager::initialize() {
// 11: NEON PULSE (Pulso Neón) - Negro → Neón brillante (rápido ping-pong) // 11: NEON PULSE (Pulso Neón) - Negro → Neón brillante (rápido ping-pong)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"NEON PULSE", "Neon Pulse",
"PULSO NEON", "Pulso Neón",
255, 60, 255, // Color texto: magenta brillante 255, 60, 255, // Color texto: magenta brillante
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Apagado (negro) // Keyframe 0: Apagado (negro)
@@ -263,8 +263,8 @@ void ThemeManager::initialize() {
// 12: FIRE (Fuego Vivo) - Brasas → Llamas → Inferno (loop) // 12: FIRE (Fuego Vivo) - Brasas → Llamas → Inferno (loop)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"FIRE", "Fire",
"FUEGO", "Fuego",
255, 150, 80, // Color texto: naranja cálido 255, 150, 80, // Color texto: naranja cálido
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Brasas oscuras (estado inicial) // Keyframe 0: Brasas oscuras (estado inicial)
@@ -314,8 +314,8 @@ void ThemeManager::initialize() {
// 13: AURORA (Aurora Boreal) - Verde → Violeta → Cian (loop) // 13: AURORA (Aurora Boreal) - Verde → Violeta → Cian (loop)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"AURORA", "Aurora",
"AURORA", "Aurora",
150, 255, 200, // Color texto: verde claro 150, 255, 200, // Color texto: verde claro
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Verde aurora (estado inicial) // Keyframe 0: Verde aurora (estado inicial)
@@ -365,8 +365,8 @@ void ThemeManager::initialize() {
// 14: VOLCANIC (Erupción Volcánica) - Ceniza → Erupción → Lava (loop) // 14: VOLCANIC (Erupción Volcánica) - Ceniza → Erupción → Lava (loop)
themes_.push_back(std::make_unique<DynamicTheme>( themes_.push_back(std::make_unique<DynamicTheme>(
"VOLCANIC", "Volcanic",
"VOLCAN", "Volcán",
200, 120, 80, // Color texto: naranja apagado 200, 120, 80, // Color texto: naranja apagado
std::vector<DynamicThemeKeyframe>{ std::vector<DynamicThemeKeyframe>{
// Keyframe 0: Ceniza oscura (pre-erupción) // Keyframe 0: Ceniza oscura (pre-erupción)