From 4c5e1e54704bbb95c3f005b35f4e00a03b182b84 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 6 Apr 2026 14:53:58 +0200 Subject: [PATCH] marcador provisional --- data/locale/ca.yaml | 11 +- data/locale/en.yaml | 11 +- source/core/rendering/render_info.cpp | 13 +- source/core/rendering/text.cpp | 31 +++++ source/core/rendering/text.hpp | 4 +- source/game/entities/player.cpp | 23 ++-- source/game/entities/player.hpp | 1 + source/game/gameplay/scoreboard.cpp | 180 +++++++++++--------------- source/game/gameplay/scoreboard.hpp | 70 ++++------ source/game/scenes/game.cpp | 5 - source/game/ui/console.cpp | 10 ++ source/game/ui/console.hpp | 2 +- 12 files changed, 180 insertions(+), 181 deletions(-) diff --git a/data/locale/ca.yaml b/data/locale/ca.yaml index d7801c8..e06ebc0 100644 --- a/data/locale/ca.yaml +++ b/data/locale/ca.yaml @@ -122,11 +122,12 @@ ui: vsync_disabled: "V-SYNC DESACTIVAT" scoreboard: - items: "TRESORS PILLATS " - time: " HORA " - rooms: "SALES" - cheat_infinite_lives: "vides inf" - cheat_invincibility: "inv" + lives: "vides " + items: "objectes " + time: "temps " + music_on: "musica" + cheat_infinite_lives: "vides infinites" + cheat_invincibility: "invencibilitat" game: music_enabled: "MÚSICA ACTIVADA" diff --git a/data/locale/en.yaml b/data/locale/en.yaml index 44c5d11..66286ed 100644 --- a/data/locale/en.yaml +++ b/data/locale/en.yaml @@ -122,11 +122,12 @@ ui: vsync_disabled: "V-SYNC DISABLED" scoreboard: - items: "ITEMS COLLECTED " - time: " TIME " - rooms: "ROOMS" - cheat_infinite_lives: "inf lives" - cheat_invincibility: "inv" + lives: "lives " + items: "items " + time: "time " + music_on: "music" + cheat_infinite_lives: "infinite lives" + cheat_invincibility: "invincibility" game: music_enabled: "MUSIC ENABLED" diff --git a/source/core/rendering/render_info.cpp b/source/core/rendering/render_info.cpp index 985676e..1ce9a6c 100644 --- a/source/core/rendering/render_info.cpp +++ b/source/core/rendering/render_info.cpp @@ -106,8 +106,7 @@ void RenderInfo::render() const { // Todo en lowercase std::ranges::transform(line, line.begin(), [](unsigned char c) { return std::tolower(c); }); - // Constantes visuales (igual que Console) - static constexpr Uint8 BG_COLOR = 0; // PaletteColor::BLACK + // Constantes visuales static constexpr Uint8 MSG_COLOR = 9; // PaletteColor::BRIGHT_GREEN static constexpr int TEXT_SIZE = 6; static constexpr int PADDING_V = (TEXT_SIZE / 2) - 1; @@ -119,16 +118,6 @@ void RenderInfo::render() const { const int CONSOLE_Y = (Console::get() != nullptr) ? Console::get()->getVisibleHeight() : 0; const int Y = CONSOLE_Y + static_cast(y_); - // Rectángulo de fondo: ancho completo, alto ajustado al texto - const SDL_FRect RECT = { - .x = 0.0F, - .y = static_cast(Y), - .w = Options::game.width, - .h = static_cast(TEXT_SIZE + (PADDING_V * 2))}; - - auto game_surface = Screen::get()->getGameSurface(); - game_surface->fillRect(&RECT, BG_COLOR); - // game_surface->drawRectBorder(&RECT, BORDER_COLOR); text_obj->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, static_cast(Options::game.width / 2), Y + PADDING_V, diff --git a/source/core/rendering/text.cpp b/source/core/rendering/text.cpp index 82bc50b..60d0d24 100644 --- a/source/core/rendering/text.cpp +++ b/source/core/rendering/text.cpp @@ -219,6 +219,37 @@ void Text::writeColored(int x, int y, const std::string& text, Uint8 color, int } } +// Escribe texto monoespaciado con color (cada glifo centrado en una celda de ancho fijo) +void Text::writeColoredMono(int x, int y, const std::string& text, Uint8 color, int cell_w) { // NOLINT(readability-convert-member-functions-to-static) + int shift = 0; + size_t pos = 0; + + sprite_->setY(y); + while (pos < text.size()) { + uint32_t cp = nextCodepoint(text, pos); + auto it = offset_.find(cp); + if (it == offset_.end()) { it = offset_.find('?'); } + if (it != offset_.end()) { + const int GLYPH_OFFSET = (cell_w - it->second.w) / 2; + sprite_->setClip(it->second.x, it->second.y, box_width_, box_height_); + sprite_->setX(x + shift + GLYPH_OFFSET); + sprite_->render(1, color); + } + shift += cell_w; + } +} + +// Obtiene la longitud en pixels de una cadena monoespaciada +auto Text::lengthMono(const std::string& text, int cell_w) const -> int { + size_t pos = 0; + int count = 0; + while (pos < text.size()) { + nextCodepoint(text, pos); + ++count; + } + return count * cell_w; +} + // Escribe el texto con sombra void Text::writeShadowed(int x, int y, const std::string& text, Uint8 color, Uint8 shadow_distance, int kerning, int lenght) { writeColored(x + shadow_distance, y + shadow_distance, text, color, kerning, lenght); diff --git a/source/core/rendering/text.hpp b/source/core/rendering/text.hpp index fe7e920..35e074e 100644 --- a/source/core/rendering/text.hpp +++ b/source/core/rendering/text.hpp @@ -48,7 +48,9 @@ class Text { auto writeToSurface(const std::string& text, int zoom = 1, int kerning = 1) -> std::shared_ptr; // Escribe el texto en una textura auto writeDXToSurface(Uint8 flags, const std::string& text, int kerning = 1, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1) -> std::shared_ptr; // Escribe el texto con extras en una textura - [[nodiscard]] auto length(const std::string& text, int kerning = 1) const -> int; // Obtiene la longitud en pixels de una cadena + void writeColoredMono(int x, int y, const std::string& text, Uint8 color, int cell_w); // Escribe texto monoespaciado con color + [[nodiscard]] auto length(const std::string& text, int kerning = 1) const -> int; // Obtiene la longitud en pixels de una cadena + [[nodiscard]] auto lengthMono(const std::string& text, int cell_w) const -> int; // Obtiene la longitud en pixels de una cadena monoespaciada [[nodiscard]] auto getCharacterSize() const -> int; // Devuelve el tamaño del caracter [[nodiscard]] auto glyphWidth(uint32_t codepoint, int kerning = 0) const -> int; // Devuelve el ancho en pixels de un glifo [[nodiscard]] auto getGlyphClip(uint32_t codepoint) const -> SDL_FRect; // Devuelve el clip rect del glifo diff --git a/source/game/entities/player.cpp b/source/game/entities/player.cpp index 3486131..67d55fb 100644 --- a/source/game/entities/player.cpp +++ b/source/game/entities/player.cpp @@ -414,9 +414,12 @@ void Player::switchBorders() { // Aplica gravedad al jugador void Player::applyGravity(float delta_time) { - // La gravedad solo se aplica cuando el jugador esta en el aire if (state_ == State::ON_AIR) { - vy_ += GRAVITY_FORCE * delta_time; + // Si está subiendo y ha soltado el botón de salto, gravedad aumentada para cortar el salto + const float GRAVITY = (vy_ < 0.0F && !wanna_jump_) + ? GRAVITY_FORCE * LOW_JUMP_GRAVITY_MULT + : GRAVITY_FORCE; + vy_ += GRAVITY * delta_time; vy_ = std::min(vy_, MAX_VY); } } @@ -675,12 +678,16 @@ void Player::updateVelocity(float delta_time) { if (target > 0.0F) { sprite_->setFlip(Flip::RIGHT); } else if (target < 0.0F) { sprite_->setFlip(Flip::LEFT); } - // Aproximar vx_ al objetivo con paso limitado por la aceleración - const float STEP = HORIZONTAL_ACCEL * delta_time; - if (vx_ < target) { - vx_ = std::min(vx_ + STEP, target); - } else if (vx_ > target) { - vx_ = std::max(vx_ - STEP, target); + // En el aire: inercia (interpolación gradual). En suelo/rampa: respuesta inmediata. + if (state_ == State::ON_AIR) { + const float STEP = HORIZONTAL_ACCEL * delta_time; + if (vx_ < target) { + vx_ = std::min(vx_ + STEP, target); + } else if (vx_ > target) { + vx_ = std::max(vx_ - STEP, target); + } + } else { + vx_ = target; } } diff --git a/source/game/entities/player.hpp b/source/game/entities/player.hpp index a6c9145..df5af8b 100644 --- a/source/game/entities/player.hpp +++ b/source/game/entities/player.hpp @@ -38,6 +38,7 @@ class Player { static constexpr float MAX_VY = 160.0F; // Velocidad vertical máxima en pixels/segundo static constexpr float JUMP_VELOCITY = -140.0F; // Velocidad inicial del salto en pixels/segundo static constexpr float GRAVITY_FORCE = 360.0F; // Fuerza de gravedad en pixels/segundo² + static constexpr float LOW_JUMP_GRAVITY_MULT = 3.0F; // Multiplicador de gravedad al soltar el botón de salto (salto variable) struct SpawnData { float x = 0; diff --git a/source/game/gameplay/scoreboard.cpp b/source/game/gameplay/scoreboard.cpp index f60b2a7..d6a0758 100644 --- a/source/game/gameplay/scoreboard.cpp +++ b/source/game/gameplay/scoreboard.cpp @@ -2,67 +2,45 @@ #include +#include #include +#include -#include "core/locale/locale.hpp" // Para Locale -#include "core/rendering/screen.hpp" // Para Screen -#include "core/rendering/sprite/animated_sprite.hpp" // Para SAnimatedSprite -#include "core/rendering/surface.hpp" // Para Surface -#include "core/rendering/text.hpp" // Para Text -#include "core/resources/resource_cache.hpp" // Para Resource -#include "game/entities/player.hpp" // Para Player::skinToAnimationPath -#include "game/options.hpp" // Para Options, options, Cheat, OptionsGame -#include "utils/defines.hpp" // Para BLOCK -#include "utils/utils.hpp" +#include "core/locale/locale.hpp" +#include "core/rendering/screen.hpp" +#include "core/rendering/surface.hpp" +#include "core/rendering/text.hpp" +#include "core/resources/resource_cache.hpp" +#include "game/options.hpp" +#include "utils/defines.hpp" // Constructor Scoreboard::Scoreboard(std::shared_ptr data) - : item_surface_(Resource::Cache::get()->getSurface("items.gif")), - data_(std::move(std::move(data))) { + : data_(std::move(data)) { const float SURFACE_WIDTH = Options::game.width; - constexpr float SURFACE_HEIGHT = 6.0F * Tile::SIZE; - - // Reserva memoria para los objetos - const std::string PLAYER_ANIM_PATH = Player::skinToAnimationPath(Options::game.player_skin); - const auto& player_animation_data = Resource::Cache::get()->getAnimationData(PLAYER_ANIM_PATH); - player_sprite_ = std::make_shared(player_animation_data); - player_sprite_->setCurrentAnimation("default"); + constexpr float SURFACE_HEIGHT = 24.0F; // 3 líneas de 8px surface_ = std::make_shared(SURFACE_WIDTH, SURFACE_HEIGHT); surface_dest_ = {.x = 0, .y = Options::game.height - SURFACE_HEIGHT, .w = SURFACE_WIDTH, .h = SURFACE_HEIGHT}; - - // Inicializa el color de items - items_color_ = 14; - - // Inicializa el vector de colores - color_ = {2, 6, 8, 10, 12, 14, 3, 7, 9, 11, 13, 15}; } // Pinta el objeto en pantalla void Scoreboard::render() { - return; surface_->render(nullptr, &surface_dest_); } // Actualiza las variables del objeto void Scoreboard::update(float delta_time) { - // Acumular tiempo para animaciones - time_accumulator_ += delta_time; - - // Actualiza el color de la cantidad de items recogidos updateItemsColor(delta_time); - - // Dibuja la textura fillTexture(); if (!is_paused_) { - // Si está en pausa no se actualiza el reloj clock_ = getTime(); } } // Obtiene el tiempo transcurrido de partida -auto Scoreboard::getTime() -> Scoreboard::ClockData { // NOLINT(readability-convert-member-functions-to-static) +auto Scoreboard::getTime() -> Scoreboard::ClockData { const Uint32 TIME_ELAPSED = SDL_GetTicks() - data_->ini_clock - paused_time_elapsed_; ClockData time; @@ -74,51 +52,27 @@ auto Scoreboard::getTime() -> Scoreboard::ClockData { // NOLINT(readability-con return time; } -// Actualiza el sprite del jugador con la skin actual -void Scoreboard::refreshPlayerSkin() { - const std::string PLAYER_ANIM_PATH = Player::skinToAnimationPath(Options::game.player_skin); - const auto& player_animation_data = Resource::Cache::get()->getAnimationData(PLAYER_ANIM_PATH); - player_sprite_ = std::make_shared(player_animation_data); - player_sprite_->setCurrentAnimation("default"); -} - // Pone el marcador en modo pausa void Scoreboard::setPaused(bool value) { - if (is_paused_ == value) { - // Evita ejecutar lógica si el estado no cambia - return; - } - + if (is_paused_ == value) { return; } is_paused_ = value; if (is_paused_) { - // Guarda el tiempo actual al pausar paused_time_ = SDL_GetTicks(); } else { - // Calcula el tiempo pausado acumulado al reanudar paused_time_elapsed_ += SDL_GetTicks() - paused_time_; } } // Actualiza el color de la cantidad de items recogidos void Scoreboard::updateItemsColor(float delta_time) { - if (!data_->jail_is_open) { - return; - } + if (!data_->jail_is_open) { return; } items_color_timer_ += delta_time; - - // Resetear timer cada 2 ciclos (0.666s total) if (items_color_timer_ >= ITEMS_COLOR_BLINK_DURATION * 2.0F) { items_color_timer_ = 0.0F; } - - // Alternar color cada ITEMS_COLOR_BLINK_DURATION - if (items_color_timer_ < ITEMS_COLOR_BLINK_DURATION) { - items_color_ = 14; - } else { - items_color_ = 6; - } + items_color_ = (items_color_timer_ < ITEMS_COLOR_BLINK_DURATION) ? VALUE_COLOR : 6; } // Devuelve la cantidad de minutos de juego transcurridos @@ -126,56 +80,80 @@ auto Scoreboard::getMinutes() -> int { return getTime().minutes; } -// Dibuja los elementos del marcador en la textura +// Dibuja los elementos del marcador en la surface void Scoreboard::fillTexture() { - // Empieza a dibujar en la textura - auto previuos_renderer = Screen::get()->getRendererSurface(); + auto previous_renderer = Screen::get()->getRendererSurface(); Screen::get()->setRendererSurface(surface_); - // Limpia la textura surface_->clear(0); - // Dibuja las vidas - const int WALK_FRAMES = player_sprite_->getCurrentAnimationSize(); - const int DESP = static_cast(time_accumulator_ / SPRITE_WALK_CYCLE_DURATION) % (WALK_FRAMES * 2); - const int FRAME = DESP % WALK_FRAMES; - player_sprite_->setCurrentAnimationFrame(FRAME); - player_sprite_->setPosY(LINE2_Y); - for (int i = 0; i < data_->lives; ++i) { - player_sprite_->setPosX(LIVES_START_X + (LIVES_SPACING * i) + DESP); - const int INDEX = i % color_.size(); - player_sprite_->render(1, color_.at(INDEX)); - } + auto text = Resource::Cache::get()->getText("8bithud"); + const int CANVAS_W = static_cast(Options::game.width); + const std::string SEP = " - "; + const int MONO_W = 7; // Ancho fijo por carácter monoespaciado (dígitos + separador) - // Muestra si suena la música + // Valores formateados + const std::string LIVES_STR = std::to_string(data_->lives); + const std::string ITEMS_STR = std::to_string(data_->items); + const std::string TIME_STR = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + + clock_.separator + + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10); + + // --- Línea 1: vides X - objectes X - temps MM:SS (centrada) --- + const std::string LIVES_LABEL = Locale::get()->get("scoreboard.lives"); + const std::string ITEMS_LABEL = Locale::get()->get("scoreboard.items"); + const std::string TIME_LABEL = Locale::get()->get("scoreboard.time"); + + // Ancho total: labels proporcionales + valores monoespaciados + const int LINE1_W = text->length(LIVES_LABEL) + text->lengthMono(LIVES_STR, MONO_W) + + text->length(SEP) + text->length(ITEMS_LABEL) + text->lengthMono(ITEMS_STR, MONO_W) + + text->length(SEP) + text->length(TIME_LABEL) + text->lengthMono(TIME_STR, MONO_W); + + int x = (CANVAS_W - LINE1_W) / 2; + text->writeColored(x, LINE1_Y, LIVES_LABEL, LABEL_COLOR); + x += text->length(LIVES_LABEL); + text->writeColoredMono(x, LINE1_Y, LIVES_STR, VALUE_COLOR, MONO_W); + x += text->lengthMono(LIVES_STR, MONO_W); + text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR); + x += text->length(SEP); + text->writeColored(x, LINE1_Y, ITEMS_LABEL, LABEL_COLOR); + x += text->length(ITEMS_LABEL); + text->writeColoredMono(x, LINE1_Y, ITEMS_STR, items_color_, MONO_W); + x += text->lengthMono(ITEMS_STR, MONO_W); + text->writeColored(x, LINE1_Y, SEP, LABEL_COLOR); + x += text->length(SEP); + text->writeColored(x, LINE1_Y, TIME_LABEL, LABEL_COLOR); + x += text->length(TIME_LABEL); + text->writeColoredMono(x, LINE1_Y, TIME_STR, VALUE_COLOR, MONO_W); + + // --- Línea 2: indicadores activos (centrada) --- + std::vector indicators; if (data_->music) { - const Uint8 C = data_->color; - SDL_FRect clip = {.x = 0, .y = 8, .w = 8, .h = 8}; - item_surface_->renderWithColorReplace(MUSIC_ICON_X, LINE2_Y, 1, C, &clip); + indicators.push_back(Locale::get()->get("scoreboard.music_on")); } - - // Escribe los textos - auto text = Resource::Cache::get()->getText("smb2"); - const std::string TIME_TEXT = std::to_string((clock_.minutes % 100) / 10) + std::to_string(clock_.minutes % 10) + clock_.separator + std::to_string((clock_.seconds % 60) / 10) + std::to_string(clock_.seconds % 10); - const std::string ITEMS_TEXT = std::to_string(data_->items / 100) + std::to_string((data_->items % 100) / 10) + std::to_string(data_->items % 10); - text->writeColored(ITEMS_LABEL_X, LINE1_Y, Locale::get()->get("scoreboard.items"), data_->color); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(ITEMS_VALUE_X, LINE1_Y, ITEMS_TEXT, items_color_); - text->writeColored(TIME_LABEL_X, LINE1_Y, Locale::get()->get("scoreboard.time"), data_->color); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(TIME_VALUE_X, LINE1_Y, TIME_TEXT, 14); - - const std::string ROOMS_TEXT = std::to_string(data_->rooms / 100) + std::to_string((data_->rooms % 100) / 10) + std::to_string(data_->rooms % 10); - text->writeColored(ROOMS_LABEL_X, LINE2_Y, Locale::get()->get("scoreboard.rooms"), 14); // NOLINT(readability-static-accessed-through-instance) - text->writeColored(ROOMS_VALUE_X, LINE2_Y, ROOMS_TEXT, 14); - - // Indicadores de trucos activos (fuente 8bithud) - auto cheat_text = Resource::Cache::get()->getText("8bithud"); if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) { - cheat_text->writeColored(CHEAT_INF_LIVES_X, CHEAT_INF_LIVES_Y, Locale::get()->get("scoreboard.cheat_infinite_lives"), data_->color); // NOLINT(readability-static-accessed-through-instance) + indicators.push_back(Locale::get()->get("scoreboard.cheat_infinite_lives")); } if (Options::cheats.invincible == Options::Cheat::State::ENABLED) { - cheat_text->writeColored(CHEAT_INVINCIBLE_X, CHEAT_INVINCIBLE_Y, Locale::get()->get("scoreboard.cheat_invincibility"), data_->color); // NOLINT(readability-static-accessed-through-instance) + indicators.push_back(Locale::get()->get("scoreboard.cheat_invincibility")); } - // Deja el renderizador como estaba - Screen::get()->setRendererSurface(previuos_renderer); -} \ No newline at end of file + if (!indicators.empty()) { + int line2_w = 0; + for (size_t i = 0; i < indicators.size(); ++i) { + if (i > 0) { line2_w += text->length(SEP); } + line2_w += text->length(indicators[i]); + } + x = (CANVAS_W - line2_w) / 2; + for (size_t i = 0; i < indicators.size(); ++i) { + if (i > 0) { + text->writeColored(x, LINE2_Y, SEP, LABEL_COLOR); + x += text->length(SEP); + } + text->writeColored(x, LINE2_Y, indicators[i], LABEL_COLOR); + x += text->length(indicators[i]); + } + } + + Screen::get()->setRendererSurface(previous_renderer); +} diff --git a/source/game/gameplay/scoreboard.hpp b/source/game/gameplay/scoreboard.hpp index 7036d9f..35946b0 100644 --- a/source/game/gameplay/scoreboard.hpp +++ b/source/game/gameplay/scoreboard.hpp @@ -3,11 +3,10 @@ #include #include // Para shared_ptr -#include // Para string, basic_string +#include // Para string #include -#include // Para vector -class AnimatedSprite; // lines 10-10 -class Surface; // lines 11-11 + +class Surface; class Scoreboard { public: @@ -28,58 +27,43 @@ class Scoreboard { void render(); // Pinta el objeto en pantalla void update(float delta_time); // Actualiza las variables del objeto void setPaused(bool value); // Pone el marcador en modo pausa - void refreshPlayerSkin(); // Actualiza el sprite del jugador con la skin actual auto getMinutes() -> int; // Devuelve la cantidad de minutos de juego transcurridos private: // Tipos anidados struct ClockData { - int hours{0}; // Horas transcurridas - int minutes{0}; // Minutos transcurridos - int seconds{0}; // Segundos transcurridos - std::string separator{":"}; // Separador para mostrar el tiempo + int hours{0}; + int minutes{0}; + int seconds{0}; + std::string separator{":"}; }; // Constantes de tiempo - static constexpr float ITEMS_COLOR_BLINK_DURATION = 0.333F; // Duración de cada estado del parpadeo (era 10 frames @ 60fps) - static constexpr float SPRITE_WALK_CYCLE_DURATION = 0.667F; // Duración del ciclo de caminar (era 40 frames @ 60fps) + static constexpr float ITEMS_COLOR_BLINK_DURATION = 0.333F; - // Posición de los elementos del marcador (en pixels, Tile::SIZE = 8) - static constexpr int LINE1_Y = 8; // Fila superior (1 * Tile::SIZE) - static constexpr int LINE2_Y = 24; // Fila inferior (3 * Tile::SIZE) - static constexpr int ITEMS_LABEL_X = 8; // "TRESORS PILLATS" / "ITEMS COLLECTED" - static constexpr int ITEMS_VALUE_X = 136; // Valor numérico de items - static constexpr int TIME_LABEL_X = 160; // "HORA" / "TIME" - static constexpr int TIME_VALUE_X = 208; // Valor numérico del tiempo - static constexpr int LIVES_START_X = 8; // Primera vida (sprite) - static constexpr int LIVES_SPACING = 16; // Separación entre vidas - static constexpr int MUSIC_ICON_X = 160; // Icono de música - static constexpr int ROOMS_LABEL_X = 176; // "SALES" / "ROOMS" - static constexpr int ROOMS_VALUE_X = 224; // Valor numérico de salas - static constexpr int CHEAT_INF_LIVES_X = 176; // Indicador "vides inf" / "inf lives" - static constexpr int CHEAT_INF_LIVES_Y = 34; // Posición Y del indicador de vidas infinitas - static constexpr int CHEAT_INVINCIBLE_X = 231; // Indicador "inv" - static constexpr int CHEAT_INVINCIBLE_Y = 34; // Posición Y del indicador de invencibilidad + // Posición de los elementos (2 líneas centradas verticalmente en surface de 24px) + static constexpr int LINE1_Y = 5; + static constexpr int LINE2_Y = 13; + + // Colores + static constexpr Uint8 LABEL_COLOR = 11; + static constexpr Uint8 VALUE_COLOR = 9; // Métodos privados - auto getTime() -> ClockData; // Obtiene el tiempo transcurrido de partida - void updateItemsColor(float delta_time); // Actualiza el color de la cantidad de items recogidos - void fillTexture(); // Dibuja los elementos del marcador en la surface + auto getTime() -> ClockData; + void updateItemsColor(float delta_time); + void fillTexture(); // Objetos y punteros - std::shared_ptr player_sprite_; // Sprite para mostrar las vidas en el marcador - std::shared_ptr item_surface_; // Surface con los graficos para los elementos del marcador - std::shared_ptr data_; // Contiene las variables a mostrar en el marcador - std::shared_ptr surface_; // Surface donde dibujar el marcador + std::shared_ptr data_; + std::shared_ptr surface_; // Variables de estado - std::vector color_; // Vector con los colores del objeto - bool is_paused_{false}; // Indica si el marcador esta en modo pausa - Uint32 paused_time_{0}; // Milisegundos que ha estado el marcador en pausa - Uint32 paused_time_elapsed_{0}; // Tiempo acumulado en pausa - ClockData clock_{}; // Contiene las horas, minutos y segundos transcurridos desde el inicio de la partida - Uint8 items_color_{0}; // Color de la cantidad de items recogidos - SDL_FRect surface_dest_{}; // Rectangulo donde dibujar la surface del marcador - float time_accumulator_{0.0F}; // Acumulador de tiempo para animaciones - float items_color_timer_{0.0F}; // Timer para parpadeo de color de items + bool is_paused_{false}; + Uint32 paused_time_{0}; + Uint32 paused_time_elapsed_{0}; + ClockData clock_{}; + Uint8 items_color_{VALUE_COLOR}; + SDL_FRect surface_dest_{}; + float items_color_timer_{0.0F}; }; diff --git a/source/game/scenes/game.cpp b/source/game/scenes/game.cpp index c9b6e39..d78d42f 100644 --- a/source/game/scenes/game.cpp +++ b/source/game/scenes/game.cpp @@ -85,7 +85,6 @@ Game::Game(Mode mode) GameControl::change_player_skin = [this](const std::string& skin_name) -> void { Options::game.player_skin = skin_name; player_->setSkin(skin_name); - scoreboard_->refreshPlayerSkin(); }; GameControl::change_player_color = [this](int color) -> void { Options::game.player_color = color; @@ -548,10 +547,6 @@ void Game::renderDebugInfo() { auto surface = Screen::get()->getRendererSurface(); - // Borra el marcador - SDL_FRect rect = {.x = 0, .y = 18 * Tile::SIZE, .w = PlayArea::WIDTH, .h = GameCanvas::HEIGHT - PlayArea::HEIGHT}; - surface->fillRect(&rect, 0); - // Pinta la rejilla /*for (int i = 0; i < PlayArea::BOTTOM; i += 8) { diff --git a/source/game/ui/console.cpp b/source/game/ui/console.cpp index dd37c49..2aa87a7 100644 --- a/source/game/ui/console.cpp +++ b/source/game/ui/console.cpp @@ -144,6 +144,13 @@ void Console::redrawText() { SDL_FRect rect = {.x = 0, .y = 0, .w = WIDTH, .h = height_}; surface_->drawRectBorder(&rect, BORDER_COLOR); + // La surface de la fuente tiene transparent_color_=255 por defecto, + // pero sus píxeles de fondo son color 0. Cambiarlo temporalmente a 0 + // para que no pinte el fondo negro de los glyphs sobre la consola. + auto* font_surface = text_->getSprite()->getSurface().get(); + const Uint8 PREV_TRANSPARENT = font_surface->getTransparentColor(); + font_surface->setTransparentColor(0); + // Líneas de mensaje con efecto typewriter (solo muestra los primeros typewriter_chars_) int y_pos = PADDING_IN_V; int remaining = typewriter_chars_; @@ -160,6 +167,9 @@ void Console::redrawText() { const std::string INPUT_STR = prompt_ + input_line_ + (SHOW_CURSOR ? "_" : ""); text_->writeColored(PADDING_IN_H, y_pos, INPUT_STR, BORDER_COLOR); + // Restaurar transparent_color_ original de la fuente + font_surface->setTransparentColor(PREV_TRANSPARENT); + Screen::get()->setRendererSurface(previous_renderer); } diff --git a/source/game/ui/console.hpp b/source/game/ui/console.hpp index 987a938..6847a32 100644 --- a/source/game/ui/console.hpp +++ b/source/game/ui/console.hpp @@ -51,7 +51,7 @@ class Console { }; // Constantes visuales - static constexpr Uint8 BG_COLOR = 0; // PaletteColor::BLACK + static constexpr Uint8 BG_COLOR = 255; // Transparente (sin fondo) static constexpr Uint8 BORDER_COLOR = 9; // PaletteColor::BRIGHT_GREEN static constexpr Uint8 MSG_COLOR = 8; // PaletteColor::GREEN static constexpr float SLIDE_SPEED = 180.0F;