feat(game): pausa graduada amb easing i separador al HUD

This commit is contained in:
JailDesigner committed 2026-04-24 11:56:38 +02:00
1 parent 8aa4ec3daf
commit 5c70019eb5
9 files changed
+258 -61

No files matched your search

+47
View File
@@ -2,10 +2,13 @@
#include <iostream>
#include <string>
#include <string_view>
#include <unordered_map>
#include "core/resources/resource_helper.hpp"
#include "external/fkyaml_node.hpp"
#include "utils/defaults.hpp"
#include "utils/easing.hpp"
namespace {
@@ -30,6 +33,28 @@ namespace {
dst = static_cast<Uint8>(VALUE);
}
// Registre de corbes disponibles. Afegir-ne una nova és només una
// entrada ací: la llegeix `UiConfig::curveByName` i queda exposada al
// YAML pel seu nom. No hi ha fallback mut: si el nom no hi és, l'api
// retorna linear i avisa per stderr perquè l'error no passi en silenci.
auto curveRegistry() -> const std::unordered_map<std::string_view, UiConfig::CurveFn>& {
static const std::unordered_map<std::string_view, UiConfig::CurveFn> REGISTRY = {
{"linear", &Easing::linear},
{"outQuad", &Easing::outQuad},
{"inQuad", &Easing::inQuad},
{"inOutQuad", &Easing::inOutQuad},
{"outCubic", &Easing::outCubic},
{"inCubic", &Easing::inCubic},
};
return REGISTRY;
}
void readCurve(const fkyaml::node& node, const char* key, UiConfig::CurveFn& dst) {
if (!node.contains(key)) { return; }
const auto NAME = node[key].get_value<std::string>();
dst = UiConfig::curveByName(NAME);
}
void readFont(const fkyaml::node& node, const char* key, UiConfig::Font& dst) {
if (!node.contains(key)) { return; }
const auto& f = node[key];
@@ -65,6 +90,10 @@ UiConfig::UiConfig()
hud_entry_ms_(Defaults::UI::HUD_ENTRY_MS),
hud_flash_ms_(Defaults::UI::HUD_FLASH_MS),
hud_shake_ms_(Defaults::UI::HUD_SHAKE_MS),
pause_enter_ms_(Defaults::UI::PAUSE_ENTER_MS),
pause_exit_ms_(Defaults::UI::PAUSE_EXIT_MS),
pause_enter_curve_(curveByName(Defaults::UI::PAUSE_ENTER_CURVE)),
pause_exit_curve_(curveByName(Defaults::UI::PAUSE_EXIT_CURVE)),
hud_font_{.name = Defaults::UI::Font::HUD_NAME, .gif = Defaults::UI::Font::HUD_GIF, .fnt = Defaults::UI::Font::HUD_FNT, .kerning = Defaults::UI::Font::HUD_KERNING},
placeholder_font_{.name = Defaults::UI::Font::PLACEHOLDER_NAME, .gif = Defaults::UI::Font::PLACEHOLDER_GIF, .fnt = Defaults::UI::Font::PLACEHOLDER_FNT, .kerning = Defaults::UI::Font::PLACEHOLDER_KERNING},
menu_title_font_{.name = Defaults::UI::Font::MENU_TITLE_NAME, .gif = Defaults::UI::Font::MENU_TITLE_GIF, .fnt = Defaults::UI::Font::MENU_TITLE_FNT, .kerning = Defaults::UI::Font::MENU_TITLE_KERNING},
@@ -76,6 +105,16 @@ auto UiConfig::get() -> UiConfig& {
return instance_;
}
auto UiConfig::curveByName(const std::string& name) -> CurveFn {
const auto& reg = curveRegistry();
const auto IT = reg.find(name);
if (IT == reg.end()) {
std::cerr << "UiConfig: corba '" << name << "' desconeguda — s'usa linear\n";
return &Easing::linear;
}
return IT->second;
}
void UiConfig::load(const std::string& file_path) {
auto bytes = Resource::Helper::loadFile(file_path);
if (bytes.empty()) {
@@ -132,6 +171,14 @@ void UiConfig::load(const std::string& file_path) {
readField(h, "shake_ms", hud_shake_ms_);
}
if (yaml.contains("pause")) {
const auto& p = yaml["pause"];
readField(p, "enter_ms", pause_enter_ms_);
readField(p, "exit_ms", pause_exit_ms_);
readCurve(p, "enter_curve", pause_enter_curve_);
readCurve(p, "exit_curve", pause_exit_curve_);
}
std::cout << "UiConfig: carregat des de " << file_path << '\n';
} catch (const std::exception& e) {
std::cerr << "UiConfig: error parsejant " << file_path << ": " << e.what() << '\n';
+22
View File
@@ -49,12 +49,30 @@ class UiConfig {
[[nodiscard]] auto hudValue() const -> Uint8 { return hud_value_; }
[[nodiscard]] auto hudFlash() const -> Uint8 { return hud_flash_; }
// Signatura d'una funció d'easing: t ∈ [0, 1] → valor ∈ [0, 1].
// Permet triar corbes des de data/ui.yaml per nom (cadena) i guardar
// el punter a la corresponent funció de `utils/easing.hpp`.
using CurveFn = auto (*)(float) -> float;
// Timings (ms).
[[nodiscard]] auto notificationMs() const -> int { return notification_ms_; }
[[nodiscard]] auto exitMs() const -> int { return exit_ms_; }
[[nodiscard]] auto hudEntryMs() const -> int { return hud_entry_ms_; }
[[nodiscard]] auto hudFlashMs() const -> int { return hud_flash_ms_; }
[[nodiscard]] auto hudShakeMs() const -> int { return hud_shake_ms_; }
[[nodiscard]] auto pauseEnterMs() const -> int { return pause_enter_ms_; }
[[nodiscard]] auto pauseExitMs() const -> int { return pause_exit_ms_; }
// Corbes d'easing triades al YAML. Si el nom no és conegut, s'usa
// Easing::linear com a fallback.
[[nodiscard]] auto pauseEnterCurve() const -> CurveFn { return pause_enter_curve_; }
[[nodiscard]] auto pauseExitCurve() const -> CurveFn { return pause_exit_curve_; }
// Resol un nom de corba a la seua funció. Pública per permetre a
// futurs camps d'UI triar corbes pel mateix mecanisme (ex.: HUD
// entry, notifications slide...). Si el nom no està registrat,
// retorna Easing::linear i deixa un warning al log.
[[nodiscard]] static auto curveByName(const std::string& name) -> CurveFn;
// Fonts de UI.
[[nodiscard]] auto hudFont() const -> const Font& { return hud_font_; }
@@ -93,6 +111,10 @@ class UiConfig {
int hud_entry_ms_;
int hud_flash_ms_;
int hud_shake_ms_;
int pause_enter_ms_;
int pause_exit_ms_;
CurveFn pause_enter_curve_;
CurveFn pause_exit_curve_;
Font hud_font_;
Font placeholder_font_;