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:
1 parent
8da18a6a86
commit
7982df922b
6 files changed
+40
-20
No files matched your search
+6
-5
@@ -37,14 +37,15 @@ hud:
|
|||||||
room: "Sala"
|
room: "Sala"
|
||||||
|
|
||||||
# Textos de la transició d'entrada/sortida de sala (FSM de GameScene).
|
# Textos de la transició d'entrada/sortida de sala (FSM de GameScene).
|
||||||
# Les dues primeres claus es renderitzen com a línies separades durant
|
# Tant l'INTRO com l'OUTRO es renderitzen com a dues línies separades
|
||||||
# l'INTRO (preparades per ser animades de manera independent en el
|
# (cadascuna amb la seua animació). L'INTRO accepta els placeholders
|
||||||
# futur). Accepten els placeholders `{p}` (piràmide) i `{r}` (sala) que
|
# `{p}` (piràmide) i `{r}` (sala); l'OUTRO no en té cap — són les
|
||||||
# es substitueixen amb els valors actuals del LevelManager.
|
# dues paraules del rètol "fase completada".
|
||||||
game:
|
game:
|
||||||
room_intro_pyramid: "Piramide {p}"
|
room_intro_pyramid: "Piramide {p}"
|
||||||
room_intro_room: "Sala {r}"
|
room_intro_room: "Sala {r}"
|
||||||
room_complete: "Fase completada"
|
room_complete_line1: "Fase"
|
||||||
|
room_complete_line2: "Completada"
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
titles:
|
titles:
|
||||||
|
|||||||
+6
-6
@@ -36,15 +36,15 @@ hud:
|
|||||||
pyramid: "Pyramid"
|
pyramid: "Pyramid"
|
||||||
room: "Room"
|
room: "Room"
|
||||||
|
|
||||||
# Room transition texts (GameScene FSM intro/outro). The two pyramid /
|
# Room transition texts (GameScene FSM intro/outro). Both INTRO and
|
||||||
# room strings render as independent lines during INTRO (so they can
|
# OUTRO render as two independent lines with their own animation.
|
||||||
# be animated separately in the future). They accept `{p}` (pyramid)
|
# INTRO uses `{p}` (pyramid) and `{r}` (room) placeholders; OUTRO has
|
||||||
# and `{r}` (room) placeholders, replaced with the current LevelManager
|
# no placeholders — it's the two words of the "stage complete" label.
|
||||||
# values.
|
|
||||||
game:
|
game:
|
||||||
room_intro_pyramid: "Pyramid {p}"
|
room_intro_pyramid: "Pyramid {p}"
|
||||||
room_intro_room: "Room {r}"
|
room_intro_room: "Room {r}"
|
||||||
room_complete: "Stage complete"
|
room_complete_line1: "Stage"
|
||||||
|
room_complete_line2: "Complete"
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
titles:
|
titles:
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ room_intro:
|
|||||||
text_enter_ms: 400 # text esquerra → centre
|
text_enter_ms: 400 # text esquerra → centre
|
||||||
text_hold_ms: 1500 # text quiet al centre
|
text_hold_ms: 1500 # text quiet al centre
|
||||||
text_exit_ms: 400 # text centre → fora per l'esquerra
|
text_exit_ms: 400 # text centre → fora per l'esquerra
|
||||||
line_gap_px: 8 # px extra entre les dues línies (piràmide / sala)
|
line_gap_px: 0 # px extra entre les dues línies (piràmide / sala)
|
||||||
|
|
||||||
room_outro:
|
room_outro:
|
||||||
text_enter_ms: 500
|
text_enter_ms: 400
|
||||||
text_hold_ms: 1000
|
text_hold_ms: 1500
|
||||||
text_exit_ms: 500
|
text_exit_ms: 400
|
||||||
fade_out_ms: 500 # món visible → negre opac
|
fade_out_ms: 500 # món visible → negre opac
|
||||||
|
line_gap_px: 0 # px extra entre les dues línies (fase / completada)
|
||||||
|
|
||||||
text:
|
text:
|
||||||
# Noms d'easing tal com els resol UiConfig::curveByName (vegeu
|
# Noms d'easing tal com els resol UiConfig::curveByName (vegeu
|
||||||
|
|||||||
@@ -721,11 +721,23 @@ void GameScene::renderRoomText() {
|
|||||||
draw_line(LINE_PYRAMID, X_PYRAMID, Y_PYRAMID);
|
draw_line(LINE_PYRAMID, X_PYRAMID, Y_PYRAMID);
|
||||||
draw_line(LINE_ROOM, X_ROOM, Y_ROOM);
|
draw_line(LINE_ROOM, X_ROOM, Y_ROOM);
|
||||||
} else if (state_ == RoomFsm::State::ROOM_OUTRO && transition_.phase >= 0 && transition_.phase <= 2) {
|
} else if (state_ == RoomFsm::State::ROOM_OUTRO && transition_.phase >= 0 && transition_.phase <= 2) {
|
||||||
const std::string TEXT = Locale::get().text("game.room_complete");
|
// Mateix patró que l'INTRO: dues línies en direccions oposades.
|
||||||
const int W = room_text_font_->length(TEXT, KERNING);
|
// Línia 1 ("Fase") per l'esquerra, línia 2 ("Completada") per
|
||||||
const int X = compute_x(W, 0, 2, transition_config_.outro_text_enter_ms, transition_config_.outro_text_exit_ms, /*from_right=*/false);
|
// la dreta; surten cap al costat oposat del que han entrat.
|
||||||
const int Y = GameCanvas::CENTER_Y - (room_text_font_->getLineHeight() / 2);
|
const std::string LINE_1 = Locale::get().text("game.room_complete_line1");
|
||||||
draw_line(TEXT, X, Y);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ namespace RoomFsm {
|
|||||||
cfg.outro_text_hold_ms = readChildInt(n, "text_hold_ms", cfg.outro_text_hold_ms);
|
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_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_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")) {
|
if (yaml.contains("text")) {
|
||||||
const auto& n = yaml["text"];
|
const auto& n = yaml["text"];
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ namespace RoomFsm {
|
|||||||
// sense recompilar.
|
// sense recompilar.
|
||||||
int intro_text_line_gap_px{8};
|
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_enter_curve{nullptr};
|
||||||
UiConfig::CurveFn text_exit_curve{nullptr};
|
UiConfig::CurveFn text_exit_curve{nullptr};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user