From e85800c5ed267132dc8197e336addfdcc4e7ec69 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Fri, 27 Mar 2026 22:54:47 +0100 Subject: [PATCH] ja es pot escriure en la consola --- source/core/rendering/screen.cpp | 2 +- source/core/system/global_events.cpp | 9 +++ source/game/scenes/game.cpp | 27 ++++++--- source/game/ui/console.cpp | 88 ++++++++++++++++++++++++---- source/game/ui/console.hpp | 20 ++++++- 5 files changed, 125 insertions(+), 21 deletions(-) diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 92371ea7..cadc8372 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -445,7 +445,7 @@ void Screen::renderInfo() const { const int LINE_HEIGHT = text_->getCharacterSize() - 3; const int X = 0; - int y = 0; + int y = (Console::get() != nullptr) ? Console::get()->getVisibleHeight() : 0; // FPS const std::string FPS_TEXT = std::to_string(fps_.last_value) + " fps"; diff --git a/source/core/system/global_events.cpp b/source/core/system/global_events.cpp index 59b8dd49..6376b501 100644 --- a/source/core/system/global_events.cpp +++ b/source/core/system/global_events.cpp @@ -3,6 +3,7 @@ #include "core/input/mouse.hpp" #include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio #include "game/scene_manager.hpp" // Para SceneManager +#include "game/ui/console.hpp" // Para Console namespace GlobalEvents { // Comprueba los eventos que se pueden producir en cualquier sección del juego @@ -17,6 +18,14 @@ namespace GlobalEvents { // reLoadTextures(); } + // Enrutar eventos de texto a la consola cuando está activa + if (Console::get() != nullptr && Console::get()->isActive()) { + if (event.type == SDL_EVENT_TEXT_INPUT || event.type == SDL_EVENT_KEY_DOWN) { + Console::get()->handleEvent(event); + return; + } + } + Mouse::handleEvent(event); } } // namespace GlobalEvents \ No newline at end of file diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index cfb4a5ea..c1c711eb 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -25,6 +25,7 @@ #include "game/gameplay/stats.hpp" // Para Stats #include "game/options.hpp" // Para Options, options, Cheat, SectionState #include "game/scene_manager.hpp" // Para SceneManager +#include "game/ui/console.hpp" // Para Console #include "game/ui/notifier.hpp" // Para Notifier, NotificationText, CHEEVO_NO... #include "utils/defines.hpp" // Para Tile::SIZE, PlayArea::HEIGHT, RoomBorder::BOTTOM #include "utils/utils.hpp" // Para PaletteColor, stringToColor @@ -71,7 +72,9 @@ void Game::handleEvents() { while (SDL_PollEvent(&event)) { GlobalEvents::handle(event); #ifdef _DEBUG - handleDebugEvents(event); + if (!Console::get()->isActive()) { + handleDebugEvents(event); + } #endif } } @@ -87,6 +90,12 @@ void Game::handleInput() { Notifier::get()->show({scoreboard_data_->music ? Locale::get()->get("game.music_enabled") : Locale::get()->get("game.music_disabled")}); } + // Si la consola está activa, no procesar inputs del juego + if (Console::get()->isActive()) { + GlobalInputs::handle(); + return; + } + // Durante fade/postfade, solo procesar inputs globales if (state_ != State::PLAYING) { GlobalInputs::handle(); @@ -163,17 +172,19 @@ void Game::updatePlaying(float delta_time) { room_->update(delta_time); switch (mode_) { case Mode::GAME: + if (!Console::get()->isActive()) { #ifdef _DEBUG - // Maneja el arrastre del jugador con el ratón (debug) - handleDebugMouseDrag(delta_time); + // Maneja el arrastre del jugador con el ratón (debug) + handleDebugMouseDrag(delta_time); - // Si estamos arrastrando, no ejecutar la física normal del jugador - if (!debug_dragging_player_) { - player_->update(delta_time); - } + // Si estamos arrastrando, no ejecutar la física normal del jugador + if (!debug_dragging_player_) { + player_->update(delta_time); + } #else - player_->update(delta_time); + player_->update(delta_time); #endif + } checkPlayerIsOnBorder(); checkPlayerAndItems(); checkPlayerAndEnemies(); diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index 72f91078..db9fd8d0 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -47,6 +47,21 @@ void Console::buildSurface() { surface_ = std::make_shared(WIDTH, height_); + // Posición inicial (fuera de pantalla por arriba) + SDL_FRect sprite_rect = {.x = 0, .y = y_, .w = WIDTH, .h = height_}; + sprite_ = std::make_shared(surface_, sprite_rect); + + // Dibujo inicial del texto + redrawText(); +} + +// Redibuja el texto dinámico sobre la surface (fondo + borde + líneas) +void Console::redrawText() { + const float WIDTH = Options::game.width; + const int TEXT_SIZE = 6; + const int PADDING_IN_H = TEXT_SIZE; + const int PADDING_IN_V = TEXT_SIZE / 2; + auto previous_renderer = Screen::get()->getRendererSurface(); Screen::get()->setRendererSurface(surface_); @@ -55,17 +70,15 @@ void Console::buildSurface() { SDL_FRect rect = {.x = 0, .y = 0, .w = WIDTH, .h = height_}; surface_->drawRectBorder(&rect, BORDER_COLOR); - // Texto de marcador de posición - const int TEXT_SIZE = 6; - const int PADDING_IN_H = TEXT_SIZE; - const int PADDING_IN_V = TEXT_SIZE / 2; - text_->writeColored(PADDING_IN_H, PADDING_IN_V, "> _", BORDER_COLOR); + // Línea 1: mensajes + text_->writeColored(PADDING_IN_H, PADDING_IN_V, msg_line_, MSG_COLOR); + + // Línea 2: prompt + input + cursor + const bool SHOW_CURSOR = cursor_visible_ && (static_cast(input_line_.size()) < MAX_INPUT_CHARS); + const std::string INPUT_STR = "> " + input_line_ + (SHOW_CURSOR ? "_" : ""); + text_->writeColored(PADDING_IN_H, PADDING_IN_V + TEXT_SIZE, INPUT_STR, BORDER_COLOR); Screen::get()->setRendererSurface(previous_renderer); - - // Posición inicial (fuera de pantalla por arriba) - SDL_FRect sprite_rect = {.x = 0, .y = y_, .w = WIDTH, .h = height_}; - sprite_ = std::make_shared(surface_, sprite_rect); } // Actualiza la animación de la consola @@ -74,6 +87,19 @@ void Console::update(float delta_time) { return; } + // Parpadeo del cursor (solo cuando activa) + if (status_ == Status::ACTIVE) { + cursor_timer_ += delta_time; + const float THRESHOLD = cursor_visible_ ? CURSOR_ON_TIME : CURSOR_OFF_TIME; + if (cursor_timer_ >= THRESHOLD) { + cursor_timer_ = 0.0F; + cursor_visible_ = !cursor_visible_; + } + } + + // Redibujar texto cada frame + redrawText(); + switch (status_) { case Status::RISING: { y_ += SLIDE_SPEED * delta_time; @@ -111,10 +137,15 @@ void Console::render() { void Console::toggle() { switch (status_) { case Status::HIDDEN: - status_ = Status::RISING; + status_ = Status::RISING; + input_line_.clear(); + cursor_timer_ = 0.0F; + cursor_visible_ = true; + SDL_StartTextInput(SDL_GetKeyboardFocus()); break; case Status::ACTIVE: status_ = Status::VANISHING; + SDL_StopTextInput(SDL_GetKeyboardFocus()); break; default: // Durante RISING o VANISHING no se hace nada @@ -122,7 +153,44 @@ void Console::toggle() { } } +// Procesa el evento SDL: entrada de texto, Backspace, Enter +void Console::handleEvent(const SDL_Event& event) { + if (status_ != Status::ACTIVE) { return; } + + if (event.type == SDL_EVENT_TEXT_INPUT) { + if (static_cast(input_line_.size()) < MAX_INPUT_CHARS) { + input_line_ += event.text.text; + } + return; + } + + if (event.type == SDL_EVENT_KEY_DOWN) { + if (event.key.scancode == SDL_SCANCODE_BACKSPACE && !input_line_.empty()) { + input_line_.pop_back(); + } else if (event.key.scancode == SDL_SCANCODE_RETURN || + event.key.scancode == SDL_SCANCODE_KP_ENTER) { + processCommand(); + } + } +} + +// Ejecuta el comando introducido y reinicia la línea de input +void Console::processCommand() { + if (!input_line_.empty()) { + msg_line_ = "OK"; + } + input_line_.clear(); + cursor_timer_ = 0.0F; + cursor_visible_ = true; +} + // Indica si la consola está activa (visible o en animación) auto Console::isActive() -> bool { return status_ != Status::HIDDEN; } + +// Devuelve los píxeles visibles de la consola (sincronizado con la animación) +auto Console::getVisibleHeight() -> int { + if (status_ == Status::HIDDEN) { return 0; } + return static_cast(y_ + height_); +} diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index 392af06b..89c92a31 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -20,9 +20,11 @@ class Console { void update(float delta_time); void render(); void toggle(); + void handleEvent(const SDL_Event& event); // Consultas - auto isActive() -> bool; // true si RISING, ACTIVE o VANISHING + auto isActive() -> bool; // true si RISING, ACTIVE o VANISHING + auto getVisibleHeight() -> int; // Píxeles visibles actuales (0 = oculta, height_ = totalmente visible) private: enum class Status { @@ -35,8 +37,14 @@ class Console { // Constantes visuales static constexpr Uint8 BG_COLOR = 0; // PaletteColor::BLACK static constexpr Uint8 BORDER_COLOR = 9; // PaletteColor::BRIGHT_GREEN + static constexpr Uint8 MSG_COLOR = 8; // PaletteColor::GREEN static constexpr float SLIDE_SPEED = 120.0F; + // Constantes de entrada + static constexpr int MAX_INPUT_CHARS = 28; + static constexpr float CURSOR_ON_TIME = 0.5F; + static constexpr float CURSOR_OFF_TIME = 0.3F; + // [SINGLETON] static Console* console; @@ -45,7 +53,9 @@ class Console { ~Console() = default; // Métodos privados - void buildSurface(); // Crea la Surface con el aspecto visual + void buildSurface(); // Crea la Surface con el aspecto visual + void redrawText(); // Redibuja el texto dinámico (msg + input + cursor) + void processCommand(); // Procesa el comando introducido por el usuario // Objetos de renderizado std::shared_ptr text_; @@ -56,4 +66,10 @@ class Console { Status status_{Status::HIDDEN}; float y_{0.0F}; // Posición Y actual (animada) float height_{0.0F}; // Altura del panel + + // Estado de la entrada de texto + std::string msg_line_{"JDD CONSOLE V1.0"}; + std::string input_line_; + float cursor_timer_{0.0F}; + bool cursor_visible_{true}; };