diff --git a/data/title/title_bg.gif b/data/title/title_bg.gif new file mode 100644 index 0000000..42c0d74 Binary files /dev/null and b/data/title/title_bg.gif differ diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index c6dd874..c13afad 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -211,6 +211,12 @@ Director::Director() { constexpr const char* MINI_LOGO_KEY = "logo_jailgames_mini.gif"; Resource::Cache::get().loadSurface(MINI_LOGO_KEY, "data/logo/logo_jailgames_mini.gif"); auto mini_logo_surface = Resource::Cache::get().getSurface(MINI_LOGO_KEY); + + // Fons sencer de la TITLE (320×240). Igual que el minilogo, conserva + // la seua paleta nadiua perquè el GIF ja porta els colors finals. + constexpr const char* TITLE_BG_KEY = "title_bg.gif"; + Resource::Cache::get().loadSurface(TITLE_BG_KEY, "data/title/title_bg.gif"); + auto title_bg_surface = Resource::Cache::get().getSurface(TITLE_BG_KEY); ServiceMenu::get().init(menu_title_text, menu_items_text, ui_palette); // Overlay hook: Screen::present() cridarà aquesta lambda al principi, @@ -259,8 +265,8 @@ Director::Director() { auto make_intro = [placeholder_text, make_game]() -> std::unique_ptr { return std::make_unique(placeholder_text, make_game); }; - auto make_title = [menu_title_text, placeholder_text, mini_logo_surface, make_intro]() -> std::unique_ptr { - return std::make_unique(menu_title_text, placeholder_text, mini_logo_surface, make_intro); + auto make_title = [menu_title_text, placeholder_text, title_bg_surface, mini_logo_surface, make_intro]() -> std::unique_ptr { + return std::make_unique(menu_title_text, placeholder_text, title_bg_surface, mini_logo_surface, make_intro); }; switch (START) { diff --git a/source/game/scenes/title_scene.cpp b/source/game/scenes/title_scene.cpp index 2b6390d..012545b 100644 --- a/source/game/scenes/title_scene.cpp +++ b/source/game/scenes/title_scene.cpp @@ -48,9 +48,10 @@ namespace { } // namespace -TitleScene::TitleScene(std::shared_ptr display_font, std::shared_ptr condensed_font, std::shared_ptr mini_logo, SceneFactory next_factory) +TitleScene::TitleScene(std::shared_ptr display_font, std::shared_ptr condensed_font, std::shared_ptr background, std::shared_ptr mini_logo, SceneFactory next_factory) : display_font_(std::move(display_font)), condensed_font_(std::move(condensed_font)), + background_(std::move(background)), mini_logo_(std::move(mini_logo)), next_factory_(std::move(next_factory)), timer_ms_(UiConfig::get().titleDurationMs()) { @@ -85,24 +86,38 @@ void TitleScene::render() { const auto& ui_config = UiConfig::get(); const auto& palette = Resource::Cache::get().getPalette("ui"); - Screen::get().fillRect(0, 0, GameCanvas::WIDTH, GameCanvas::HEIGHT, palette[ui_config.titleBgColor()]); + // Fons: la imatge si està disponible (cobreix tot el canvas amb la + // seua paleta nadiua); en cas contrari, color pla de la paleta UI + // com a fallback defensiu. + if (background_) { + background_->render(0, 0); + } else { + Screen::get().fillRect(0, 0, GameCanvas::WIDTH, GameCanvas::HEIGHT, palette[ui_config.titleBgColor()]); + } const Uint8 TEXT_COLOR = ui_config.titleTextColor(); + const Uint8 OUTLINE_COLOR = ui_config.titleCopyrightColor(); + constexpr Uint8 OUTLINE_DIST = 1; + constexpr Uint8 STROKE4 = Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG; if (display_font_) { const int TITLE_Y = (GameCanvas::HEIGHT * TITLE_Y_PERCENT) / 100; - display_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, + display_font_->writeDX(STROKE4, GameCanvas::CENTER_X, TITLE_Y, TITLE_LINE_1, display_font_->getDefaultKerning(), - TEXT_COLOR); - display_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, + TEXT_COLOR, + OUTLINE_DIST, + OUTLINE_COLOR); + display_font_->writeDX(STROKE4, GameCanvas::CENTER_X, TITLE_Y + titleLineGap(*display_font_), TITLE_LINE_2, display_font_->getDefaultKerning(), - TEXT_COLOR); + TEXT_COLOR, + OUTLINE_DIST, + OUTLINE_COLOR); } if (condensed_font_) { @@ -115,12 +130,14 @@ void TitleScene::render() { if (VISIBLE) { const int PROMPT_Y = (GameCanvas::HEIGHT * PROMPT_Y_PERCENT) / 100; - condensed_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, + condensed_font_->writeDX(STROKE4, GameCanvas::CENTER_X, PROMPT_Y, Locale::get().text("title.press_start"), condensed_font_->getDefaultKerning() - 1, - TEXT_COLOR); + TEXT_COLOR, + OUTLINE_DIST, + OUTLINE_COLOR); } } diff --git a/source/game/scenes/title_scene.hpp b/source/game/scenes/title_scene.hpp index d4d6a7b..4040a84 100644 --- a/source/game/scenes/title_scene.hpp +++ b/source/game/scenes/title_scene.hpp @@ -16,7 +16,7 @@ class TitleScene : public Scene { public: using SceneFactory = std::function()>; - TitleScene(std::shared_ptr display_font, std::shared_ptr condensed_font, std::shared_ptr mini_logo, SceneFactory next_factory); + TitleScene(std::shared_ptr display_font, std::shared_ptr condensed_font, std::shared_ptr background, std::shared_ptr mini_logo, SceneFactory next_factory); ~TitleScene() override; void update(int delta_ms) override; @@ -25,6 +25,7 @@ class TitleScene : public Scene { private: std::shared_ptr display_font_; std::shared_ptr condensed_font_; + std::shared_ptr background_; std::shared_ptr mini_logo_; SceneFactory next_factory_; int timer_ms_;