feat(scenes): data/scenes/game.yaml amb timings i corbes de transició
This commit is contained in:
1 parent
651db50a93
commit
368f9d2d6a
4 files changed
+117
No files matched your search
@@ -0,0 +1,24 @@
|
|||||||
|
# Configuració de la GameScene: timings i corbes de la FSM de sala
|
||||||
|
# (ROOM_INTRO i ROOM_OUTRO). Tots els valors són ms i tota la geometria
|
||||||
|
# i font del text es reutilitzen del tema UI (data/ui.yaml > pause +
|
||||||
|
# notification). Si manca el fitxer o alguna clau, GameScene cau als
|
||||||
|
# fallbacks compilats; veure `readSceneConfig` a game_scene.cpp.
|
||||||
|
|
||||||
|
room_intro:
|
||||||
|
fade_in_ms: 500 # negre opac → món visible
|
||||||
|
text_delay_ms: 500 # espera amb el món net abans de sortir el text
|
||||||
|
text_enter_ms: 500 # text esquerra → centre
|
||||||
|
text_hold_ms: 1000 # text quiet al centre
|
||||||
|
text_exit_ms: 500 # text centre → fora per l'esquerra
|
||||||
|
|
||||||
|
room_outro:
|
||||||
|
text_enter_ms: 500
|
||||||
|
text_hold_ms: 1000
|
||||||
|
text_exit_ms: 500
|
||||||
|
fade_out_ms: 500 # món visible → negre opac
|
||||||
|
|
||||||
|
text:
|
||||||
|
# Noms d'easing tal com els resol UiConfig::curveByName (vegeu
|
||||||
|
# `data/ui.yaml`). El text entra suau i surt accelerant.
|
||||||
|
enter_curve: outCubic
|
||||||
|
exit_curve: inCubic
|
||||||
@@ -74,6 +74,63 @@ namespace {
|
|||||||
return yaml[key].get_value<float>();
|
return yaml[key].get_value<float>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Llegeix un sub-camp sencer del bloc `parent` (o el fallback) sense
|
||||||
|
// imprimir res. Pensat per a la lectura puntual del data/scenes/game.yaml.
|
||||||
|
auto readChildInt(const fkyaml::node& parent, const char* key, int fallback) -> int {
|
||||||
|
if (!parent.contains(key)) { return fallback; }
|
||||||
|
return parent[key].get_value<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Carrega `data/scenes/game.yaml` i emplena un SceneTransitionConfig.
|
||||||
|
// Si el fitxer falta o algun camp no hi és, els valors de fallback
|
||||||
|
// que ja porta l'estructura es conserven. Les dues corbes es resolen
|
||||||
|
// per nom amb `UiConfig::curveByName` (mateix mecanisme que la pausa);
|
||||||
|
// si el nom és desconegut, cau a `Easing::linear` amb warning al log.
|
||||||
|
auto readSceneConfig(const std::string& yaml_path) -> GameScene::SceneTransitionConfig {
|
||||||
|
GameScene::SceneTransitionConfig cfg{};
|
||||||
|
cfg.text_enter_curve = UiConfig::curveByName("outCubic");
|
||||||
|
cfg.text_exit_curve = UiConfig::curveByName("inCubic");
|
||||||
|
|
||||||
|
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||||
|
if (bytes.empty()) {
|
||||||
|
std::cout << "GameScene: " << yaml_path << " absent — uso fallbacks compilats\n";
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||||
|
const auto* end = begin + bytes.size();
|
||||||
|
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||||
|
|
||||||
|
if (yaml.contains("room_intro")) {
|
||||||
|
const auto& n = yaml["room_intro"];
|
||||||
|
cfg.intro_fade_in_ms = readChildInt(n, "fade_in_ms", cfg.intro_fade_in_ms);
|
||||||
|
cfg.intro_text_delay_ms = readChildInt(n, "text_delay_ms", cfg.intro_text_delay_ms);
|
||||||
|
cfg.intro_text_enter_ms = readChildInt(n, "text_enter_ms", cfg.intro_text_enter_ms);
|
||||||
|
cfg.intro_text_hold_ms = readChildInt(n, "text_hold_ms", cfg.intro_text_hold_ms);
|
||||||
|
cfg.intro_text_exit_ms = readChildInt(n, "text_exit_ms", cfg.intro_text_exit_ms);
|
||||||
|
}
|
||||||
|
if (yaml.contains("room_outro")) {
|
||||||
|
const auto& n = yaml["room_outro"];
|
||||||
|
cfg.outro_text_enter_ms = readChildInt(n, "text_enter_ms", cfg.outro_text_enter_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_fade_out_ms = readChildInt(n, "fade_out_ms", cfg.outro_fade_out_ms);
|
||||||
|
}
|
||||||
|
if (yaml.contains("text")) {
|
||||||
|
const auto& n = yaml["text"];
|
||||||
|
if (n.contains("enter_curve")) {
|
||||||
|
cfg.text_enter_curve = UiConfig::curveByName(n["enter_curve"].get_value<std::string>());
|
||||||
|
}
|
||||||
|
if (n.contains("exit_curve")) {
|
||||||
|
cfg.text_exit_curve = UiConfig::curveByName(n["exit_curve"].get_value<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "GameScene: timings carregats des de " << yaml_path
|
||||||
|
<< " (intro fade " << cfg.intro_fade_in_ms
|
||||||
|
<< "ms, outro fade " << cfg.outro_fade_out_ms << "ms)\n";
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
// Comprova si `a` i `b` se solapen amb una tolerància positiva al
|
// Comprova si `a` i `b` se solapen amb una tolerància positiva al
|
||||||
// contacte perfecte (cantos que es toquen = no-solapament). SDL3 ja
|
// contacte perfecte (cantos que es toquen = no-solapament). SDL3 ja
|
||||||
// ofereix `SDL_HasRectIntersectionFloat`, però aquí volem la mateixa
|
// ofereix `SDL_HasRectIntersectionFloat`, però aquí volem la mateixa
|
||||||
@@ -398,6 +455,10 @@ GameScene::GameScene(Config config)
|
|||||||
pause_font_ = std::make_shared<Text>(pause_surface, UiConfig::get().placeholderFont().fnt);
|
pause_font_ = std::make_shared<Text>(pause_surface, UiConfig::get().placeholderFont().fnt);
|
||||||
pause_font_->setDefaultKerning(UiConfig::get().placeholderFont().kerning);
|
pause_font_->setDefaultKerning(UiConfig::get().placeholderFont().kerning);
|
||||||
|
|
||||||
|
// Timings i corbes de la FSM de sala. Llegits del YAML una sola
|
||||||
|
// vegada; canvis requereixen reiniciar el joc.
|
||||||
|
transition_config_ = readSceneConfig(Defaults::GameScene::CONFIG_YAML);
|
||||||
|
|
||||||
// Log d'estat inicial: la FSM arrenca a ROOM_INTRO. En aquesta fita
|
// Log d'estat inicial: la FSM arrenca a ROOM_INTRO. En aquesta fita
|
||||||
// les transicions són instantànies (sense fades ni text) i el primer
|
// les transicions són instantànies (sense fades ni text) i el primer
|
||||||
// tick d'`updateRoomTransition` ja saltarà a PLAYING.
|
// tick d'`updateRoomTransition` ja saltarà a PLAYING.
|
||||||
|
|||||||
@@ -50,6 +50,27 @@ class GameScene : public Scene {
|
|||||||
ROOM_OUTRO, // Sortida de sala: text de sortida + fade out.
|
ROOM_OUTRO, // Sortida de sala: text de sortida + fade out.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Configuració de la FSM de sala llegida de `data/scenes/game.yaml`.
|
||||||
|
// Si el YAML manca, els camps queden amb els fallbacks compilats. Es
|
||||||
|
// carrega un sol cop al ctor; canvis al fitxer requereixen reiniciar.
|
||||||
|
// Pública pel mateix motiu que State: el reader viu en un anonymous
|
||||||
|
// namespace fora de la classe per simetria amb els altres readers.
|
||||||
|
struct SceneTransitionConfig {
|
||||||
|
int intro_fade_in_ms{500};
|
||||||
|
int intro_text_delay_ms{500};
|
||||||
|
int intro_text_enter_ms{500};
|
||||||
|
int intro_text_hold_ms{1000};
|
||||||
|
int intro_text_exit_ms{500};
|
||||||
|
|
||||||
|
int outro_text_enter_ms{500};
|
||||||
|
int outro_text_hold_ms{1000};
|
||||||
|
int outro_text_exit_ms{500};
|
||||||
|
int outro_fade_out_ms{500};
|
||||||
|
|
||||||
|
UiConfig::CurveFn text_enter_curve{nullptr};
|
||||||
|
UiConfig::CurveFn text_exit_curve{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
explicit GameScene(Config config = defaultConfig());
|
explicit GameScene(Config config = defaultConfig());
|
||||||
~GameScene() override;
|
~GameScene() override;
|
||||||
|
|
||||||
@@ -155,6 +176,10 @@ class GameScene : public Scene {
|
|||||||
UiConfig::CurveFn curve{nullptr}; // Corba activa.
|
UiConfig::CurveFn curve{nullptr}; // Corba activa.
|
||||||
} pause_;
|
} pause_;
|
||||||
|
|
||||||
|
// Configuració de la FSM de sala (intro/outro). Carregada al ctor des
|
||||||
|
// de `data/scenes/game.yaml`; valors per defecte si manca el YAML.
|
||||||
|
SceneTransitionConfig transition_config_{};
|
||||||
|
|
||||||
// Estat actual de la FSM de sala. S'inicialitza a ROOM_INTRO al ctor
|
// Estat actual de la FSM de sala. S'inicialitza a ROOM_INTRO al ctor
|
||||||
// perquè cada vegada que entres al joc passes per la presentació de
|
// perquè cada vegada que entres al joc passes per la presentació de
|
||||||
// la sala. La transició a PLAYING l'orquestra `updateRoomTransition`.
|
// la sala. La transició a PLAYING l'orquestra `updateRoomTransition`.
|
||||||
|
|||||||
@@ -220,6 +220,13 @@ namespace Defaults {
|
|||||||
} // namespace Editor
|
} // namespace Editor
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Configuració de l'escena de joc (timings i corbes de la FSM de sala).
|
||||||
|
// Independent de la piràmide concreta — quan un dia hi haja diferents
|
||||||
|
// ritmes per piràmide, aquest YAML pot adoptar variants per nivell.
|
||||||
|
namespace GameScene {
|
||||||
|
constexpr const char* CONFIG_YAML = "data/scenes/game.yaml";
|
||||||
|
} // namespace GameScene
|
||||||
|
|
||||||
// Rutes d'assets per piràmide. Centralitzats ací perquè `GameScene` no
|
// Rutes d'assets per piràmide. Centralitzats ací perquè `GameScene` no
|
||||||
// en contingui cap literal; afegir una piràmide nova serà un altre
|
// en contingui cap literal; afegir una piràmide nova serà un altre
|
||||||
// conjunt de constants + un Config distint passat al ctor.
|
// conjunt de constants + un Config distint passat al ctor.
|
||||||
|
|||||||
Reference in new issue
Block a user