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:
+14
-6
@@ -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.
+114
-78
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#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 "text/textrenderer.h" // for TextRenderer
|
||||||
#include "theme_manager.h" // for ThemeManager
|
#include "theme_manager.h" // for ThemeManager
|
||||||
|
|
||||||
// Modos de aplicación mutuamente excluyentes
|
// Modos de aplicación mutuamente excluyentes
|
||||||
@@ -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;
|
||||||
@@ -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();
|
||||||
|
|||||||
@@ -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_);
|
||||||
|
}
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user