diff --git a/data/fonts/PixeloidSans-Bold.fnt b/data/fonts/PixeloidSans-Bold.fnt deleted file mode 100644 index 375dd08..0000000 --- a/data/fonts/PixeloidSans-Bold.fnt +++ /dev/null @@ -1,133 +0,0 @@ -# Font: PixeloidSans-Bold — generado desde PixeloidSans-Bold.ttf size 9 -# Generado con font_gen.py - -box_width 10 -box_height 11 -columns 15 - -# codepoint_decimal ancho_visual -32 4 # U+0020 -33 2 # ! -34 5 # " -35 7 # # -36 7 # $ -37 6 # % -38 7 # & -39 2 # ' -40 4 # ( -41 4 # ) -42 5 # * -43 4 # + -44 2 # , -45 4 # - -46 2 # . -47 6 # / -48 6 # 0 -49 6 # 1 -50 6 # 2 -51 6 # 3 -52 6 # 4 -53 6 # 5 -54 6 # 6 -55 6 # 7 -56 6 # 8 -57 6 # 9 -58 2 # : -59 2 # ; -60 4 # < -61 4 # = -62 4 # > -63 6 # ? -64 6 # @ -65 6 # A -66 6 # B -67 6 # C -68 6 # D -69 6 # E -70 6 # F -71 6 # G -72 6 # H -73 4 # I -74 5 # J -75 6 # K -76 6 # L -77 8 # M -78 7 # N -79 6 # O -80 6 # P -81 6 # Q -82 6 # R -83 6 # S -84 6 # T -85 6 # U -86 6 # V -87 8 # W -88 6 # X -89 6 # Y -90 6 # Z -91 5 # [ -92 6 # \ -93 5 # ] -94 6 # ^ -95 4 # _ -96 3 # ` -97 6 # a -98 6 # b -99 6 # c -100 6 # d -101 6 # e -102 4 # f -103 6 # g -104 6 # h -105 2 # i -106 5 # j -107 5 # k -108 2 # l -109 8 # m -110 6 # n -111 6 # o -112 6 # p -113 6 # q -114 5 # r -115 6 # s -116 4 # t -117 6 # u -118 6 # v -119 8 # w -120 6 # x -121 6 # y -122 6 # z -123 5 # { -124 2 # | -125 5 # } -126 7 # ~ -192 6 # À -193 6 # Á -200 6 # È -201 6 # É -204 4 # Ì -205 4 # Í -210 6 # Ò -211 6 # Ó -217 6 # Ù -218 6 # Ú -209 7 # Ñ -199 6 # Ç -224 6 # à -225 6 # á -232 6 # è -233 6 # é -236 3 # ì -237 3 # í -242 6 # ò -243 6 # ó -249 6 # ù -250 6 # ú -241 6 # ñ -231 6 # ç -161 2 # ¡ -191 6 # ¿ -171 7 # « -187 7 # » -183 2 # · -169 9 # © diff --git a/data/fonts/PixeloidSans-Bold.gif b/data/fonts/PixeloidSans-Bold.gif deleted file mode 100644 index 1711fc6..0000000 Binary files a/data/fonts/PixeloidSans-Bold.gif and /dev/null differ diff --git a/data/fonts/Tiny5-Regular.fnt b/data/fonts/Tiny5-Regular.fnt new file mode 100644 index 0000000..cd76292 --- /dev/null +++ b/data/fonts/Tiny5-Regular.fnt @@ -0,0 +1,133 @@ +# Font: Tiny5-Regular — generado desde Tiny5-Regular.ttf size 8 +# Generado con font_gen.py + +box_width 6 +box_height 9 +columns 15 + +# codepoint_decimal ancho_visual +32 2 # U+0020 +33 1 # ! +34 3 # " +35 5 # # +36 3 # $ +37 4 # % +38 4 # & +39 1 # ' +40 2 # ( +41 2 # ) +42 3 # * +43 3 # + +44 2 # , +45 3 # - +46 1 # . +47 2 # / +48 3 # 0 +49 2 # 1 +50 3 # 2 +51 3 # 3 +52 3 # 4 +53 3 # 5 +54 3 # 6 +55 3 # 7 +56 3 # 8 +57 3 # 9 +58 1 # : +59 2 # ; +60 3 # < +61 3 # = +62 3 # > +63 3 # ? +64 4 # @ +65 4 # A +66 4 # B +67 4 # C +68 4 # D +69 4 # E +70 4 # F +71 4 # G +72 4 # H +73 1 # I +74 3 # J +75 4 # K +76 3 # L +77 5 # M +78 4 # N +79 4 # O +80 4 # P +81 4 # Q +82 4 # R +83 4 # S +84 3 # T +85 4 # U +86 3 # V +87 5 # W +88 3 # X +89 3 # Y +90 3 # Z +91 2 # [ +92 2 # \ +93 2 # ] +94 3 # ^ +95 3 # _ +96 2 # ` +97 3 # a +98 3 # b +99 3 # c +100 3 # d +101 3 # e +102 2 # f +103 3 # g +104 3 # h +105 1 # i +106 1 # j +107 3 # k +108 1 # l +109 5 # m +110 3 # n +111 3 # o +112 3 # p +113 3 # q +114 2 # r +115 3 # s +116 2 # t +117 3 # u +118 3 # v +119 5 # w +120 3 # x +121 3 # y +122 3 # z +123 3 # { +124 1 # | +125 3 # } +126 2 # ~ +192 4 # À +193 4 # Á +200 4 # È +201 4 # É +204 2 # Ì +205 2 # Í +210 4 # Ò +211 4 # Ó +217 4 # Ù +218 4 # Ú +209 4 # Ñ +199 4 # Ç +224 3 # à +225 3 # á +232 3 # è +233 3 # é +236 2 # ì +237 2 # í +242 3 # ò +243 3 # ó +249 3 # ù +250 3 # ú +241 3 # ñ +231 3 # ç +161 1 # ¡ +191 3 # ¿ +171 5 # « +187 5 # » +183 1 # · +169 3 # © diff --git a/data/fonts/Tiny5-Regular.gif b/data/fonts/Tiny5-Regular.gif new file mode 100644 index 0000000..1e9087e Binary files /dev/null and b/data/fonts/Tiny5-Regular.gif differ diff --git a/data/title/game_logo.gif b/data/title/game_logo.gif index 0d61106..345692c 100644 Binary files a/data/title/game_logo.gif and b/data/title/game_logo.gif differ diff --git a/data/title/title_bg.gif b/data/title/title_bg.gif index 42c0d74..cef3c84 100644 Binary files a/data/title/title_bg.gif and b/data/title/title_bg.gif differ diff --git a/data/ui.yaml b/data/ui.yaml index 98da804..803051c 100644 --- a/data/ui.yaml +++ b/data/ui.yaml @@ -58,13 +58,14 @@ fonts: gif: "data/fonts/ari-w9500-condensed-display.gif" fnt: "data/fonts/ari-w9500-condensed-display.fnt" kerning: 0 - # Copyright de la TITLE: pixel-art estricte (PixeloidSans-Bold size 9 - # generat amb font-gen). Diferenciada de la `placeholder` que pinta - # el "press start" — així la jerarquia tipogràfica del peu queda neta. + # Copyright de la TITLE: pixel-art estricte (Tiny5-Regular size 5, + # caixa 3×6 px) generat amb font-gen. Diferenciada de la `placeholder` + # que pinta el "press start" — així la jerarquia tipogràfica del peu + # queda neta. copyright: - name: "PixeloidSans-Bold" - gif: "data/fonts/PixeloidSans-Bold.gif" - fnt: "data/fonts/PixeloidSans-Bold.fnt" + name: "Tiny5-Regular" + gif: "data/fonts/Tiny5-Regular.gif" + fnt: "data/fonts/Tiny5-Regular.fnt" kerning: 1 hud: @@ -121,7 +122,23 @@ title: duration_ms: 30000 bg_color: 1 text_color: 31 - copyright_color: 19 + # Color del text del © de copyright (peu de la TITLE). Off-white càlid: + # índex 183 = (255,218,170), tipus crema/peach, ~90% blanc amb tint càlid. + copyright_color: 183 + # Color de l'outline del prompt "PRESS START". Marró fosc càlid (índex + # 19 = 109,72,0), coherent amb la paleta del logo. Es manté separat de + # `copyright_color` perquè l'outline i el text del © tenen rols visuals + # diferents (contrast vs. peu informatiu). + press_start_outline_color: 19 + # Posicions Y dels tres elements verticals de la TITLE, en percentatge + # sobre l'alçada del canvas (240 px). El logo s'ancora pel seu top + # (la imatge cau cap avall des d'aquest Y); el prompt i el copyright + # es centren verticalment sobre la línia. + logo_y_percent: 15 + prompt_y_percent: 68 + copyright_y_percent: 92 + # Separació vertical en píxels entre el minilogo i el text del © al peu. + mini_logo_gap_px: 2 blink_visible_ms: 800 blink_hidden_ms: 200 # Fase STARTING (entre la primera pulsació de START i el salt a la diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 582d707..ee5f760 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -200,7 +200,7 @@ Director::Director() { placeholder_text->setDefaultKerning(UiConfig::get().placeholderFont().kerning); placeholder_text_ = placeholder_text; - // Font del copyright de la TITLE (PixeloidSans-Bold). Pixel-art + // Font del copyright de la TITLE (Tiny5-Regular size 8). Pixel-art // estricte; va amb la paleta UI per compartir índex de color amb la // resta de textos placeholder. const std::string COPYRIGHT_FONT_GIF_KEY = UiConfig::get().copyrightFont().name + ".gif"; diff --git a/source/core/ui/ui_config.cpp b/source/core/ui/ui_config.cpp index 8944ad9..2f9d6ae 100644 --- a/source/core/ui/ui_config.cpp +++ b/source/core/ui/ui_config.cpp @@ -100,6 +100,11 @@ UiConfig::UiConfig() title_bg_color_(Defaults::UI::Title::BG_COLOR), title_text_color_(Defaults::UI::Title::TEXT_COLOR), title_copyright_color_(Defaults::UI::Title::COPYRIGHT_COLOR), + title_press_start_outline_color_(Defaults::UI::Title::PRESS_START_OUTLINE_COLOR), + title_logo_y_percent_(Defaults::UI::Title::LOGO_Y_PERCENT), + title_prompt_y_percent_(Defaults::UI::Title::PROMPT_Y_PERCENT), + title_copyright_y_percent_(Defaults::UI::Title::COPYRIGHT_Y_PERCENT), + title_mini_logo_gap_px_(Defaults::UI::Title::MINI_LOGO_GAP_PX), title_blink_visible_ms_(Defaults::UI::Title::BLINK_VISIBLE_MS), title_blink_hidden_ms_(Defaults::UI::Title::BLINK_HIDDEN_MS), title_starting_ms_(Defaults::UI::Title::STARTING_MS), @@ -233,6 +238,11 @@ void UiConfig::load(const std::string& file_path) { readColorIndex(t, "bg_color", title_bg_color_); readColorIndex(t, "text_color", title_text_color_); readColorIndex(t, "copyright_color", title_copyright_color_); + readColorIndex(t, "press_start_outline_color", title_press_start_outline_color_); + readField(t, "logo_y_percent", title_logo_y_percent_); + readField(t, "prompt_y_percent", title_prompt_y_percent_); + readField(t, "copyright_y_percent", title_copyright_y_percent_); + readField(t, "mini_logo_gap_px", title_mini_logo_gap_px_); readField(t, "blink_visible_ms", title_blink_visible_ms_); readField(t, "blink_hidden_ms", title_blink_hidden_ms_); readField(t, "starting_ms", title_starting_ms_); diff --git a/source/core/ui/ui_config.hpp b/source/core/ui/ui_config.hpp index aee03e3..2e60237 100644 --- a/source/core/ui/ui_config.hpp +++ b/source/core/ui/ui_config.hpp @@ -93,6 +93,11 @@ class UiConfig { [[nodiscard]] auto titleBgColor() const -> Uint8 { return title_bg_color_; } [[nodiscard]] auto titleTextColor() const -> Uint8 { return title_text_color_; } [[nodiscard]] auto titleCopyrightColor() const -> Uint8 { return title_copyright_color_; } + [[nodiscard]] auto titlePressStartOutlineColor() const -> Uint8 { return title_press_start_outline_color_; } + [[nodiscard]] auto titleLogoYPercent() const -> int { return title_logo_y_percent_; } + [[nodiscard]] auto titlePromptYPercent() const -> int { return title_prompt_y_percent_; } + [[nodiscard]] auto titleCopyrightYPercent() const -> int { return title_copyright_y_percent_; } + [[nodiscard]] auto titleMiniLogoGapPx() const -> int { return title_mini_logo_gap_px_; } [[nodiscard]] auto titleBlinkVisibleMs() const -> int { return title_blink_visible_ms_; } [[nodiscard]] auto titleBlinkHiddenMs() const -> int { return title_blink_hidden_ms_; } [[nodiscard]] auto titleStartingMs() const -> int { return title_starting_ms_; } @@ -174,6 +179,11 @@ class UiConfig { Uint8 title_bg_color_; Uint8 title_text_color_; Uint8 title_copyright_color_; + Uint8 title_press_start_outline_color_; + int title_logo_y_percent_; + int title_prompt_y_percent_; + int title_copyright_y_percent_; + int title_mini_logo_gap_px_; int title_blink_visible_ms_; int title_blink_hidden_ms_; int title_starting_ms_; diff --git a/source/game/scenes/title_scene.cpp b/source/game/scenes/title_scene.cpp index 53507f2..5866a92 100644 --- a/source/game/scenes/title_scene.cpp +++ b/source/game/scenes/title_scene.cpp @@ -32,11 +32,6 @@ namespace { // docs/audit-core-rendering.md). const char* const SCENE_NAME = "TITLE"; - constexpr int TITLE_Y_PERCENT = 25; - constexpr int PROMPT_Y_PERCENT = 60; - constexpr int COPYRIGHT_Y_PERCENT = 90; - constexpr int LOGO_GAP_PX = 2; // Separació vertical entre el minilogo i el text de copyright. - // Detecta una pulsació de START dins el frame actual per al jugador // indicat. Combina events de teclat (scancode hardcoded a Defaults:: // KeysGame[P2]) i events de gamepad (botó remapejable via @@ -259,7 +254,7 @@ void TitleScene::render() { } const Uint8 TEXT_COLOR = ui_config.titleTextColor(); - const Uint8 OUTLINE_COLOR = ui_config.titleCopyrightColor(); + const Uint8 OUTLINE_COLOR = ui_config.titlePressStartOutlineColor(); constexpr Uint8 OUTLINE_DIST = 1; constexpr Uint8 STROKE4 = Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG; @@ -268,7 +263,7 @@ void TitleScene::render() { // la primera línia del text. Substitueix els dos `display_font_` // que pintaven "Aventures en Egipte" + "A R C A D E". if (game_logo_) { - const int LOGO_Y = (GameCanvas::HEIGHT * TITLE_Y_PERCENT) / 100; + const int LOGO_Y = (GameCanvas::HEIGHT * ui_config.titleLogoYPercent()) / 100; const int LOGO_X = GameCanvas::CENTER_X - (game_logo_->getWidth() / 2); game_logo_->render(LOGO_X, LOGO_Y); } @@ -290,7 +285,7 @@ void TitleScene::render() { const bool VISIBLE = (cycle_ms == 0) || ((blink_elapsed_ms_ % cycle_ms) < visible_ms); if (VISIBLE) { - const int PROMPT_Y = (GameCanvas::HEIGHT * PROMPT_Y_PERCENT) / 100; + const int PROMPT_Y = (GameCanvas::HEIGHT * ui_config.titlePromptYPercent()) / 100; condensed_font_->writeDX(STROKE4, GameCanvas::CENTER_X, PROMPT_Y, @@ -303,15 +298,16 @@ void TitleScene::render() { } // Footer: minilogo centrat horitzontalment damunt del © de - // copyright. El text va al 90% Y, el logo just damunt amb un petit - // gap (LOGO_GAP_PX). El copyright fa servir una font pixel-art - // pròpia (PixeloidSans-Bold) — més neta i petita que la del - // "press start" perquè la jerarquia tipogràfica del peu quedi clara. + // copyright. El text va al `title.copyright_y_percent`, el logo just + // damunt amb un petit gap (`title.mini_logo_gap_px`). El copyright fa + // servir una font pixel-art pròpia (Tiny5-Regular size 8) — més neta + // i petita que la del "press start" perquè la jerarquia tipogràfica + // del peu quedi clara. if (copyright_font_) { - const int COPY_Y = (GameCanvas::HEIGHT * COPYRIGHT_Y_PERCENT) / 100; + const int COPY_Y = (GameCanvas::HEIGHT * ui_config.titleCopyrightYPercent()) / 100; if (mini_logo_) { const int LOGO_X = GameCanvas::CENTER_X - (mini_logo_->getWidth() / 2); - const int LOGO_Y = COPY_Y - mini_logo_->getHeight() - LOGO_GAP_PX; + const int LOGO_Y = COPY_Y - mini_logo_->getHeight() - ui_config.titleMiniLogoGapPx(); mini_logo_->render(LOGO_X, LOGO_Y); } copyright_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, diff --git a/source/utils/defaults.hpp b/source/utils/defaults.hpp index 67d63c7..8831f2c 100644 --- a/source/utils/defaults.hpp +++ b/source/utils/defaults.hpp @@ -158,13 +158,13 @@ namespace Defaults { constexpr int MENU_ITEMS_KERNING = 0; // Copyright al peu de la TITLE: pixel-art estricte, generat amb - // font-gen a partir de PixeloidSans-Bold size 9. La separem - // de la `placeholder` (que la fa servir el "press start") per - // diferenciar tipogràficament jerarquia: prompt destacat amb - // outline gros, copyright net i petit a baix. - constexpr const char* COPYRIGHT_NAME = "PixeloidSans-Bold"; - constexpr const char* COPYRIGHT_GIF = "data/fonts/PixeloidSans-Bold.gif"; - constexpr const char* COPYRIGHT_FNT = "data/fonts/PixeloidSans-Bold.fnt"; + // font-gen a partir de Tiny5-Regular size 5 (caixa 3×6 px). La + // separem de la `placeholder` (que la fa servir el "press start") + // per diferenciar tipogràficament jerarquia: prompt destacat amb + // outline gros, copyright net i micro a baix. + constexpr const char* COPYRIGHT_NAME = "Tiny5-Regular"; + constexpr const char* COPYRIGHT_GIF = "data/fonts/Tiny5-Regular.gif"; + constexpr const char* COPYRIGHT_FNT = "data/fonts/Tiny5-Regular.fnt"; constexpr int COPYRIGHT_KERNING = 0; } // namespace Font @@ -271,7 +271,22 @@ namespace Defaults { constexpr int DURATION_MS = 30000; constexpr Uint8 BG_COLOR = 1; constexpr Uint8 TEXT_COLOR = 31; - constexpr Uint8 COPYRIGHT_COLOR = 246; // (218,218,255) off-white amb un mínim de fred. + // Color del text de "© 2026 JailDesigner": off-white càlid (índex + // 183 = 255,218,170, peach/cream) — ~90% blanc amb tint càlid. + constexpr Uint8 COPYRIGHT_COLOR = 183; + // Color de l'outline del prompt "PRESS START" (no del copyright, + // tot i compartir-se a versions antigues). Marró fosc càlid + // (índex 19 = 109,72,0) coherent amb la paleta del logo. + constexpr Uint8 PRESS_START_OUTLINE_COLOR = 19; + // Posicions Y dels tres elements verticals de la TITLE, en + // percentatge sobre `GameCanvas::HEIGHT`. El logo s'ancora pel + // seu top (la imatge cau cap avall des d'aquest Y); el prompt + // i el copyright es centren verticalment sobre la línia. + constexpr int LOGO_Y_PERCENT = 15; + constexpr int PROMPT_Y_PERCENT = 68; + constexpr int COPYRIGHT_Y_PERCENT = 92; + // Separació vertical entre el minilogo i el text del © al peu. + constexpr int MINI_LOGO_GAP_PX = 2; constexpr int BLINK_VISIBLE_MS = 800; constexpr int BLINK_HIDDEN_MS = 200;