feat(demo): transició títol→demo amb dive de càmera + cortinilla negra (substitueix el fundido)
This commit is contained in:
@@ -39,11 +39,18 @@ namespace Defaults::Game {
|
||||
constexpr float LEVEL_COMPLETED_DURATION = 3.0F; // Duración total
|
||||
constexpr float LEVEL_COMPLETED_TYPING_RATIO = 0.05F; // ~150ms de typewriter (escan ràpid però visible)
|
||||
|
||||
// Attract mode: durada de la fosa a/desde negre a les transicions de demo.
|
||||
namespace Fade {
|
||||
constexpr float DEMO_OUT_DURATION = 0.6F; // TÍTOL → DEMO (fosa a negre abans del salt)
|
||||
constexpr float DEMO_IN_DURATION = 0.6F; // DEMO: fosa des de negre sobre el joc ja en marxa
|
||||
} // namespace Fade
|
||||
// Attract mode: transició TÍTOL → DEMO. Primer un "dive" de càmera cap al
|
||||
// punt de fuga (deixa enrere títol/naus/logo) i després una cortinilla negra
|
||||
// que cau per tapar; a la demo, la cortinilla segueix caient i destapa.
|
||||
namespace Dive {
|
||||
constexpr float DURATION = 0.55F; // Durada del dive (s), amb acceleració (ease-in)
|
||||
constexpr float CAMERA_DISTANCE = 450.0F; // Avanç de la càmera en +Z (passa les naus, a Z≈323)
|
||||
constexpr float ZOOM_MAX = 7.0F; // Zoom final dels elements 2D (logo + peu) en travessar-los
|
||||
} // namespace Dive
|
||||
namespace Curtain {
|
||||
constexpr float COVER_DURATION = 0.35F; // TÍTOL: la tela cau i tapa
|
||||
constexpr float REVEAL_DURATION = 0.45F; // DEMO: la tela segueix caient i destapa
|
||||
} // namespace Curtain
|
||||
|
||||
// Transición INIT_HUD (animación inicial del HUD)
|
||||
constexpr float INIT_HUD_DURATION = 3.0F; // Duración total del estado
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// curtain.cpp - Implementació de la cortinilla negra
|
||||
// © 2026 JailDesigner
|
||||
|
||||
#include "core/graphics/curtain.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "core/defaults/game.hpp"
|
||||
#include "core/math/easing.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
namespace {
|
||||
constexpr float SCREEN_H = static_cast<float>(Defaults::Game::HEIGHT);
|
||||
constexpr float SCREEN_W = static_cast<float>(Defaults::Game::WIDTH);
|
||||
} // namespace
|
||||
|
||||
Curtain::Curtain(Rendering::Renderer* renderer)
|
||||
: renderer_(renderer) {}
|
||||
|
||||
void Curtain::cover(float duration) {
|
||||
// Caire superior de -H (fora, a dalt) fins a 0 (tela tapant tota la pantalla).
|
||||
from_ = -SCREEN_H;
|
||||
to_ = 0.0F;
|
||||
duration_ = duration;
|
||||
elapsed_ = 0.0F;
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
void Curtain::reveal(float duration) {
|
||||
// Caire superior de 0 (tapant) fins a +H (tela fora per baix).
|
||||
from_ = 0.0F;
|
||||
to_ = SCREEN_H;
|
||||
duration_ = duration;
|
||||
elapsed_ = 0.0F;
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
void Curtain::update(float delta_time) {
|
||||
if (!active_) {
|
||||
return;
|
||||
}
|
||||
elapsed_ += delta_time;
|
||||
}
|
||||
|
||||
auto Curtain::topY() const -> float {
|
||||
if (duration_ <= 0.0F) {
|
||||
return to_;
|
||||
}
|
||||
const float T = std::clamp(elapsed_ / duration_, 0.0F, 1.0F);
|
||||
// Ease-in: la tela "cau" accelerant, com per gravetat.
|
||||
return Easing::lerp(from_, to_, Easing::easeInQuad(T));
|
||||
}
|
||||
|
||||
auto Curtain::isDone() const -> bool {
|
||||
return !active_ || elapsed_ >= duration_;
|
||||
}
|
||||
|
||||
void Curtain::draw() const {
|
||||
if (!active_) {
|
||||
return;
|
||||
}
|
||||
const float TOP = topY();
|
||||
// Si la tela ja ha sortit completament per baix, no hi ha res a pintar.
|
||||
if (TOP >= SCREEN_H) {
|
||||
return;
|
||||
}
|
||||
renderer_->pushRect(0.0F, TOP, SCREEN_W, SCREEN_H, 0.0F, 0.0F, 0.0F, 1.0F);
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
@@ -0,0 +1,48 @@
|
||||
// curtain.hpp - Cortinilla negra per a transicions d'escena
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// Tela negra a pantalla completa que es mou SEMPRE cap avall:
|
||||
// - cover(): cau des de dalt fins a tapar-ho tot (queda negre).
|
||||
// - reveal(): segueix caient i surt per baix, deixant veure l'escena.
|
||||
// Una escena la posseeix, l'actualitza cada frame i la dibuixa l'ÚLTIM (per
|
||||
// damunt de tot). En repòs (no arrencada o reveal acabada) el draw() és no-op.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/rendering/render_context.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class Curtain {
|
||||
public:
|
||||
explicit Curtain(Rendering::Renderer* renderer);
|
||||
|
||||
// Tela que cau des de dalt fins a tapar tota la pantalla en 'duration' s.
|
||||
void cover(float duration);
|
||||
|
||||
// Tela que segueix caient i surt per baix (destapa) en 'duration' s.
|
||||
void reveal(float duration);
|
||||
|
||||
// Avança el temporitzador intern.
|
||||
void update(float delta_time);
|
||||
|
||||
// Dibuixa la tela negra a la seva posició vertical actual. No-op si no
|
||||
// queda res visible.
|
||||
void draw() const;
|
||||
|
||||
// Cert quan el moviment actual ha acabat (o no s'ha arrencat mai).
|
||||
[[nodiscard]] auto isDone() const -> bool;
|
||||
|
||||
private:
|
||||
// Posició actual del caire superior de la tela (píxels lògics).
|
||||
[[nodiscard]] auto topY() const -> float;
|
||||
|
||||
Rendering::Renderer* renderer_;
|
||||
float from_{0.0F};
|
||||
float to_{0.0F};
|
||||
float duration_{0.0F};
|
||||
float elapsed_{0.0F};
|
||||
bool active_{false};
|
||||
};
|
||||
|
||||
} // namespace Graphics
|
||||
@@ -1,62 +0,0 @@
|
||||
// screen_fade.cpp - Implementació de la fosa a/desde negre
|
||||
// © 2026 JailDesigner
|
||||
|
||||
#include "core/graphics/screen_fade.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "core/defaults/game.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
ScreenFade::ScreenFade(Rendering::Renderer* renderer)
|
||||
: renderer_(renderer) {}
|
||||
|
||||
void ScreenFade::start(float from, float to, float duration) {
|
||||
from_ = from;
|
||||
to_ = to;
|
||||
duration_ = duration;
|
||||
elapsed_ = 0.0F;
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
void ScreenFade::update(float delta_time) {
|
||||
if (!active_) {
|
||||
return;
|
||||
}
|
||||
elapsed_ += delta_time;
|
||||
}
|
||||
|
||||
auto ScreenFade::alpha() const -> float {
|
||||
if (!active_) {
|
||||
return 0.0F;
|
||||
}
|
||||
if (duration_ <= 0.0F) {
|
||||
return to_;
|
||||
}
|
||||
const float T = std::clamp(elapsed_ / duration_, 0.0F, 1.0F);
|
||||
return std::lerp(from_, to_, T);
|
||||
}
|
||||
|
||||
auto ScreenFade::isDone() const -> bool {
|
||||
return !active_ || elapsed_ >= duration_;
|
||||
}
|
||||
|
||||
void ScreenFade::draw() const {
|
||||
const float A = alpha();
|
||||
if (A <= 0.0F) {
|
||||
return;
|
||||
}
|
||||
renderer_->pushRect(
|
||||
0.0F,
|
||||
0.0F,
|
||||
static_cast<float>(Defaults::Game::WIDTH),
|
||||
static_cast<float>(Defaults::Game::HEIGHT),
|
||||
0.0F,
|
||||
0.0F,
|
||||
0.0F,
|
||||
A);
|
||||
}
|
||||
|
||||
} // namespace Graphics
|
||||
@@ -1,43 +0,0 @@
|
||||
// screen_fade.hpp - Fosa a/desde negre per a transicions d'escena
|
||||
// © 2026 JailDesigner
|
||||
//
|
||||
// Rect negre a pantalla completa amb l'alpha animat linealment. L'escena que el
|
||||
// posseeix l'actualitza cada frame i el dibuixa l'ÚLTIM (per damunt de tot). En
|
||||
// repòs (default-construït o fosa acabada amb alpha 0) el draw() és un no-op.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/rendering/render_context.hpp"
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
class ScreenFade {
|
||||
public:
|
||||
explicit ScreenFade(Rendering::Renderer* renderer);
|
||||
|
||||
// Arrenca una fosa lineal d'alpha 'from' a 'to' en 'duration' segons.
|
||||
void start(float from, float to, float duration);
|
||||
|
||||
// Avança el temporitzador intern.
|
||||
void update(float delta_time);
|
||||
|
||||
// Dibuixa el rect negre a pantalla completa amb l'alpha actual.
|
||||
// No fa res si l'alpha és ~0 (estalvia el pushRect).
|
||||
void draw() const;
|
||||
|
||||
// Cert quan la fosa ha acabat (o no s'ha arrencat mai).
|
||||
[[nodiscard]] auto isDone() const -> bool;
|
||||
|
||||
// Alpha actual ∈ [0, 1].
|
||||
[[nodiscard]] auto alpha() const -> float;
|
||||
|
||||
private:
|
||||
Rendering::Renderer* renderer_;
|
||||
float from_{0.0F};
|
||||
float to_{0.0F};
|
||||
float duration_{0.0F};
|
||||
float elapsed_{0.0F};
|
||||
bool active_{false};
|
||||
};
|
||||
|
||||
} // namespace Graphics
|
||||
Reference in New Issue
Block a user