feat(demo): transició títol→demo amb dive de càmera + cortinilla negra (substitueix el fundido)
This commit is contained in:
@@ -38,7 +38,7 @@ TitleScene::TitleScene(SDLManager& sdl, SceneContext& context)
|
||||
: sdl_(sdl),
|
||||
context_(context),
|
||||
text_(sdl.getRenderer()),
|
||||
fade_(sdl.getRenderer()) {
|
||||
curtain_(sdl.getRenderer()) {
|
||||
std::cout << "SceneType Titol: Inicialitzant...\n";
|
||||
|
||||
match_config_.player1_active = false;
|
||||
@@ -277,8 +277,9 @@ void TitleScene::dibuixarPeuTitol(float spacing) const {
|
||||
// a 1.0 (a la mida i posició finals, "lluny" al VP).
|
||||
const float SCREEN_CENTRE_X = Defaults::Game::WIDTH / 2.0F;
|
||||
const float SCREEN_CENTRE_Y = Defaults::Game::HEIGHT / 2.0F;
|
||||
const float JAILGAMES_S = std::lerp(S::FOOTER_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_jailgames_progress_));
|
||||
const float COPYRIGHT_S = std::lerp(S::FOOTER_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_copyright_progress_));
|
||||
// dive_zoom_ (attract) afegeix el zoom del dive per travessar el peu.
|
||||
const float JAILGAMES_S = dive_zoom_ * std::lerp(S::FOOTER_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_jailgames_progress_));
|
||||
const float COPYRIGHT_S = dive_zoom_ * std::lerp(S::FOOTER_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_copyright_progress_));
|
||||
|
||||
const float JAILGAMES_RENDER_SCALE = Defaults::Title::Layout::JAILGAMES_SCALE * JAILGAMES_S;
|
||||
for (const auto& letter : letters_jailgames_) {
|
||||
@@ -334,8 +335,11 @@ void TitleScene::update(float delta_time) {
|
||||
case TitleState::BLACK_SCREEN:
|
||||
updateBlackScreenState(delta_time);
|
||||
break;
|
||||
case TitleState::DEMO_FADE_OUT:
|
||||
updateDemoFadeOutState(delta_time);
|
||||
case TitleState::DEMO_DIVE:
|
||||
updateDemoDiveState(delta_time);
|
||||
break;
|
||||
case TitleState::DEMO_CURTAIN:
|
||||
updateDemoCurtainState(delta_time);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -372,11 +376,14 @@ void TitleScene::update(float delta_time) {
|
||||
demo_cfg.player2_active = (SC.players >= 2);
|
||||
demo_cfg.mode = GameConfig::Mode::DEMO;
|
||||
context_.setMatchConfig(demo_cfg);
|
||||
// No saltem en sec: fosa a negre i, en acabar, canvi a GAME (el salt
|
||||
// real el fa updateDemoFadeOutState). L'estat deixa de ser MAIN, així
|
||||
// que ni es re-dispara la demo ni s'accepta START durant la fosa.
|
||||
current_state_ = TitleState::DEMO_FADE_OUT;
|
||||
fade_.start(0.0F, 1.0F, Defaults::Game::Fade::DEMO_OUT_DURATION);
|
||||
// No saltem en sec: primer un "dive" de càmera cap al punt de fuga
|
||||
// (deixa enrere títol/naus/logo) i després la cortinilla. L'estat
|
||||
// deixa de ser MAIN, així que ni es re-dispara la demo ni s'accepta
|
||||
// START durant la transició. Amaguem ja el "PREMEU START".
|
||||
press_start_visible_ = false;
|
||||
current_state_ = TitleState::DEMO_DIVE;
|
||||
dive_time_ = 0.0F;
|
||||
dive_zoom_ = 1.0F;
|
||||
temps_acumulat_ = 0.0F;
|
||||
}
|
||||
}
|
||||
@@ -482,9 +489,29 @@ void TitleScene::updateBlackScreenState(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void TitleScene::updateDemoFadeOutState(float delta_time) {
|
||||
fade_.update(delta_time);
|
||||
if (fade_.isDone()) {
|
||||
void TitleScene::updateDemoDiveState(float delta_time) {
|
||||
namespace D = Defaults::Game::Dive;
|
||||
dive_time_ += delta_time;
|
||||
const float T = std::min(dive_time_ / D::DURATION, 1.0F);
|
||||
const float EASED = Easing::easeInQuad(T); // acceleració cap al punt de fuga
|
||||
|
||||
// Càmera 3D real cap a +Z: starfield i naus es projecten amb la càmera, així
|
||||
// que les estrelles es rasguen i les naus creixen i s'escapen pels costats.
|
||||
if (camera_ != nullptr) {
|
||||
camera_->setPosition(Vec3{.x = 0.0F, .y = 0.0F, .z = EASED * D::CAMERA_DISTANCE});
|
||||
}
|
||||
// Logo i peu són 2D: els fakegem el dive amb un zoom des del centre.
|
||||
dive_zoom_ = std::lerp(1.0F, D::ZOOM_MAX, EASED);
|
||||
|
||||
if (T >= 1.0F) {
|
||||
current_state_ = TitleState::DEMO_CURTAIN;
|
||||
curtain_.cover(Defaults::Game::Curtain::COVER_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
void TitleScene::updateDemoCurtainState(float delta_time) {
|
||||
curtain_.update(delta_time);
|
||||
if (curtain_.isDone()) {
|
||||
context_.setNextScene(SceneType::GAME);
|
||||
}
|
||||
}
|
||||
@@ -594,7 +621,8 @@ void TitleScene::draw() {
|
||||
current_state_ == TitleState::STARFIELD ||
|
||||
current_state_ == TitleState::MAIN ||
|
||||
current_state_ == TitleState::PLAYER_JOIN_PHASE ||
|
||||
current_state_ == TitleState::DEMO_FADE_OUT)) {
|
||||
current_state_ == TitleState::DEMO_DIVE ||
|
||||
current_state_ == TitleState::DEMO_CURTAIN)) {
|
||||
ship_animator_->draw();
|
||||
}
|
||||
drawFlashes();
|
||||
@@ -603,19 +631,21 @@ void TitleScene::draw() {
|
||||
return;
|
||||
}
|
||||
|
||||
// DEMO_FADE_OUT es pinta com MAIN (logo + text) perquè el títol segueixi
|
||||
// visible sota la fosa a negre.
|
||||
// DEMO_DIVE/DEMO_CURTAIN es pinten com MAIN (logo + peu) perquè el títol
|
||||
// segueixi visible sota el dive i la cortinilla.
|
||||
if (current_state_ != TitleState::MAIN &&
|
||||
current_state_ != TitleState::PLAYER_JOIN_PHASE &&
|
||||
current_state_ != TitleState::DEMO_FADE_OUT) {
|
||||
fade_.draw(); // BLACK_SCREEN i altres: només la fosa (si activa)
|
||||
current_state_ != TitleState::DEMO_DIVE &&
|
||||
current_state_ != TitleState::DEMO_CURTAIN) {
|
||||
curtain_.draw(); // BLACK_SCREEN i altres: només la cortinilla (si activa)
|
||||
return;
|
||||
}
|
||||
|
||||
// Factor d'escala+posició per simular un moviment 3D des de l'usuari (prop,
|
||||
// sprite gran i posició projectada extrema) cap al VP (lluny, sprite a la
|
||||
// seva mida i posició finals). Pivot: centre de pantalla (= projecció VP).
|
||||
const float LOGO_S = std::lerp(Defaults::Title::Sequence::LOGO_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_logo_progress_));
|
||||
// El dive (attract) hi afegeix un zoom extra (dive_zoom_) per travessar-los.
|
||||
const float LOGO_S = dive_zoom_ * std::lerp(Defaults::Title::Sequence::LOGO_INTRO_SCALE_START, 1.0F, Easing::easeOutQuad(intro_logo_progress_));
|
||||
const float SCREEN_CENTRE_X = Defaults::Game::WIDTH / 2.0F;
|
||||
const float SCREEN_CENTRE_Y = Defaults::Game::HEIGHT / 2.0F;
|
||||
const float LOGO_RENDER_SCALE = Defaults::Title::Layout::LOGO_SCALE * LOGO_S;
|
||||
@@ -680,8 +710,8 @@ void TitleScene::draw() {
|
||||
|
||||
dibuixarPeuTitol(SPACING);
|
||||
|
||||
// Fosa a negre (attract): per damunt de tot. No-op si no està activa.
|
||||
fade_.draw();
|
||||
// Cortinilla negra (attract): per damunt de tot. No-op si no està activa.
|
||||
curtain_.draw();
|
||||
}
|
||||
|
||||
auto TitleScene::checkSkipButtonPressed() -> bool {
|
||||
|
||||
Reference in New Issue
Block a user