feat(intro): font dedicada (CaesarDressing) i separació vertical entre línies
Nova font del rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO): CaesarDressing-Regular, vista com a fonts.room_text al data/ui.yaml i exposada per UiConfig::roomTextFont(). Director la preloda al costat de la del HUD i la del placeholder; GameScene construeix room_text_font_ paral·lel a pause_font_ i renderRoomText l'usa per a les dues línies de l'INTRO i el text de l'OUTRO. La pausa segueix amb la font placeholder antiga — no es barregen. Espai vertical configurable: nova clau room_intro.line_gap_px al data/scenes/game.yaml (default 8 px). El gap es suma al lineHeight natural del font i es reparteix simètricament cap amunt i cap avall del CENTER_Y, deixant el bloc de dues línies sempre centrat. Es poden afinar des del YAML sense recompilar.
This commit is contained in:
1 parent
f52e7f4682
commit
af25a31639
11 files changed
+201
-17
No files matched your search
@@ -436,6 +436,13 @@ GameScene::GameScene(Config config)
|
||||
pause_font_ = std::make_shared<Text>(pause_surface, UiConfig::get().placeholderFont().fnt);
|
||||
pause_font_->setDefaultKerning(UiConfig::get().placeholderFont().kerning);
|
||||
|
||||
// Font del rètol de transició de sala. Mateixa convenció que la pausa
|
||||
// (Surface preloaded pel Director, només construïm el `Text` ací).
|
||||
const std::string ROOM_TEXT_FONT_KEY = UiConfig::get().roomTextFont().name + ".gif";
|
||||
auto room_text_surface = Resource::Cache::get().getSurface(ROOM_TEXT_FONT_KEY);
|
||||
room_text_font_ = std::make_shared<Text>(room_text_surface, UiConfig::get().roomTextFont().fnt);
|
||||
room_text_font_->setDefaultKerning(UiConfig::get().roomTextFont().kerning);
|
||||
|
||||
// Timings i corbes de la FSM de sala. Llegits del YAML una sola
|
||||
// vegada; canvis requereixen reiniciar el joc.
|
||||
transition_config_ = RoomFsm::loadConfig(Defaults::GameScene::CONFIG_YAML);
|
||||
@@ -627,10 +634,10 @@ void GameScene::renderRoomFade() {
|
||||
}
|
||||
|
||||
void GameScene::renderRoomText() {
|
||||
// Text de la transició de sala. Reusa la font cachejada per a la
|
||||
// pausa (mateix tipus de lletra, mateix índex de color), i fa el
|
||||
// mateix patró esquerra → centre → dreta que el text de pausa però
|
||||
// amb les durades pròpies de la transició.
|
||||
// Text de la transició de sala. Font dedicada (`room_text_font_`,
|
||||
// CaesarDressing per defecte) — la pausa té la seua i no es barregen.
|
||||
// Patró esquerra → centre → dreta amb les durades pròpies de la
|
||||
// transició.
|
||||
//
|
||||
// Mapatge per estat (només els estats amb text actiu hi entren):
|
||||
// ROOM_INTRO: phases 2..4 → enter / hold / exit; dues línies
|
||||
@@ -639,7 +646,7 @@ void GameScene::renderRoomText() {
|
||||
// per deixar la porta oberta a desacoblar-les.
|
||||
// ROOM_OUTRO: phases 0..2 → enter / hold / exit; una línia
|
||||
// ("fase completada").
|
||||
if (!pause_font_) { return; }
|
||||
if (!room_text_font_) { return; }
|
||||
|
||||
constexpr int KERNING = 0;
|
||||
constexpr Uint8 OUTLINE_WHITE = 255;
|
||||
@@ -671,7 +678,7 @@ void GameScene::renderRoomText() {
|
||||
};
|
||||
|
||||
auto draw_line = [&](const std::string& text, int x, int y) {
|
||||
pause_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG,
|
||||
room_text_font_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG | Text::STROKE4_FLAG,
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
@@ -685,25 +692,28 @@ void GameScene::renderRoomText() {
|
||||
const auto& mgr = Levels::LevelManager::get();
|
||||
const std::string LINE_PYRAMID = RoomFsm::formatIntroPyramidLine(mgr.currentPyramid());
|
||||
const std::string LINE_ROOM = RoomFsm::formatIntroRoomLine(mgr.currentRoom());
|
||||
const int W_PYRAMID = pause_font_->length(LINE_PYRAMID, KERNING);
|
||||
const int W_ROOM = pause_font_->length(LINE_ROOM, KERNING);
|
||||
const int W_PYRAMID = room_text_font_->length(LINE_PYRAMID, KERNING);
|
||||
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);
|
||||
// Bloc de dues línies centrat al voltant de CENTER_Y: la
|
||||
// piràmide ocupa la línia de damunt, la sala la de davall. Si
|
||||
// un dia el font canvia d'alçada, `getLineHeight` ho reflecteix.
|
||||
const int LINE_HEIGHT = pause_font_->getLineHeight();
|
||||
const int Y_PYRAMID = GameCanvas::CENTER_Y - LINE_HEIGHT;
|
||||
const int Y_ROOM = GameCanvas::CENTER_Y;
|
||||
// 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
|
||||
// meitat la traiem cap amunt de la piràmide i la meitat la
|
||||
// sumem cap avall a la sala, mantenint el centre del bloc fix.
|
||||
const int LINE_HEIGHT = room_text_font_->getLineHeight();
|
||||
const int GAP = transition_config_.intro_text_line_gap_px;
|
||||
const int Y_PYRAMID = GameCanvas::CENTER_Y - LINE_HEIGHT - (GAP / 2);
|
||||
const int Y_ROOM = GameCanvas::CENTER_Y + (GAP / 2);
|
||||
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 = pause_font_->length(TEXT, KERNING);
|
||||
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 Y = GameCanvas::CENTER_Y - (pause_font_->getLineHeight() / 2);
|
||||
const int Y = GameCanvas::CENTER_Y - (room_text_font_->getLineHeight() / 2);
|
||||
draw_line(TEXT, X, Y);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user