feat(intro): línies del rètol travessen en direccions oposades

compute_x guanya un paràmetre from_right que decideix per quin costat
entra i per quin surt. La línia de la piràmide es queda amb el patró
clàssic (entra per l'esquerra, surt per la dreta); la de la sala s'hi
inverteix (entra per la dreta, surt per l'esquerra). El text de
l'OUTRO continua amb la direcció original.
This commit is contained in:
JailDesigner committed 2026-04-26 16:59:01 +02:00
1 parent af25a31639
commit 00594d9eb2
1 file changed
+17 -11
+17 -11
View File
@@ -652,27 +652,30 @@ void GameScene::renderRoomText() {
constexpr Uint8 OUTLINE_WHITE = 255;
constexpr Uint8 STROKE_DIST = 1;
// Calcula la X animada d'una línia: entra des de l'esquerra
// (off-screen amb el seu cantó dret a x=0), s'atura al CENTER_X
// durant el hold i surt cap a la dreta (off-screen amb el cantó
// esquerre a x=WIDTH). El càlcul depèn de l'amplada de la línia
// — per això la passem com a paràmetre.
auto compute_x = [&](int width, int phase_enter, int phase_exit, int dur_enter, int dur_exit) -> int {
// Calcula la X animada d'una línia: entra des de fora de pantalla,
// s'atura al CENTER_X durant el hold i surt pel costat oposat.
// `from_right=false` és el patró clàssic (entra per l'esquerra,
// surt cap a la dreta); `true` el flipa (entra per la dreta, surt
// cap a l'esquerra). Així les dues línies de l'INTRO poden
// travessar la pantalla en direccions oposades.
auto compute_x = [&](int width, int phase_enter, int phase_exit, int dur_enter, int dur_exit, bool from_right) -> int {
const int OFF_LEFT = -width;
const int OFF_RIGHT = GameCanvas::WIDTH;
const int OFF_ENTER = from_right ? OFF_RIGHT : OFF_LEFT;
const int OFF_EXIT = from_right ? OFF_LEFT : OFF_RIGHT;
if (transition_.phase == phase_enter) {
const float T = (dur_enter > 0)
? std::clamp(static_cast<float>(transition_.elapsed_ms) / static_cast<float>(dur_enter), 0.0F, 1.0F)
: 1.0F;
const auto CURVE = (transition_config_.text_enter_curve != nullptr) ? transition_config_.text_enter_curve : &Easing::linear;
return Easing::lerpInt(OFF_LEFT, GameCanvas::CENTER_X, CURVE(T));
return Easing::lerpInt(OFF_ENTER, GameCanvas::CENTER_X, CURVE(T));
}
if (transition_.phase == phase_exit) {
const float T = (dur_exit > 0)
? std::clamp(static_cast<float>(transition_.elapsed_ms) / static_cast<float>(dur_exit), 0.0F, 1.0F)
: 1.0F;
const auto CURVE = (transition_config_.text_exit_curve != nullptr) ? transition_config_.text_exit_curve : &Easing::linear;
return Easing::lerpInt(GameCanvas::CENTER_X, OFF_RIGHT, CURVE(T));
return Easing::lerpInt(GameCanvas::CENTER_X, OFF_EXIT, CURVE(T));
}
return GameCanvas::CENTER_X;
};
@@ -696,8 +699,11 @@ void GameScene::renderRoomText() {
const int W_ROOM = room_text_font_->length(LINE_ROOM, KERNING);
const int DUR_ENTER = transition_config_.intro_text_enter_ms;
const int DUR_EXIT = transition_config_.intro_text_exit_ms;
const int X_PYRAMID = compute_x(W_PYRAMID, 2, 4, DUR_ENTER, DUR_EXIT);
const int X_ROOM = compute_x(W_ROOM, 2, 4, DUR_ENTER, DUR_EXIT);
// Direccions oposades: la línia de la piràmide entra per
// l'esquerra, la de la sala per la dreta. Quan surten, cada
// una continua cap al costat oposat al que ha entrat.
const int X_PYRAMID = compute_x(W_PYRAMID, 2, 4, DUR_ENTER, DUR_EXIT, /*from_right=*/false);
const int X_ROOM = compute_x(W_ROOM, 2, 4, DUR_ENTER, DUR_EXIT, /*from_right=*/true);
// Bloc de dues línies centrat al voltant de CENTER_Y. Entre
// les dues línies hi posem `intro_text_line_gap_px` extra (a
// més del lineHeight natural) per donar-los aire visual; la
@@ -712,7 +718,7 @@ void GameScene::renderRoomText() {
} 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);
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);
}