feat(title): fade-in inicial de negre a escena (500 ms, configurable a ui.yaml)
This commit is contained in:
1 parent
29cb4c2211
commit
1431f27cfa
6 files changed
+36
No files matched your search
@@ -139,6 +139,10 @@ title:
|
|||||||
# mosaic — capa negra lineal damunt del canvas. La música no es toca:
|
# mosaic — capa negra lineal damunt del canvas. La música no es toca:
|
||||||
# `title.ogg` continua sonant cap a LOGO, que ja veurà què en fa.
|
# `title.ogg` continua sonant cap a LOGO, que ja veurà què en fa.
|
||||||
attract_fade_to_black_ms: 800
|
attract_fade_to_black_ms: 800
|
||||||
|
# Fade-in inicial: capa negra al començament que s'esvaeix cap al fons.
|
||||||
|
# Mateix valor que `room_intro.fade_in_ms` (data/scenes/game.yaml) perquè
|
||||||
|
# l'arribada a la TITLE i a una sala de joc tinguin el mateix ritme.
|
||||||
|
intro_fade_in_ms: 500
|
||||||
# Distorsió sinusoidal del fons (efecte de calor del desert).
|
# Distorsió sinusoidal del fons (efecte de calor del desert).
|
||||||
# `amplitude_px`: desplaçament màxim de cada fila en píxels.
|
# `amplitude_px`: desplaçament màxim de cada fila en píxels.
|
||||||
# `wavelength_px`: distància vertical entre dos pics de l'ona.
|
# `wavelength_px`: distància vertical entre dos pics de l'ona.
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ UiConfig::UiConfig()
|
|||||||
title_fade_out_max_block_(Defaults::UI::Title::FADE_OUT_MAX_BLOCK),
|
title_fade_out_max_block_(Defaults::UI::Title::FADE_OUT_MAX_BLOCK),
|
||||||
title_music_fade_out_ms_(Defaults::UI::Title::MUSIC_FADE_OUT_MS),
|
title_music_fade_out_ms_(Defaults::UI::Title::MUSIC_FADE_OUT_MS),
|
||||||
title_attract_fade_to_black_ms_(Defaults::UI::Title::ATTRACT_FADE_TO_BLACK_MS),
|
title_attract_fade_to_black_ms_(Defaults::UI::Title::ATTRACT_FADE_TO_BLACK_MS),
|
||||||
|
title_intro_fade_in_ms_(Defaults::UI::Title::INTRO_FADE_IN_MS),
|
||||||
title_heat_haze_{
|
title_heat_haze_{
|
||||||
.enabled = Defaults::UI::Title::HeatHaze::ENABLED,
|
.enabled = Defaults::UI::Title::HeatHaze::ENABLED,
|
||||||
.amplitude_px = Defaults::UI::Title::HeatHaze::AMPLITUDE_PX,
|
.amplitude_px = Defaults::UI::Title::HeatHaze::AMPLITUDE_PX,
|
||||||
@@ -238,6 +239,7 @@ void UiConfig::load(const std::string& file_path) {
|
|||||||
readField(t, "fade_out_max_block", title_fade_out_max_block_);
|
readField(t, "fade_out_max_block", title_fade_out_max_block_);
|
||||||
readField(t, "music_fade_out_ms", title_music_fade_out_ms_);
|
readField(t, "music_fade_out_ms", title_music_fade_out_ms_);
|
||||||
readField(t, "attract_fade_to_black_ms", title_attract_fade_to_black_ms_);
|
readField(t, "attract_fade_to_black_ms", title_attract_fade_to_black_ms_);
|
||||||
|
readField(t, "intro_fade_in_ms", title_intro_fade_in_ms_);
|
||||||
if (t.contains("heat_haze")) {
|
if (t.contains("heat_haze")) {
|
||||||
const auto& hh = t["heat_haze"];
|
const auto& hh = t["heat_haze"];
|
||||||
readField(hh, "enabled", title_heat_haze_.enabled);
|
readField(hh, "enabled", title_heat_haze_.enabled);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class UiConfig {
|
|||||||
[[nodiscard]] auto titleFadeOutMaxBlock() const -> int { return title_fade_out_max_block_; }
|
[[nodiscard]] auto titleFadeOutMaxBlock() const -> int { return title_fade_out_max_block_; }
|
||||||
[[nodiscard]] auto titleMusicFadeOutMs() const -> int { return title_music_fade_out_ms_; }
|
[[nodiscard]] auto titleMusicFadeOutMs() const -> int { return title_music_fade_out_ms_; }
|
||||||
[[nodiscard]] auto titleAttractFadeToBlackMs() const -> int { return title_attract_fade_to_black_ms_; }
|
[[nodiscard]] auto titleAttractFadeToBlackMs() const -> int { return title_attract_fade_to_black_ms_; }
|
||||||
|
[[nodiscard]] auto titleIntroFadeInMs() const -> int { return title_intro_fade_in_ms_; }
|
||||||
[[nodiscard]] auto titleHeatHaze() const -> const TitleHeatHaze& { return title_heat_haze_; }
|
[[nodiscard]] auto titleHeatHaze() const -> const TitleHeatHaze& { return title_heat_haze_; }
|
||||||
|
|
||||||
// Corbes d'easing triades al YAML. Si el nom no és conegut, s'usa
|
// Corbes d'easing triades al YAML. Si el nom no és conegut, s'usa
|
||||||
@@ -180,6 +181,7 @@ class UiConfig {
|
|||||||
int title_fade_out_max_block_;
|
int title_fade_out_max_block_;
|
||||||
int title_music_fade_out_ms_;
|
int title_music_fade_out_ms_;
|
||||||
int title_attract_fade_to_black_ms_;
|
int title_attract_fade_to_black_ms_;
|
||||||
|
int title_intro_fade_in_ms_;
|
||||||
TitleHeatHaze title_heat_haze_;
|
TitleHeatHaze title_heat_haze_;
|
||||||
|
|
||||||
std::string menu_select_sound_;
|
std::string menu_select_sound_;
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ TitleScene::TitleScene(std::shared_ptr<Text> display_font, std::shared_ptr<Text>
|
|||||||
.max_block_size = UiConfig::get().titleFadeOutMaxBlock(),
|
.max_block_size = UiConfig::get().titleFadeOutMaxBlock(),
|
||||||
});
|
});
|
||||||
attract_fade_.emplace();
|
attract_fade_.emplace();
|
||||||
|
// Fade-in inicial: arrenquem en negre opac i ens esvaïm cap a la
|
||||||
|
// imatge de fons. Sense lligar a cap fase — viu sempre al frame i
|
||||||
|
// un cop finished, `render()` és no-op fins que la TitleScene mor.
|
||||||
|
intro_fade_.begin(UiConfig::get().titleIntroFadeInMs(), Transitions::FadeToBlack::Direction::FADE_IN);
|
||||||
|
|
||||||
// Música de fons en bucle. Es preloda al Director, així que la
|
// Música de fons en bucle. Es preloda al Director, així que la
|
||||||
// primera crida és immediata. El fade-out arrenca en entrar a
|
// primera crida és immediata. El fade-out arrenca en entrar a
|
||||||
@@ -122,6 +126,11 @@ void TitleScene::update(int delta_ms) {
|
|||||||
|
|
||||||
if (heat_haze_) { heat_haze_->tick(delta_ms); }
|
if (heat_haze_) { heat_haze_->tick(delta_ms); }
|
||||||
|
|
||||||
|
// Fade-in inicial: tica sempre. Un cop finished, FadeToBlack::tick
|
||||||
|
// és idempotent (clamp intern al duration_ms_) i `render()` pinta
|
||||||
|
// alpha=0 (no-op) durant la resta del cicle.
|
||||||
|
intro_fade_.tick(delta_ms);
|
||||||
|
|
||||||
// Comptador del parpadeig: avança sempre amb `delta_ms` cru. La
|
// Comptador del parpadeig: avança sempre amb `delta_ms` cru. La
|
||||||
// lectura (cicle/visible) la decideix `render()` segons la fase:
|
// lectura (cicle/visible) la decideix `render()` segons la fase:
|
||||||
// IDLE usa visible_ms / hidden_ms del yaml (asimètric, 80/20 per
|
// IDLE usa visible_ms / hidden_ms del yaml (asimètric, 80/20 per
|
||||||
@@ -336,6 +345,13 @@ void TitleScene::render() {
|
|||||||
|
|
||||||
Notifier::get().render();
|
Notifier::get().render();
|
||||||
|
|
||||||
|
// Fade-in inicial: capa negra que s'esvaeix cap a l'escena durant
|
||||||
|
// els primers `title.intro_fade_in_ms` ms. `render()` és no-op un
|
||||||
|
// cop finished, així que es queda penjat aquí sense lògica
|
||||||
|
// condicional. Va per damunt del Notifier — coherent amb la resta
|
||||||
|
// de transicions — però per davall del RenderInfo de debug.
|
||||||
|
intro_fade_.render();
|
||||||
|
|
||||||
// Capa de transició final segons la fase. Sempre cobreix l'escena
|
// Capa de transició final segons la fase. Sempre cobreix l'escena
|
||||||
// i el Notifier, mai el RenderInfo (overlay de debug, sempre
|
// i el Notifier, mai el RenderInfo (overlay de debug, sempre
|
||||||
// visible). STARTING usa mosaic dissolve; ATTRACT_OUT, fade-to-black
|
// visible). STARTING usa mosaic dissolve; ATTRACT_OUT, fade-to-black
|
||||||
|
|||||||
@@ -61,4 +61,9 @@ class TitleScene : public Scene {
|
|||||||
DebugConfig::StartingPlayers pending_players_{DebugConfig::StartingPlayers::BOTH};
|
DebugConfig::StartingPlayers pending_players_{DebugConfig::StartingPlayers::BOTH};
|
||||||
std::optional<Transitions::Mosaic> fade_out_;
|
std::optional<Transitions::Mosaic> fade_out_;
|
||||||
std::optional<Transitions::FadeToBlack> attract_fade_;
|
std::optional<Transitions::FadeToBlack> attract_fade_;
|
||||||
|
// Fade-in inicial: capa negra que s'esvaeix cap a la imatge de fons
|
||||||
|
// durant els primers `title.intro_fade_in_ms` ms. Sempre activa al
|
||||||
|
// ctor; un cop finished, `render()` pinta alpha=0 (no-op) la resta
|
||||||
|
// del cicle de l'escena.
|
||||||
|
Transitions::FadeToBlack intro_fade_;
|
||||||
};
|
};
|
||||||
@@ -294,6 +294,13 @@ namespace Defaults {
|
|||||||
// veurà què en fa.
|
// veurà què en fa.
|
||||||
constexpr int ATTRACT_FADE_TO_BLACK_MS = 800;
|
constexpr int ATTRACT_FADE_TO_BLACK_MS = 800;
|
||||||
|
|
||||||
|
// Fade-in inicial de l'escena: capa negra al començament que
|
||||||
|
// s'esvaeix cap a la imatge de fons. Lineal, sense mosaic —
|
||||||
|
// mateixa convenció que el `room_intro.fade_in_ms` del joc
|
||||||
|
// perquè l'arribada a la TITLE i l'arribada a una sala de
|
||||||
|
// joc tinguin el mateix ritme visual.
|
||||||
|
constexpr int INTRO_FADE_IN_MS = 500;
|
||||||
|
|
||||||
// Distorsió sinusoidal horitzontal de l'imatge de fons
|
// Distorsió sinusoidal horitzontal de l'imatge de fons
|
||||||
// (efecte de calor del desert). `amplitude_px` és el
|
// (efecte de calor del desert). `amplitude_px` és el
|
||||||
// desplaçament màxim per fila; `wavelength_px` la distància
|
// desplaçament màxim per fila; `wavelength_px` la distància
|
||||||
|
|||||||
Reference in new issue
Block a user