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:
@@ -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})
|
||||||
|
|||||||
BIN
data/fonts/BBHSansHegarty-Regular.ttf
Normal file
BIN
data/fonts/BBHSansHegarty-Regular.ttf
Normal file
Binary file not shown.
BIN
data/fonts/FunnelSans-Regular.ttf
Normal file
BIN
data/fonts/FunnelSans-Regular.ttf
Normal file
Binary file not shown.
BIN
data/fonts/JetBrainsMono-Regular.ttf
Normal file
BIN
data/fonts/JetBrainsMono-Regular.ttf
Normal file
Binary file not shown.
BIN
data/fonts/Minecraftia-Regular.ttf
Normal file
BIN
data/fonts/Minecraftia-Regular.ttf
Normal file
Binary file not shown.
BIN
data/fonts/PixelOperator.ttf
Normal file
BIN
data/fonts/PixelOperator.ttf
Normal file
Binary file not shown.
BIN
data/fonts/determination.ttf
Normal file
BIN
data/fonts/determination.ttf
Normal file
Binary file not shown.
BIN
data/fonts/dogica.ttf
Normal file
BIN
data/fonts/dogica.ttf
Normal file
Binary file not shown.
BIN
data/fonts/rainyhearts.ttf
Normal file
BIN
data/fonts/rainyhearts.ttf
Normal file
Binary file not shown.
@@ -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();
|
||||||
|
|||||||
112
source/text/textrenderer.cpp
Normal file
112
source/text/textrenderer.cpp
Normal 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
source/text/textrenderer.h
Normal file
36
source/text/textrenderer.h
Normal 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_;
|
||||||
|
};
|
||||||
@@ -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