feat(title): parpadeig STARTING amb cicle 50/50 i període configurable
This commit is contained in:
1 parent
0618452224
commit
36fc496226
5 files changed
+37
-21
No files matched your search
+4
-1
@@ -119,7 +119,10 @@ title:
|
|||||||
# de freqüència). Si l'altre jugador prem START dins d'aquesta
|
# de freqüència). Si l'altre jugador prem START dins d'aquesta
|
||||||
# finestra, el comptador es reseteja i s'arrenca amb BOTH.
|
# finestra, el comptador es reseteja i s'arrenca amb BOTH.
|
||||||
starting_ms: 3000
|
starting_ms: 3000
|
||||||
starting_blink_speedup: 2.0
|
# Durant STARTING el prompt commuta a un cicle simètric 50/50
|
||||||
|
# (visible/ocult) amb aquest període total. 200 ms = 5 Hz, prou
|
||||||
|
# ràpid per llegir-se com a "pulsació confirmada".
|
||||||
|
starting_blink_period_ms: 200
|
||||||
# Fade-out estil "mosaic dissolve" durant l'última part de STARTING.
|
# Fade-out estil "mosaic dissolve" durant l'última part de STARTING.
|
||||||
# `fade_out_ms` ha de ser <= starting_ms (els últims X ms del STARTING
|
# `fade_out_ms` ha de ser <= starting_ms (els últims X ms del STARTING
|
||||||
# es fan amb el dissolve actiu fins a quedar negre). `fade_out_max_block`
|
# es fan amb el dissolve actiu fins a quedar negre). `fade_out_max_block`
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ UiConfig::UiConfig()
|
|||||||
title_blink_visible_ms_(Defaults::UI::Title::BLINK_VISIBLE_MS),
|
title_blink_visible_ms_(Defaults::UI::Title::BLINK_VISIBLE_MS),
|
||||||
title_blink_hidden_ms_(Defaults::UI::Title::BLINK_HIDDEN_MS),
|
title_blink_hidden_ms_(Defaults::UI::Title::BLINK_HIDDEN_MS),
|
||||||
title_starting_ms_(Defaults::UI::Title::STARTING_MS),
|
title_starting_ms_(Defaults::UI::Title::STARTING_MS),
|
||||||
title_starting_blink_speedup_(Defaults::UI::Title::STARTING_BLINK_SPEEDUP),
|
title_starting_blink_period_ms_(Defaults::UI::Title::STARTING_BLINK_PERIOD_MS),
|
||||||
title_fade_out_ms_(Defaults::UI::Title::FADE_OUT_MS),
|
title_fade_out_ms_(Defaults::UI::Title::FADE_OUT_MS),
|
||||||
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_heat_haze_{
|
title_heat_haze_{
|
||||||
@@ -229,7 +229,7 @@ void UiConfig::load(const std::string& file_path) {
|
|||||||
readField(t, "blink_visible_ms", title_blink_visible_ms_);
|
readField(t, "blink_visible_ms", title_blink_visible_ms_);
|
||||||
readField(t, "blink_hidden_ms", title_blink_hidden_ms_);
|
readField(t, "blink_hidden_ms", title_blink_hidden_ms_);
|
||||||
readField(t, "starting_ms", title_starting_ms_);
|
readField(t, "starting_ms", title_starting_ms_);
|
||||||
readField(t, "starting_blink_speedup", title_starting_blink_speedup_);
|
readField(t, "starting_blink_period_ms", title_starting_blink_period_ms_);
|
||||||
readField(t, "fade_out_ms", title_fade_out_ms_);
|
readField(t, "fade_out_ms", title_fade_out_ms_);
|
||||||
readField(t, "fade_out_max_block", title_fade_out_max_block_);
|
readField(t, "fade_out_max_block", title_fade_out_max_block_);
|
||||||
if (t.contains("heat_haze")) {
|
if (t.contains("heat_haze")) {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class UiConfig {
|
|||||||
[[nodiscard]] auto titleBlinkVisibleMs() const -> int { return title_blink_visible_ms_; }
|
[[nodiscard]] auto titleBlinkVisibleMs() const -> int { return title_blink_visible_ms_; }
|
||||||
[[nodiscard]] auto titleBlinkHiddenMs() const -> int { return title_blink_hidden_ms_; }
|
[[nodiscard]] auto titleBlinkHiddenMs() const -> int { return title_blink_hidden_ms_; }
|
||||||
[[nodiscard]] auto titleStartingMs() const -> int { return title_starting_ms_; }
|
[[nodiscard]] auto titleStartingMs() const -> int { return title_starting_ms_; }
|
||||||
[[nodiscard]] auto titleStartingBlinkSpeedup() const -> float { return title_starting_blink_speedup_; }
|
[[nodiscard]] auto titleStartingBlinkPeriodMs() const -> int { return title_starting_blink_period_ms_; }
|
||||||
[[nodiscard]] auto titleFadeOutMs() const -> int { return title_fade_out_ms_; }
|
[[nodiscard]] auto titleFadeOutMs() const -> int { return title_fade_out_ms_; }
|
||||||
[[nodiscard]] auto titleFadeOutMaxBlock() const -> int { return title_fade_out_max_block_; }
|
[[nodiscard]] auto titleFadeOutMaxBlock() const -> int { return title_fade_out_max_block_; }
|
||||||
[[nodiscard]] auto titleHeatHaze() const -> const TitleHeatHaze& { return title_heat_haze_; }
|
[[nodiscard]] auto titleHeatHaze() const -> const TitleHeatHaze& { return title_heat_haze_; }
|
||||||
@@ -172,7 +172,7 @@ class UiConfig {
|
|||||||
int title_blink_visible_ms_;
|
int title_blink_visible_ms_;
|
||||||
int title_blink_hidden_ms_;
|
int title_blink_hidden_ms_;
|
||||||
int title_starting_ms_;
|
int title_starting_ms_;
|
||||||
float title_starting_blink_speedup_;
|
int title_starting_blink_period_ms_;
|
||||||
int title_fade_out_ms_;
|
int title_fade_out_ms_;
|
||||||
int title_fade_out_max_block_;
|
int title_fade_out_max_block_;
|
||||||
TitleHeatHaze title_heat_haze_;
|
TitleHeatHaze title_heat_haze_;
|
||||||
|
|||||||
@@ -103,13 +103,12 @@ void TitleScene::update(int delta_ms) {
|
|||||||
|
|
||||||
if (heat_haze_) { heat_haze_->tick(delta_ms); }
|
if (heat_haze_) { heat_haze_->tick(delta_ms); }
|
||||||
|
|
||||||
// Avanç del comptador del parpadeig: durant STARTING, accelera per
|
// Comptador del parpadeig: avança sempre amb `delta_ms` cru. La
|
||||||
// `starting_blink_speedup` (típicament 2.0). Es manté en enter perquè
|
// lectura (cicle/visible) la decideix `render()` segons la fase:
|
||||||
// tota la lògica del cicle (visible_ms / hidden_ms) treballa amb int.
|
// IDLE usa visible_ms / hidden_ms del yaml (asimètric, 80/20 per
|
||||||
const float BLINK_RATE = (phase_ == Phase::STARTING)
|
// defecte); STARTING usa un cicle simètric 50/50 amb període
|
||||||
? UiConfig::get().titleStartingBlinkSpeedup()
|
// `starting_blink_period_ms`.
|
||||||
: 1.0F;
|
blink_elapsed_ms_ += delta_ms;
|
||||||
blink_elapsed_ms_ += static_cast<int>(static_cast<float>(delta_ms) * BLINK_RATE);
|
|
||||||
|
|
||||||
const bool P1_START = pressedStart(0);
|
const bool P1_START = pressedStart(0);
|
||||||
const bool P2_START = pressedStart(1);
|
const bool P2_START = pressedStart(1);
|
||||||
@@ -169,6 +168,10 @@ void TitleScene::enterStarting(DebugConfig::StartingPlayers players) {
|
|||||||
phase_ = Phase::STARTING;
|
phase_ = Phase::STARTING;
|
||||||
pending_players_ = players;
|
pending_players_ = players;
|
||||||
starting_timer_ms_ = UiConfig::get().titleStartingMs();
|
starting_timer_ms_ = UiConfig::get().titleStartingMs();
|
||||||
|
// Resetem el comptador del parpadeig perquè el primer frame de
|
||||||
|
// STARTING comenci visible — sense això, el modulus amb el nou
|
||||||
|
// període podria caure mig cicle i donar un primer "off" estrany.
|
||||||
|
blink_elapsed_ms_ = 0;
|
||||||
std::cout << "[scene] " << SCENE_NAME << " STARTING (players=" << DebugConfig::toString(players) << ")\n";
|
std::cout << "[scene] " << SCENE_NAME << " STARTING (players=" << DebugConfig::toString(players) << ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,12 +224,20 @@ void TitleScene::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (condensed_font_) {
|
if (condensed_font_) {
|
||||||
// Cicle de parpadeig: visible_ms ON + hidden_ms OFF, repetint-se.
|
// Cicle de parpadeig: a IDLE pren visible_ms+hidden_ms del yaml
|
||||||
// Si la suma val 0 (configuració degenerada), cau a "sempre visible".
|
// (asimètric, 80/20 per defecte); a STARTING commuta a 50/50 amb
|
||||||
const int VISIBLE_MS = std::max(0, ui_config.titleBlinkVisibleMs());
|
// `starting_blink_period_ms` per donar feedback de "polsat".
|
||||||
const int HIDDEN_MS = std::max(0, ui_config.titleBlinkHiddenMs());
|
// Si el cicle val 0 (configuració degenerada), cau a "sempre visible".
|
||||||
const int CYCLE_MS = VISIBLE_MS + HIDDEN_MS;
|
int cycle_ms = 0;
|
||||||
const bool VISIBLE = (CYCLE_MS == 0) || ((blink_elapsed_ms_ % CYCLE_MS) < VISIBLE_MS);
|
int visible_ms = 0;
|
||||||
|
if (phase_ == Phase::STARTING) {
|
||||||
|
cycle_ms = std::max(0, ui_config.titleStartingBlinkPeriodMs());
|
||||||
|
visible_ms = cycle_ms / 2;
|
||||||
|
} else {
|
||||||
|
visible_ms = std::max(0, ui_config.titleBlinkVisibleMs());
|
||||||
|
cycle_ms = visible_ms + std::max(0, ui_config.titleBlinkHiddenMs());
|
||||||
|
}
|
||||||
|
const bool VISIBLE = (cycle_ms == 0) || ((blink_elapsed_ms_ % cycle_ms) < visible_ms);
|
||||||
|
|
||||||
if (VISIBLE) {
|
if (VISIBLE) {
|
||||||
const int PROMPT_Y = (GameCanvas::HEIGHT * PROMPT_Y_PERCENT) / 100;
|
const int PROMPT_Y = (GameCanvas::HEIGHT * PROMPT_Y_PERCENT) / 100;
|
||||||
|
|||||||
@@ -261,10 +261,12 @@ namespace Defaults {
|
|||||||
|
|
||||||
// Fase STARTING: durada fixa entre la primera pulsació de
|
// Fase STARTING: durada fixa entre la primera pulsació de
|
||||||
// START i la transició a la següent escena. Durant aquesta
|
// START i la transició a la següent escena. Durant aquesta
|
||||||
// fase, el parpadeig del prompt va a `BLINK_SPEEDUP` × la
|
// fase, el parpadeig del prompt commuta a un cicle simètric
|
||||||
// freqüència normal (2.0 = doble; 1.5 = un 50% més ràpid).
|
// 50/50 (visible/ocult) amb període `STARTING_BLINK_PERIOD_MS`,
|
||||||
|
// pensat per a un ritme molt més ràpid que l'animació
|
||||||
|
// atràctil del IDLE (200 ms = 5 Hz).
|
||||||
constexpr int STARTING_MS = 3000;
|
constexpr int STARTING_MS = 3000;
|
||||||
constexpr float STARTING_BLINK_SPEEDUP = 2.0F;
|
constexpr int STARTING_BLINK_PERIOD_MS = 200;
|
||||||
|
|
||||||
// Fade-out estil mosaic dissolve dins l'última part de la
|
// Fade-out estil mosaic dissolve dins l'última part de la
|
||||||
// fase STARTING. `FADE_OUT_MS` ha de ser <= STARTING_MS;
|
// fase STARTING. `FADE_OUT_MS` ha de ser <= STARTING_MS;
|
||||||
|
|||||||
Reference in new issue
Block a user