animacio de tancar el menu

This commit is contained in:
2026-04-16 20:14:35 +02:00
parent e0f9b60f22
commit 5956d874c3
4 changed files with 52 additions and 13 deletions

View File

@@ -44,6 +44,7 @@ namespace Menu {
// --- Animació ---
static constexpr float OPEN_SPEED = 8.0F; // 1.0 / 0.125s
static constexpr float CLOSE_SPEED = 10.0F; // 1.0 / 0.1s (una mica més ràpida que l'obertura)
static constexpr float HEIGHT_RATE = 12.0F; // smoothing exponencial de l'alçada (~150 ms al 90%)
// --- Items ---
@@ -92,6 +93,7 @@ namespace Menu {
static float animated_h_{0.0F}; // alçada actual animada (smoothing cap al target visible)
static Uint32 last_ticks_{0};
static SDL_Scancode* capturing_{nullptr}; // != null → esperant tecla per assignar
static bool closing_{false}; // true mentre l'animació de tancament és en curs
// --- Transició entre pàgines ---
static constexpr float TRANSITION_SPEED = 5.5F; // ~180 ms
@@ -354,36 +356,56 @@ namespace Menu {
font_ = std::make_unique<Text>("fonts/8bithud.fnt", "fonts/8bithud.gif");
stack_.clear();
open_anim_ = 0.0F;
closing_ = false;
last_ticks_ = SDL_GetTicks();
}
void destroy() {
font_.reset();
stack_.clear();
closing_ = false;
}
// "Actiu": accepta input. Durant l'animació de tancament la pila encara
// té pàgines però ja no ha de processar tecles.
auto isOpen() -> bool {
return !stack_.empty() && !closing_;
}
// "Visible": encara hi ha caixa per pintar (incloent close animation).
auto isVisible() -> bool {
return !stack_.empty();
}
void toggle() {
if (closing_ && !stack_.empty()) {
// Cancel·la el tancament en curs — continua l'animació cap a "obert"
// des del valor actual d'open_anim_.
closing_ = false;
last_ticks_ = SDL_GetTicks();
return;
}
if (isOpen()) {
close();
} else {
stack_.push_back(buildRoot());
open_anim_ = 0.0F;
closing_ = false;
animated_h_ = static_cast<float>(boxHeight(stack_.back()));
last_ticks_ = SDL_GetTicks();
}
}
// close() no buida la pila immediatament: marca closing_ i deixa que
// render() faça decréixer open_anim_ fins a 0. En aquell moment es neteja
// l'estat. Si es crida estant ja tancat o tancant-se, no-op.
void close() {
stack_.clear();
open_anim_ = 0.0F;
animated_h_ = 0.0F;
if (stack_.empty() || closing_) return;
closing_ = true;
capturing_ = nullptr;
transition_active_ = false;
transition_progress_ = 1.0F;
last_ticks_ = SDL_GetTicks();
}
auto isCapturing() -> bool {
@@ -556,13 +578,23 @@ namespace Menu {
}
void render(Uint32* pixel_data) {
if (!isOpen() || !font_ || !pixel_data) return;
if (!isVisible() || !font_ || !pixel_data) return;
// Delta time
Uint32 now = SDL_GetTicks();
float dt = static_cast<float>(now - last_ticks_) / 1000.0F;
last_ticks_ = now;
if (open_anim_ < 1.0F) {
if (closing_) {
open_anim_ -= CLOSE_SPEED * dt;
if (open_anim_ <= 0.0F) {
// Animació de tancament completada — buida l'estat de veritat.
open_anim_ = 0.0F;
stack_.clear();
animated_h_ = 0.0F;
closing_ = false;
return;
}
} else if (open_anim_ < 1.0F) {
open_anim_ += OPEN_SPEED * dt;
if (open_anim_ > 1.0F) open_anim_ = 1.0F;
}