feat(title): game_logo.gif al lloc del text i font PixeloidSans-Bold per al copyright

This commit is contained in:
JailDesigner committed 2026-05-06 22:35:27 +02:00
1 parent 8bc45ccedc
commit 233fcb8226
11 files changed
+197 -45

No files matched your search

+133
View File
@@ -0,0 +1,133 @@
# 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 # ©
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+9 -1
View File
@@ -58,6 +58,14 @@ fonts:
gif: "data/fonts/ari-w9500-condensed-display.gif" gif: "data/fonts/ari-w9500-condensed-display.gif"
fnt: "data/fonts/ari-w9500-condensed-display.fnt" fnt: "data/fonts/ari-w9500-condensed-display.fnt"
kerning: 0 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:
name: "PixeloidSans-Bold"
gif: "data/fonts/PixeloidSans-Bold.gif"
fnt: "data/fonts/PixeloidSans-Bold.fnt"
kerning: 1
hud: hud:
bg_enabled: false bg_enabled: false
@@ -113,7 +121,7 @@ title:
duration_ms: 30000 duration_ms: 30000
bg_color: 1 bg_color: 1
text_color: 31 text_color: 31
copyright_color: 246 copyright_color: 19
blink_visible_ms: 800 blink_visible_ms: 800
blink_hidden_ms: 200 blink_hidden_ms: 200
# Fase STARTING (entre la primera pulsació de START i el salt a la # Fase STARTING (entre la primera pulsació de START i el salt a la
+18 -2
View File
@@ -200,6 +200,16 @@ Director::Director() {
placeholder_text->setDefaultKerning(UiConfig::get().placeholderFont().kerning); placeholder_text->setDefaultKerning(UiConfig::get().placeholderFont().kerning);
placeholder_text_ = placeholder_text; placeholder_text_ = placeholder_text;
// Font del copyright de la TITLE (PixeloidSans-Bold). 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";
Resource::Cache::get().loadSurface(COPYRIGHT_FONT_GIF_KEY, UiConfig::get().copyrightFont().gif);
Resource::Cache::get().getSurface(COPYRIGHT_FONT_GIF_KEY)->setPalette(Resource::Cache::get().getPalette("ui"));
auto copyright_text = std::make_shared<Text>(Resource::Cache::get().getSurface(COPYRIGHT_FONT_GIF_KEY), UiConfig::get().copyrightFont().fnt);
copyright_text->setDefaultKerning(UiConfig::get().copyrightFont().kerning);
copyright_text_ = copyright_text;
// Font del menú de servei (F9). El títol va amb la variant `display` // Font del menú de servei (F9). El títol va amb la variant `display`
// i els items amb `condensed-display` (més compacte perquè caben més // i els items amb `condensed-display` (més compacte perquè caben més
// files). Els dos noms i kernings viuen a data/ui.yaml via UiConfig. // files). Els dos noms i kernings viuen a data/ui.yaml via UiConfig.
@@ -213,7 +223,6 @@ Director::Director() {
}; };
auto menu_title_text = load_menu_font(UiConfig::get().menuTitleFont()); auto menu_title_text = load_menu_font(UiConfig::get().menuTitleFont());
auto menu_items_text = load_menu_font(UiConfig::get().menuItemsFont()); auto menu_items_text = load_menu_font(UiConfig::get().menuItemsFont());
menu_title_text_ = menu_title_text;
// Mini-logo del peu de la TITLE. Es preloda ací per consistència // Mini-logo del peu de la TITLE. Es preloda ací per consistència
// amb la resta d'assets d'UI; manté la seua paleta original (no la // amb la resta d'assets d'UI; manté la seua paleta original (no la
@@ -231,6 +240,13 @@ Director::Director() {
Resource::Cache::get().loadSurface(LOGO_FULL_KEY, "data/logo/logo_jailgames.gif"); Resource::Cache::get().loadSurface(LOGO_FULL_KEY, "data/logo/logo_jailgames.gif");
logo_full_surface_ = Resource::Cache::get().getSurface(LOGO_FULL_KEY); logo_full_surface_ = Resource::Cache::get().getSurface(LOGO_FULL_KEY);
// Logotip del joc per a la TITLE (substitueix el text "Aventures en
// Egipte ARCADE"). Igual que la resta de logos, paleta nadiua —
// l'art ja porta els colors finals i no passa per la UI.
constexpr const char* GAME_LOGO_KEY = "game_logo.gif";
Resource::Cache::get().loadSurface(GAME_LOGO_KEY, "data/title/game_logo.gif");
game_logo_surface_ = Resource::Cache::get().getSurface(GAME_LOGO_KEY);
// Fons sencer de la TITLE (320×240). Igual que el minilogo, conserva // Fons sencer de la TITLE (320×240). Igual que el minilogo, conserva
// la seua paleta nadiua perquè el GIF ja porta els colors finals. // la seua paleta nadiua perquè el GIF ja porta els colors finals.
constexpr const char* TITLE_BG_KEY = "title_bg.gif"; constexpr const char* TITLE_BG_KEY = "title_bg.gif";
@@ -437,7 +453,7 @@ auto Director::buildScene(SceneId id, const SceneParams& params) -> std::unique_
return std::make_unique<LogoScene>(logo_full_surface_, p.reset); return std::make_unique<LogoScene>(logo_full_surface_, p.reset);
} }
case SceneId::TITLE: case SceneId::TITLE:
return std::make_unique<TitleScene>(menu_title_text_, placeholder_text_, title_bg_surface_, mini_logo_surface_); return std::make_unique<TitleScene>(placeholder_text_, copyright_text_, title_bg_surface_, game_logo_surface_, mini_logo_surface_);
case SceneId::INTRO: { case SceneId::INTRO: {
const auto& p = std::get<IntroParams>(params); const auto& p = std::get<IntroParams>(params);
return std::make_unique<IntroScene>(placeholder_text_, p.starting_players); return std::make_unique<IntroScene>(placeholder_text_, p.starting_players);
+2 -1
View File
@@ -30,8 +30,9 @@ class Director {
// escena. No són `static`/Meyers perquè depenen de l'inici d'SDL i // escena. No són `static`/Meyers perquè depenen de l'inici d'SDL i
// de Resource::Cache. // de Resource::Cache.
std::shared_ptr<Text> placeholder_text_; std::shared_ptr<Text> placeholder_text_;
std::shared_ptr<Text> menu_title_text_; std::shared_ptr<Text> copyright_text_;
std::shared_ptr<Surface> title_bg_surface_; std::shared_ptr<Surface> title_bg_surface_;
std::shared_ptr<Surface> game_logo_surface_;
std::shared_ptr<Surface> mini_logo_surface_; std::shared_ptr<Surface> mini_logo_surface_;
std::shared_ptr<Surface> logo_full_surface_; std::shared_ptr<Surface> logo_full_surface_;
+2
View File
@@ -123,6 +123,7 @@ UiConfig::UiConfig()
room_text_font_{.name = Defaults::UI::Font::ROOM_TEXT_NAME, .gif = Defaults::UI::Font::ROOM_TEXT_GIF, .fnt = Defaults::UI::Font::ROOM_TEXT_FNT, .kerning = Defaults::UI::Font::ROOM_TEXT_KERNING}, room_text_font_{.name = Defaults::UI::Font::ROOM_TEXT_NAME, .gif = Defaults::UI::Font::ROOM_TEXT_GIF, .fnt = Defaults::UI::Font::ROOM_TEXT_FNT, .kerning = Defaults::UI::Font::ROOM_TEXT_KERNING},
menu_title_font_{.name = Defaults::UI::Font::MENU_TITLE_NAME, .gif = Defaults::UI::Font::MENU_TITLE_GIF, .fnt = Defaults::UI::Font::MENU_TITLE_FNT, .kerning = Defaults::UI::Font::MENU_TITLE_KERNING}, menu_title_font_{.name = Defaults::UI::Font::MENU_TITLE_NAME, .gif = Defaults::UI::Font::MENU_TITLE_GIF, .fnt = Defaults::UI::Font::MENU_TITLE_FNT, .kerning = Defaults::UI::Font::MENU_TITLE_KERNING},
menu_items_font_{.name = Defaults::UI::Font::MENU_ITEMS_NAME, .gif = Defaults::UI::Font::MENU_ITEMS_GIF, .fnt = Defaults::UI::Font::MENU_ITEMS_FNT, .kerning = Defaults::UI::Font::MENU_ITEMS_KERNING}, menu_items_font_{.name = Defaults::UI::Font::MENU_ITEMS_NAME, .gif = Defaults::UI::Font::MENU_ITEMS_GIF, .fnt = Defaults::UI::Font::MENU_ITEMS_FNT, .kerning = Defaults::UI::Font::MENU_ITEMS_KERNING},
copyright_font_{.name = Defaults::UI::Font::COPYRIGHT_NAME, .gif = Defaults::UI::Font::COPYRIGHT_GIF, .fnt = Defaults::UI::Font::COPYRIGHT_FNT, .kerning = Defaults::UI::Font::COPYRIGHT_KERNING},
notifier_{ notifier_{
.padding_h = Defaults::UI::Notifier::PADDING_H, .padding_h = Defaults::UI::Notifier::PADDING_H,
.padding_top = Defaults::UI::Notifier::PADDING_TOP, .padding_top = Defaults::UI::Notifier::PADDING_TOP,
@@ -200,6 +201,7 @@ void UiConfig::load(const std::string& file_path) {
readFont(f, "room_text", room_text_font_); readFont(f, "room_text", room_text_font_);
readFont(f, "menu_title", menu_title_font_); readFont(f, "menu_title", menu_title_font_);
readFont(f, "menu_items", menu_items_font_); readFont(f, "menu_items", menu_items_font_);
readFont(f, "copyright", copyright_font_);
} }
if (yaml.contains("hud")) { if (yaml.contains("hud")) {
+2
View File
@@ -127,6 +127,7 @@ class UiConfig {
[[nodiscard]] auto roomTextFont() const -> const Font& { return room_text_font_; } [[nodiscard]] auto roomTextFont() const -> const Font& { return room_text_font_; }
[[nodiscard]] auto menuTitleFont() const -> const Font& { return menu_title_font_; } [[nodiscard]] auto menuTitleFont() const -> const Font& { return menu_title_font_; }
[[nodiscard]] auto menuItemsFont() const -> const Font& { return menu_items_font_; } [[nodiscard]] auto menuItemsFont() const -> const Font& { return menu_items_font_; }
[[nodiscard]] auto copyrightFont() const -> const Font& { return copyright_font_; }
// Geometria del Notifier. // Geometria del Notifier.
[[nodiscard]] auto notifier() const -> const Notifier& { return notifier_; } [[nodiscard]] auto notifier() const -> const Notifier& { return notifier_; }
@@ -193,6 +194,7 @@ class UiConfig {
Font room_text_font_; Font room_text_font_;
Font menu_title_font_; Font menu_title_font_;
Font menu_items_font_; Font menu_items_font_;
Font copyright_font_;
Notifier notifier_; Notifier notifier_;
+18 -39
View File
@@ -32,11 +32,6 @@ namespace {
// docs/audit-core-rendering.md). // docs/audit-core-rendering.md).
const char* const SCENE_NAME = "TITLE"; const char* const SCENE_NAME = "TITLE";
// Textos hardcodejats fins que tinguem artwork. Quan apareguen com
// a sprites, aquesta secció desapareix sencera.
const char* const TITLE_LINE_1 = "Aventures en Egipte";
const char* const TITLE_LINE_2 = "A R C A D E";
constexpr int TITLE_Y_PERCENT = 25; constexpr int TITLE_Y_PERCENT = 25;
constexpr int PROMPT_Y_PERCENT = 60; constexpr int PROMPT_Y_PERCENT = 60;
constexpr int COPYRIGHT_Y_PERCENT = 90; constexpr int COPYRIGHT_Y_PERCENT = 90;
@@ -63,14 +58,6 @@ namespace {
}); });
} }
// Separació vertical entre la primera i segona línia del títol. Una
// alçada de línia és l'opció més llegible al canvas de 240 px sense
// entrar a configuració extra; si demà cal afinar-ho, mou-se a
// ui.yaml.
[[nodiscard]] auto titleLineGap(const Text& font) -> int {
return font.getLineHeight();
}
// Reproducció del so de START. Centralitzat ací per disparar-lo des // Reproducció del so de START. Centralitzat ací per disparar-lo des
// dels punts on una pulsació té efecte real (entrada a STARTING o // dels punts on una pulsació té efecte real (entrada a STARTING o
// upgrade a BOTH); l'attract timeout no l'ha de tocar. // upgrade a BOTH); l'attract timeout no l'ha de tocar.
@@ -82,10 +69,11 @@ namespace {
} // namespace } // namespace
TitleScene::TitleScene(std::shared_ptr<Text> display_font, std::shared_ptr<Text> condensed_font, std::shared_ptr<Surface> background, std::shared_ptr<Surface> mini_logo) TitleScene::TitleScene(std::shared_ptr<Text> condensed_font, std::shared_ptr<Text> copyright_font, std::shared_ptr<Surface> background, std::shared_ptr<Surface> game_logo, std::shared_ptr<Surface> mini_logo)
: display_font_(std::move(display_font)), : condensed_font_(std::move(condensed_font)),
condensed_font_(std::move(condensed_font)), copyright_font_(std::move(copyright_font)),
background_(std::move(background)), background_(std::move(background)),
game_logo_(std::move(game_logo)),
mini_logo_(std::move(mini_logo)), mini_logo_(std::move(mini_logo)),
timer_ms_(UiConfig::get().titleDurationMs()) { timer_ms_(UiConfig::get().titleDurationMs()) {
std::cout << "[scene] " << SCENE_NAME << " start\n"; std::cout << "[scene] " << SCENE_NAME << " start\n";
@@ -275,24 +263,14 @@ void TitleScene::render() {
constexpr Uint8 OUTLINE_DIST = 1; constexpr Uint8 OUTLINE_DIST = 1;
constexpr Uint8 STROKE4 = Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG; constexpr Uint8 STROKE4 = Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG;
if (display_font_) { // Logotip del joc: GIF amb la seua paleta nadiua, centrat
const int TITLE_Y = (GameCanvas::HEIGHT * TITLE_Y_PERCENT) / 100; // horitzontalment al canvas i ancorat al mateix Y on abans naixia
display_font_->writeDX(STROKE4, // la primera línia del text. Substitueix els dos `display_font_`
GameCanvas::CENTER_X, // que pintaven "Aventures en Egipte" + "A R C A D E".
TITLE_Y, if (game_logo_) {
TITLE_LINE_1, const int LOGO_Y = (GameCanvas::HEIGHT * TITLE_Y_PERCENT) / 100;
display_font_->getDefaultKerning(), const int LOGO_X = GameCanvas::CENTER_X - (game_logo_->getWidth() / 2);
TEXT_COLOR, game_logo_->render(LOGO_X, LOGO_Y);
OUTLINE_DIST,
OUTLINE_COLOR);
display_font_->writeDX(STROKE4,
GameCanvas::CENTER_X,
TITLE_Y + titleLineGap(*display_font_),
TITLE_LINE_2,
display_font_->getDefaultKerning(),
TEXT_COLOR,
OUTLINE_DIST,
OUTLINE_COLOR);
} }
if (condensed_font_) { if (condensed_font_) {
@@ -326,20 +304,21 @@ void TitleScene::render() {
// Footer: minilogo centrat horitzontalment damunt del © de // Footer: minilogo centrat horitzontalment damunt del © de
// copyright. El text va al 90% Y, el logo just damunt amb un petit // copyright. El text va al 90% Y, el logo just damunt amb un petit
// gap (LOGO_GAP_PX). Tots dos blocs són hardcodejats fins que // gap (LOGO_GAP_PX). El copyright fa servir una font pixel-art
// tinguem artwork final. // pròpia (PixeloidSans-Bold) — més neta i petita que la del
if (condensed_font_) { // "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 * COPYRIGHT_Y_PERCENT) / 100;
if (mini_logo_) { if (mini_logo_) {
const int LOGO_X = GameCanvas::CENTER_X - (mini_logo_->getWidth() / 2); 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() - LOGO_GAP_PX;
mini_logo_->render(LOGO_X, LOGO_Y); mini_logo_->render(LOGO_X, LOGO_Y);
} }
condensed_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, copyright_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG,
GameCanvas::CENTER_X, GameCanvas::CENTER_X,
COPY_Y, COPY_Y,
"© 2026 JailDesigner", "© 2026 JailDesigner",
condensed_font_->getDefaultKerning() - 1, copyright_font_->getDefaultKerning(),
ui_config.titleCopyrightColor()); ui_config.titleCopyrightColor());
} }
+3 -2
View File
@@ -34,7 +34,7 @@ class TitleScene : public Scene {
STARTING, STARTING,
ATTRACT_OUT }; ATTRACT_OUT };
TitleScene(std::shared_ptr<Text> display_font, std::shared_ptr<Text> condensed_font, std::shared_ptr<Surface> background, std::shared_ptr<Surface> mini_logo); TitleScene(std::shared_ptr<Text> condensed_font, std::shared_ptr<Text> copyright_font, std::shared_ptr<Surface> background, std::shared_ptr<Surface> game_logo, std::shared_ptr<Surface> mini_logo);
~TitleScene() override; ~TitleScene() override;
void update(int delta_ms) override; void update(int delta_ms) override;
@@ -49,9 +49,10 @@ class TitleScene : public Scene {
void advanceToIntro(DebugConfig::StartingPlayers players); void advanceToIntro(DebugConfig::StartingPlayers players);
void advanceToLogo(); void advanceToLogo();
std::shared_ptr<Text> display_font_;
std::shared_ptr<Text> condensed_font_; std::shared_ptr<Text> condensed_font_;
std::shared_ptr<Text> copyright_font_;
std::shared_ptr<Surface> background_; std::shared_ptr<Surface> background_;
std::shared_ptr<Surface> game_logo_;
std::shared_ptr<Surface> mini_logo_; std::shared_ptr<Surface> mini_logo_;
int timer_ms_; int timer_ms_;
int blink_elapsed_ms_{0}; int blink_elapsed_ms_{0};
+10
View File
@@ -156,6 +156,16 @@ namespace Defaults {
constexpr const char* MENU_ITEMS_GIF = "data/fonts/ari-w9500-condensed-display.gif"; constexpr const char* MENU_ITEMS_GIF = "data/fonts/ari-w9500-condensed-display.gif";
constexpr const char* MENU_ITEMS_FNT = "data/fonts/ari-w9500-condensed-display.fnt"; constexpr const char* MENU_ITEMS_FNT = "data/fonts/ari-w9500-condensed-display.fnt";
constexpr int MENU_ITEMS_KERNING = 0; 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";
constexpr int COPYRIGHT_KERNING = 0;
} // namespace Font } // namespace Font
// Overlay de RenderInfo (F12). // Overlay de RenderInfo (F12).