feat(outro): rètol "fase completada" en dues línies oposades

Mateixa tècnica que l'INTRO: la línia 1 ("Fase") entra per
l'esquerra, la línia 2 ("Completada") per la dreta, i surten cap
al costat oposat al d'entrada. Centrades verticalment al voltant
del CENTER_Y amb el gap configurable ( a
data/scenes/game.yaml; 0 per defecte, paral·lel a la del room_intro).

Locale: la clau game.room_complete es divideix en
game.room_complete_line1 / room_complete_line2 als ca.yaml i en.yaml
("Fase"/"Completada" i "Stage"/"Complete"). Cada línia es
tradueix per separat — útil si demà voleu paraules de longitud o
ordre distint en altres idiomes.
This commit is contained in:
JailDesigner committed 2026-04-26 17:28:07 +02:00
1 parent 8da18a6a86
commit 7982df922b
6 files changed
+40 -20

No files matched your search

+17 -5
View File
@@ -721,11 +721,23 @@ void GameScene::renderRoomText() {
draw_line(LINE_PYRAMID, X_PYRAMID, Y_PYRAMID);
draw_line(LINE_ROOM, X_ROOM, Y_ROOM);
} else if (state_ == RoomFsm::State::ROOM_OUTRO && transition_.phase >= 0 && transition_.phase <= 2) {
const std::string TEXT = Locale::get().text("game.room_complete");
const int W = room_text_font_->length(TEXT, KERNING);
const int X = compute_x(W, 0, 2, transition_config_.outro_text_enter_ms, transition_config_.outro_text_exit_ms, /*from_right=*/false);
const int Y = GameCanvas::CENTER_Y - (room_text_font_->getLineHeight() / 2);
draw_line(TEXT, X, Y);
// Mateix patró que l'INTRO: dues línies en direccions oposades.
// Línia 1 ("Fase") per l'esquerra, línia 2 ("Completada") per
// la dreta; surten cap al costat oposat del que han entrat.
const std::string LINE_1 = Locale::get().text("game.room_complete_line1");
const std::string LINE_2 = Locale::get().text("game.room_complete_line2");
const int W_1 = room_text_font_->length(LINE_1, KERNING);
const int W_2 = room_text_font_->length(LINE_2, KERNING);
const int DUR_ENTER = transition_config_.outro_text_enter_ms;
const int DUR_EXIT = transition_config_.outro_text_exit_ms;
const int X_1 = compute_x(W_1, 0, 2, DUR_ENTER, DUR_EXIT, /*from_right=*/false);
const int X_2 = compute_x(W_2, 0, 2, DUR_ENTER, DUR_EXIT, /*from_right=*/true);
const int LINE_HEIGHT = room_text_font_->getLineHeight();
const int GAP = transition_config_.outro_text_line_gap_px;
const int Y_1 = GameCanvas::CENTER_Y - LINE_HEIGHT - (GAP / 2);
const int Y_2 = GameCanvas::CENTER_Y + (GAP / 2);
draw_line(LINE_1, X_1, Y_1);
draw_line(LINE_2, X_2, Y_2);
}
}
+1
View File
@@ -51,6 +51,7 @@ namespace RoomFsm {
cfg.outro_text_hold_ms = readChildInt(n, "text_hold_ms", cfg.outro_text_hold_ms);
cfg.outro_text_exit_ms = readChildInt(n, "text_exit_ms", cfg.outro_text_exit_ms);
cfg.outro_fade_out_ms = readChildInt(n, "fade_out_ms", cfg.outro_fade_out_ms);
cfg.outro_text_line_gap_px = readChildInt(n, "line_gap_px", cfg.outro_text_line_gap_px);
}
if (yaml.contains("text")) {
const auto& n = yaml["text"];
+5
View File
@@ -56,6 +56,11 @@ namespace RoomFsm {
// sense recompilar.
int intro_text_line_gap_px{8};
// Equivalent per a l'OUTRO ("fase" damunt, "completada" davall).
// Es manté independent del de l'INTRO per si el ritme visual
// demana un espaiat distint en cada banda de la transició.
int outro_text_line_gap_px{8};
UiConfig::CurveFn text_enter_curve{nullptr};
UiConfig::CurveFn text_exit_curve{nullptr};
};