diff --git a/data/locale/ca.yaml b/data/locale/ca.yaml index 1edf63b..36c9066 100644 --- a/data/locale/ca.yaml +++ b/data/locale/ca.yaml @@ -37,14 +37,15 @@ hud: room: "Sala" # Textos de la transició d'entrada/sortida de sala (FSM de GameScene). -# Les dues primeres claus es renderitzen com a línies separades durant -# l'INTRO (preparades per ser animades de manera independent en el -# futur). Accepten els placeholders `{p}` (piràmide) i `{r}` (sala) que -# es substitueixen amb els valors actuals del LevelManager. +# Tant l'INTRO com l'OUTRO es renderitzen com a dues línies separades +# (cadascuna amb la seua animació). L'INTRO accepta els placeholders +# `{p}` (piràmide) i `{r}` (sala); l'OUTRO no en té cap — són les +# dues paraules del rètol "fase completada". game: room_intro_pyramid: "Piramide {p}" room_intro_room: "Sala {r}" - room_complete: "Fase completada" + room_complete_line1: "Fase" + room_complete_line2: "Completada" menu: titles: diff --git a/data/locale/en.yaml b/data/locale/en.yaml index faae49c..b0e1469 100644 --- a/data/locale/en.yaml +++ b/data/locale/en.yaml @@ -36,15 +36,15 @@ hud: pyramid: "Pyramid" room: "Room" -# Room transition texts (GameScene FSM intro/outro). The two pyramid / -# room strings render as independent lines during INTRO (so they can -# be animated separately in the future). They accept `{p}` (pyramid) -# and `{r}` (room) placeholders, replaced with the current LevelManager -# values. +# Room transition texts (GameScene FSM intro/outro). Both INTRO and +# OUTRO render as two independent lines with their own animation. +# INTRO uses `{p}` (pyramid) and `{r}` (room) placeholders; OUTRO has +# no placeholders — it's the two words of the "stage complete" label. game: room_intro_pyramid: "Pyramid {p}" room_intro_room: "Room {r}" - room_complete: "Stage complete" + room_complete_line1: "Stage" + room_complete_line2: "Complete" menu: titles: diff --git a/data/scenes/game.yaml b/data/scenes/game.yaml index 1a3353e..4242e75 100644 --- a/data/scenes/game.yaml +++ b/data/scenes/game.yaml @@ -10,13 +10,14 @@ room_intro: text_enter_ms: 400 # text esquerra → centre text_hold_ms: 1500 # text quiet al centre 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: - text_enter_ms: 500 - text_hold_ms: 1000 - text_exit_ms: 500 + text_enter_ms: 400 + text_hold_ms: 1500 + text_exit_ms: 400 fade_out_ms: 500 # món visible → negre opac + line_gap_px: 0 # px extra entre les dues línies (fase / completada) text: # Noms d'easing tal com els resol UiConfig::curveByName (vegeu diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 5a42d74..337bc55 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -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); } } diff --git a/source/game/scenes/room_fsm.cpp b/source/game/scenes/room_fsm.cpp index 0ec5671..cb4e5e0 100644 --- a/source/game/scenes/room_fsm.cpp +++ b/source/game/scenes/room_fsm.cpp @@ -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"]; diff --git a/source/game/scenes/room_fsm.hpp b/source/game/scenes/room_fsm.hpp index 7a85e27..2114b8b 100644 --- a/source/game/scenes/room_fsm.hpp +++ b/source/game/scenes/room_fsm.hpp @@ -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}; };