animacio de tancar el menu
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,15 @@ namespace Menu {
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
// "Actiu": el menú accepta input. Fals durant l'animació de tancament.
|
||||
[[nodiscard]] auto isOpen() -> bool;
|
||||
// "Visible": hi ha una caixa pintada (incloent l'animació de tancament).
|
||||
// Overlay la usa per a decidir si cridar render().
|
||||
[[nodiscard]] auto isVisible() -> bool;
|
||||
void toggle();
|
||||
void close();
|
||||
|
||||
// Pinta el menú sobre el buffer ARGB — cridat des d'Overlay::render si està obert
|
||||
// Pinta el menú sobre el buffer ARGB — cridat des d'Overlay::render si està visible
|
||||
void render(Uint32* pixel_data);
|
||||
|
||||
// Gestió d'input — cridat des del Director en KEY_DOWN
|
||||
|
||||
@@ -361,8 +361,8 @@ namespace Overlay {
|
||||
std::remove_if(notifications_.begin(), notifications_.end(), [](const Notification& n) { return n.status == Status::FINISHED; }),
|
||||
notifications_.end());
|
||||
|
||||
// Menú flotant per damunt de tot
|
||||
if (Menu::isOpen()) {
|
||||
// Menú flotant per damunt de tot (isVisible inclou l'animació de tancament)
|
||||
if (Menu::isVisible()) {
|
||||
Menu::render(pixel_data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,11 +286,6 @@ void Director::handleEvent(const SDL_Event& event) {
|
||||
Gamepad::handleEvent(event);
|
||||
return;
|
||||
}
|
||||
// Salta els crèdits amb qualsevol tecla; no deixem que arribi al joc
|
||||
if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat && Overlay::creditsActive()) {
|
||||
Overlay::cancelCredits();
|
||||
return;
|
||||
}
|
||||
// Empassar-se el KEY_UP de qualsevol tecla que el menú va consumir en KEY_DOWN
|
||||
if (event.type == SDL_EVENT_KEY_UP && event.key.scancode >= 0 &&
|
||||
event.key.scancode < SDL_SCANCODE_COUNT && menu_keys_held_[event.key.scancode]) {
|
||||
@@ -340,6 +335,14 @@ void Director::handleEvent(const SDL_Event& event) {
|
||||
if (Menu::isOpen() && event.type == SDL_EVENT_KEY_UP) {
|
||||
return; // no deixem passar KEY_UP al joc tampoc
|
||||
}
|
||||
// Salta els crèdits amb qualsevol tecla que arribe al joc. Es fa DESPRÉS
|
||||
// del toggle del menú/pausa i del handling del menú obert — així F12 i
|
||||
// SELECT (gamepad) obrin el menú sense cancel·lar els crèdits, i la
|
||||
// navegació per dins del menú tampoc els anul·la.
|
||||
if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat && Overlay::creditsActive()) {
|
||||
Overlay::cancelCredits();
|
||||
return;
|
||||
}
|
||||
// Allibera el bloqueig d'ESC quan l'usuari la deixa anar
|
||||
if (event.type == SDL_EVENT_KEY_UP && event.key.scancode == SDL_SCANCODE_ESCAPE && esc_swallow_until_release_) {
|
||||
esc_swallow_until_release_ = false;
|
||||
|
||||
Reference in New Issue
Block a user