refactor(data): reorganitza data/ i centralitza paths a defaults.hpp
This commit is contained in:
1 parent
9949096fba
commit
05465b791e
54 files changed
+368
-304
No files matched your search
@@ -80,7 +80,7 @@ class Audio {
|
||||
// --- Control de sons ---
|
||||
void playSound(const std::string& name, Group group = Group::GAME); // Reproduir so puntual per nom (muta globals de Ja)
|
||||
void playSound(Ja::Sound* sound, Group group = Group::GAME); // Reproduir so puntual per punter (muta globals de Ja)
|
||||
// Reprodueix un so processat per un efecte definit a data/sounds.yaml
|
||||
// Reprodueix un so processat per un efecte definit a data/config/sounds.yaml
|
||||
// (preset_name busca a SoundEffectsConfig). Si el preset no existeix
|
||||
// o el motor està al cap de canals amb efecte, fa fallback a playSound
|
||||
// sec — l'usuari sent el so igualment, sense la cua.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "core/audio/jail_audio.hpp" // Per a Ja::EchoParams / Ja::ReverbParams
|
||||
|
||||
// Catàleg de presets d'efectes carregat des de data/sounds.yaml. La capa
|
||||
// Catàleg de presets d'efectes carregat des de data/config/sounds.yaml. La capa
|
||||
// Audio (playSoundWithEcho/playSoundWithReverb) hi accedeix per nom: si el
|
||||
// preset no existeix, el so es reprodueix sec amb un avís a stderr.
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace GlobalInputs {
|
||||
// La lliguem a la durada de la notificació EXIT perquè el missatge i
|
||||
// la confirmació expiren alhora — si no, l'usuari podria veure el
|
||||
// text però ja no ser dins del rang de confirmació (o al revés).
|
||||
// El valor concret viu a data/ui.yaml (timings.exit_ms) via UiConfig.
|
||||
// El valor concret viu a data/config/ui.yaml (timings.exit_ms) via UiConfig.
|
||||
constexpr int MIN_ZOOM = 1;
|
||||
constexpr int MAX_ZOOM = 6;
|
||||
|
||||
@@ -161,7 +161,7 @@ namespace GlobalInputs {
|
||||
// Debug helper: dispara una notificació prou llarga perquè
|
||||
// `wrapToWidth` la parteixi en (almenys) dues línies. Útil per a
|
||||
// verificar visualment el padding asimètric, el line_gap i la caixa
|
||||
// multilinia després de tocar la geometria a `data/ui.yaml`.
|
||||
// multilinia després de tocar la geometria a `data/config/ui.yaml`.
|
||||
void onDebugLongNotification() {
|
||||
Notification::notify("Notificació de prova llarga per a comprovar que el text es parteix correctament en dues línies dins la caixa.");
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
// Mapeig id → SDL_Scancode carregat des de data/input/keys.yaml. Consumit
|
||||
// Mapeig id → SDL_Scancode carregat des de data/config/input.yaml. Consumit
|
||||
// per GlobalInputs i (en el futur) per menús de remapat. No té cap cost
|
||||
// global: si la clau no existeix, retorna SDL_SCANCODE_UNKNOWN i GlobalInputs
|
||||
// ignora l'acció. D'aquesta manera podem afegir nous bindings al YAML sense
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
// Temes per a les notificacions de pantalla. Un "preset" captura els dos
|
||||
// colors (text i fons, índexs sobre la paleta "ui") i el temps de visibilitat
|
||||
// en mil·lisegons. Els valors concrets viuen a data/ui.yaml (carregat per
|
||||
// en mil·lisegons. Els valors concrets viuen a data/config/ui.yaml (carregat per
|
||||
// UiConfig); per llançar una notificació amb un preset concret, cridar
|
||||
// Notification::notify(text, preset). Sense preset s'usa el DEFAULT.
|
||||
namespace Notification {
|
||||
@@ -22,7 +22,7 @@ namespace Notification {
|
||||
|
||||
// Preset per defecte: text clar sobre fons fosc. Es construeix en cada
|
||||
// crida a partir d'UiConfig perquè els valors no són constexpr: viuen a
|
||||
// data/ui.yaml i es carreguen a l'arrencada.
|
||||
// data/config/ui.yaml i es carreguen a l'arrencada.
|
||||
[[nodiscard]] inline auto defaultPreset() -> Preset {
|
||||
return {
|
||||
.text_color = UiConfig::get().notificationText(),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <string_view>
|
||||
|
||||
#include "core/resources/resource_pack.hpp"
|
||||
#include "utils/defaults.hpp"
|
||||
|
||||
namespace Resource::Helper {
|
||||
|
||||
@@ -92,7 +93,7 @@ namespace Resource::Helper {
|
||||
// carpeta `data/`).
|
||||
const auto FROM_PACK = [&filepath]() -> std::vector<std::uint8_t> {
|
||||
if (!g_pack_loaded) { return {}; }
|
||||
constexpr std::string_view PREFIX = "data/";
|
||||
const std::string_view PREFIX{Defaults::Paths::DATA_ROOT};
|
||||
std::string key = filepath;
|
||||
if (key.starts_with(PREFIX)) { key.erase(0, PREFIX.size()); }
|
||||
if (g_pack.hasResource(key)) { return g_pack.getResource(key); }
|
||||
|
||||
@@ -118,22 +118,29 @@ Director::Director() {
|
||||
Locale::get().load(std::string(Defaults::I18n::LOCALE_DIR) + Options::locale() + ".yaml");
|
||||
|
||||
// Hotkeys globals. GlobalInputs::update() les consumirà a cada frame.
|
||||
KeyConfig::get().load("data/input/keys.yaml");
|
||||
KeyConfig::get().load(Defaults::Paths::INPUT_YAML);
|
||||
|
||||
// Tema d'UI (colors, timings, fonts, flags). Qualsevol clau absent a
|
||||
// data/ui.yaml cau al valor compilat a Defaults::UI.
|
||||
UiConfig::get().load("data/ui.yaml");
|
||||
// data/config/ui.yaml cau al valor compilat a Defaults::UI.
|
||||
UiConfig::get().load(Defaults::Paths::UI_YAML);
|
||||
// Configuració específica de les escenes TITLE i LOGO. Es carreguen
|
||||
// additivament sobre el mateix UiConfig: cada fitxer només conté la
|
||||
// seua subclau (`title:` o `logo:`), i les claus absents a la base
|
||||
// (ui.yaml) o als yamls d'escena cauen al valor compilat a
|
||||
// Defaults::UI::Title / Defaults::UI::Logo.
|
||||
UiConfig::get().load(Defaults::Paths::TITLE_YAML);
|
||||
UiConfig::get().load(Defaults::Paths::LOGO_YAML);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Tema visual de l'editor de tilemap (Debug-only). Claus absents
|
||||
// cauen als valors compilats a Defaults::Editor.
|
||||
EditorConfig::get().load("data/editor/editor.yaml");
|
||||
EditorConfig::get().load(Defaults::Paths::EDITOR_YAML);
|
||||
#endif
|
||||
|
||||
// Recursos compartits d'UI (paleta + fonts). Es carreguen abans que els
|
||||
// overlays perquè tots els reaprofiten sense duplicar la lògica. Els
|
||||
// noms de font viuen al fitxer data/ui.yaml via UiConfig.
|
||||
Resource::Cache::get().loadPalette("ui", "data/palettes/uzebox.pal");
|
||||
// noms de font viuen al fitxer data/config/ui.yaml via UiConfig.
|
||||
Resource::Cache::get().loadPalette("ui", Defaults::Paths::UI_PALETTE);
|
||||
const std::string HUD_FONT_GIF_KEY = UiConfig::get().hudFont().name + ".gif";
|
||||
Resource::Cache::get().loadSurface(HUD_FONT_GIF_KEY, UiConfig::get().hudFont().gif);
|
||||
Resource::Cache::get().getSurface(HUD_FONT_GIF_KEY)->setPalette(Resource::Cache::get().getPalette("ui"));
|
||||
@@ -152,33 +159,33 @@ Director::Director() {
|
||||
// Pistes de música del cicle de sala (intro/playing/outro). Es preloden
|
||||
// ací perquè formen part del preload d'assets, com la font i la paleta;
|
||||
// la lògica de quina sona en cada estat viu a `GameScene`.
|
||||
Resource::Cache::get().loadMusic("room_intro.ogg", "data/music/room_intro.ogg");
|
||||
Resource::Cache::get().loadMusic("playing.ogg", "data/music/playing.ogg");
|
||||
Resource::Cache::get().loadMusic("room_outro.ogg", "data/music/room_outro.ogg");
|
||||
Resource::Cache::get().loadMusic("room_intro.ogg", Defaults::Paths::MUSIC_ROOM_INTRO);
|
||||
Resource::Cache::get().loadMusic("playing.ogg", Defaults::Paths::MUSIC_PLAYING);
|
||||
Resource::Cache::get().loadMusic("room_outro.ogg", Defaults::Paths::MUSIC_ROOM_OUTRO);
|
||||
// Música de la TITLE: arrenca al constructor de l'escena i es fa
|
||||
// fade-out quan l'escena entra a STARTING.
|
||||
Resource::Cache::get().loadMusic("title.ogg", "data/music/title.ogg");
|
||||
Resource::Cache::get().loadMusic("title.ogg", Defaults::Paths::MUSIC_TITLE);
|
||||
|
||||
// Sons del menú de servei. Els noms venen de `data/ui.yaml` (amb
|
||||
// Sons del menú de servei. Els noms venen de `data/config/ui.yaml` (amb
|
||||
// fallback a `Defaults::UI::MENU_*_SOUND`); el ServiceMenu els
|
||||
// dispara via Audio::Group::INTERFACE.
|
||||
const auto& menu_select = UiConfig::get().menuSelectSound();
|
||||
const auto& menu_accept = UiConfig::get().menuAcceptSound();
|
||||
Resource::Cache::get().loadSound(menu_select, "data/sounds/" + menu_select);
|
||||
Resource::Cache::get().loadSound(menu_accept, "data/sounds/" + menu_accept);
|
||||
Resource::Cache::get().loadSound(menu_select, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + menu_select);
|
||||
Resource::Cache::get().loadSound(menu_accept, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + menu_accept);
|
||||
// So del START a la TITLE: el dispara TitleScene quan un jugador
|
||||
// prem START (vore enterStarting i el reset del segon jugador).
|
||||
const auto& player_start = UiConfig::get().playerStartSound();
|
||||
Resource::Cache::get().loadSound(player_start, "data/sounds/" + player_start);
|
||||
Resource::Cache::get().loadSound(player_start, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + player_start);
|
||||
// Soroll de LogoScene (scanline reveal). El dispara LogoScene al
|
||||
// ctor; amb fallback al nom de Defaults si la clau YAML no hi és.
|
||||
const auto& logo_glitch = UiConfig::get().logoGlitchSound();
|
||||
Resource::Cache::get().loadSound(logo_glitch, "data/sounds/" + logo_glitch);
|
||||
Resource::Cache::get().loadSound(logo_glitch, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + logo_glitch);
|
||||
|
||||
// Catàleg de presets d'efectes per als sons. Es carrega abans d'Audio
|
||||
// perquè els primers playSoundWith* (al començament del joc) ja
|
||||
// troben els presets disponibles.
|
||||
SoundEffectsConfig::get().load("data/sounds.yaml");
|
||||
SoundEffectsConfig::get().load(Defaults::Paths::SOUNDS_YAML);
|
||||
|
||||
// Audio: singleton manual propietari d'un SDL audio device. Es destrueix
|
||||
// explícitament a ~Director abans que Resource::Cache (Meyers) buide els
|
||||
@@ -216,7 +223,7 @@ Director::Director() {
|
||||
|
||||
// Font del menú de servei (F9). El títol va amb la variant `display`
|
||||
// i els items amb `condensed-display` (més compacte perquè caben més
|
||||
// files). Els dos noms i kernings viuen a data/ui.yaml via UiConfig.
|
||||
// files). Els dos noms i kernings viuen a data/config/ui.yaml via UiConfig.
|
||||
auto load_menu_font = [&](const UiConfig::Font& font) {
|
||||
const std::string KEY = font.name + ".gif";
|
||||
Resource::Cache::get().loadSurface(KEY, font.gif);
|
||||
@@ -233,7 +240,7 @@ Director::Director() {
|
||||
// sobreescrivim amb la "ui" perquè el GIF ja porta els colors finals
|
||||
// del logo).
|
||||
constexpr const char* MINI_LOGO_KEY = "logo_jailgames_mini.gif";
|
||||
Resource::Cache::get().loadSurface(MINI_LOGO_KEY, "data/logo/logo_jailgames_mini.gif");
|
||||
Resource::Cache::get().loadSurface(MINI_LOGO_KEY, Defaults::Paths::LOGO_MINI_GIF);
|
||||
auto mini_logo_surface = Resource::Cache::get().getSurface(MINI_LOGO_KEY);
|
||||
mini_logo_surface_ = mini_logo_surface;
|
||||
|
||||
@@ -241,20 +248,20 @@ Director::Director() {
|
||||
// conserva la seua paleta nadiua: els colors finals del logo viuen
|
||||
// dins del propi GIF i no han de passar per la paleta UI.
|
||||
constexpr const char* LOGO_FULL_KEY = "logo_jailgames.gif";
|
||||
Resource::Cache::get().loadSurface(LOGO_FULL_KEY, "data/logo/logo_jailgames.gif");
|
||||
Resource::Cache::get().loadSurface(LOGO_FULL_KEY, Defaults::Paths::LOGO_FULL_GIF);
|
||||
logo_full_surface_ = Resource::Cache::get().getSurface(LOGO_FULL_KEY);
|
||||
|
||||
// Logotip del joc per a la TITLE (substitueix el text "Aventures en
|
||||
// Egipte ARCADE"). Igual que la resta de logos, paleta nadiua —
|
||||
// l'art ja porta els colors finals i no passa per la UI.
|
||||
constexpr const char* GAME_LOGO_KEY = "game_logo.gif";
|
||||
Resource::Cache::get().loadSurface(GAME_LOGO_KEY, "data/title/game_logo.gif");
|
||||
Resource::Cache::get().loadSurface(GAME_LOGO_KEY, Defaults::Paths::TITLE_GAME_LOGO_GIF);
|
||||
game_logo_surface_ = Resource::Cache::get().getSurface(GAME_LOGO_KEY);
|
||||
|
||||
// Fons sencer de la TITLE (320×240). Igual que el minilogo, conserva
|
||||
// la seua paleta nadiua perquè el GIF ja porta els colors finals.
|
||||
constexpr const char* TITLE_BG_KEY = "title_bg.gif";
|
||||
Resource::Cache::get().loadSurface(TITLE_BG_KEY, "data/title/title_bg.gif");
|
||||
Resource::Cache::get().loadSurface(TITLE_BG_KEY, Defaults::Paths::TITLE_BG_GIF);
|
||||
auto title_bg_surface = Resource::Cache::get().getSurface(TITLE_BG_KEY);
|
||||
title_bg_surface_ = title_bg_surface;
|
||||
ServiceMenu::get().init(menu_title_text, menu_items_text, ui_palette);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
// Configuració del tema UI (índexs de paleta, timings, fonts i flags)
|
||||
// carregada des de data/ui.yaml. Cada camp s'inicialitza amb el valor
|
||||
// carregada des de data/config/ui.yaml. Cada camp s'inicialitza amb el valor
|
||||
// de Defaults::UI com a fallback: si el fitxer falta o li manca una
|
||||
// clau, el joc s'executa amb el tema compilat.
|
||||
//
|
||||
@@ -21,12 +21,12 @@ class UiConfig {
|
||||
};
|
||||
|
||||
// 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
|
||||
// Permet triar corbes des de data/config/ui.yaml per nom (cadena) i guardar
|
||||
// el punter a la corresponent funció de `utils/easing.hpp`.
|
||||
using CurveFn = auto (*)(float) -> float;
|
||||
|
||||
// Geometria del Notifier (popup superior). Carregada des de
|
||||
// data/ui.yaml secció `notifier:`; els valors per defecte vénen de
|
||||
// data/config/ui.yaml secció `notifier:`; els valors per defecte vénen de
|
||||
// Defaults::UI::Notifier. El moviment és per temps (slide_ms) i no per
|
||||
// velocitat, perquè una caixa més gran no triga més a entrar/eixir.
|
||||
struct Notifier {
|
||||
@@ -170,7 +170,7 @@ class UiConfig {
|
||||
[[nodiscard]] static auto curveByName(const std::string& name) -> CurveFn;
|
||||
|
||||
// Sons del menú de servei. Claus de Resource::Cache::loadSound (els
|
||||
// fitxers viuen a `data/sounds/`).
|
||||
// fitxers viuen a `data/audio/sounds/`).
|
||||
[[nodiscard]] auto menuSelectSound() const -> const std::string& { return menu_select_sound_; }
|
||||
[[nodiscard]] auto menuAcceptSound() const -> const std::string& { return menu_accept_sound_; }
|
||||
[[nodiscard]] auto playerStartSound() const -> const std::string& { return player_start_sound_; }
|
||||
|
||||
@@ -234,7 +234,7 @@ void Editor::ensureEditableEntities() {
|
||||
// llança si no troba — provem primer i, en cas de miss, carreguem.
|
||||
const auto REL = sp["path"].get_value<std::string>();
|
||||
const std::string KEY = std::filesystem::path(REL).filename().string();
|
||||
std::string full = "data/entities/";
|
||||
std::string full = Defaults::Paths::ENTITIES_DIR;
|
||||
full += name;
|
||||
full += '/';
|
||||
full += REL;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
|
||||
// Configuració visual de l'editor de tilemap (Debug-only). Carregada des
|
||||
// de data/editor/editor.yaml; les claus absents cauen als valors compilats
|
||||
// de data/config/editor.yaml; les claus absents cauen als valors compilats
|
||||
// a Defaults::Editor. Mateix patró que UiConfig (Meyers singleton + load).
|
||||
class EditorConfig {
|
||||
public:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "game/entities/entity.hpp"
|
||||
#include "game/entities/entity_factory.hpp"
|
||||
#include "utils/defaults.hpp"
|
||||
|
||||
namespace EntityLoader {
|
||||
|
||||
@@ -20,7 +21,7 @@ namespace EntityLoader {
|
||||
}
|
||||
|
||||
auto templatePath(const std::string& name) -> std::string {
|
||||
return "data/entities/" + name + "/" + name + ".yaml";
|
||||
return std::string{Defaults::Paths::ENTITIES_DIR} + name + "/" + name + ".yaml";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "game/entities/entity_manager.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
#include "game/map/map.hpp"
|
||||
#include "utils/defaults.hpp"
|
||||
|
||||
// Render centralitzat al manager per confinar la dependència cap a
|
||||
// `Surface`. Les entitats exposen `getSurface()` + `getPixelRect()` i el
|
||||
@@ -124,7 +125,7 @@ namespace {
|
||||
if (s.contains("path")) {
|
||||
const auto REL = s["path"].get_value<std::string>();
|
||||
info.key = std::filesystem::path(REL).filename().string();
|
||||
info.full_path = "data/entities/" + type + "/" + REL;
|
||||
info.full_path = std::string{Defaults::Paths::ENTITIES_DIR} + type + "/" + REL;
|
||||
info.valid = true;
|
||||
}
|
||||
if (s.contains("size")) {
|
||||
|
||||
@@ -179,16 +179,16 @@ void Player::readJumpBlock(const fkyaml::node& yaml) {
|
||||
if (j.contains("gravity")) { jump_config.gravity_px_per_s2 = j["gravity"].get_value<float>(); }
|
||||
if (j.contains("landing_stun_ms")) { jump_config.landing_stun_ms = j["landing_stun_ms"].get_value<int>(); }
|
||||
if (j.contains("shadow_y_offset")) { jump_config.shadow_y_offset = j["shadow_y_offset"].get_value<int>(); }
|
||||
// Sons opcionals: el nom del fitxer (relatiu a data/sounds/) val tant
|
||||
// de clau al Resource::Cache com de basename per a la càrrega. Si el
|
||||
// camp manca, la clau queda buida i `playSound` no es crida.
|
||||
// Sons opcionals: el nom del fitxer (relatiu a Defaults::Paths::AUDIO_SOUNDS_DIR)
|
||||
// val tant de clau al Resource::Cache com de basename per a la càrrega.
|
||||
// Si el camp manca, la clau queda buida i `playSound` no es crida.
|
||||
if (j.contains("sound")) {
|
||||
jump_config.sound_key = j["sound"].get_value<std::string>();
|
||||
Resource::Cache::get().loadSound(jump_config.sound_key, "data/sounds/" + jump_config.sound_key);
|
||||
Resource::Cache::get().loadSound(jump_config.sound_key, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + jump_config.sound_key);
|
||||
}
|
||||
if (j.contains("land_sound")) {
|
||||
jump_config.land_sound_key = j["land_sound"].get_value<std::string>();
|
||||
Resource::Cache::get().loadSound(jump_config.land_sound_key, "data/sounds/" + jump_config.land_sound_key);
|
||||
Resource::Cache::get().loadSound(jump_config.land_sound_key, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + jump_config.land_sound_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ void Player::readHurtBlock(const fkyaml::node& yaml) {
|
||||
// So d'entrada a HURT — mateix patró que `jump.sound` i `whip.sound`.
|
||||
if (h.contains("sound")) {
|
||||
hurt_config.sound_key = h["sound"].get_value<std::string>();
|
||||
Resource::Cache::get().loadSound(hurt_config.sound_key, "data/sounds/" + hurt_config.sound_key);
|
||||
Resource::Cache::get().loadSound(hurt_config.sound_key, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + hurt_config.sound_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,10 +220,11 @@ void Player::readImmunityBlock(const fkyaml::node& yaml) {
|
||||
if (im.contains("duration_ms")) { immunity_config.duration_ms = im["duration_ms"].get_value<float>(); }
|
||||
if (im.contains("blink_period_ms")) { immunity_config.blink_period_ms = im["blink_period_ms"].get_value<int>(); }
|
||||
// Paleta del blink: el basename val tant de clau al Resource::Cache
|
||||
// com de path (`data/player/<key>.pal`). Mateix patró que els sons.
|
||||
// com de path (`Defaults::Paths::PLAYER_DIR + key + .pal`). Mateix patró
|
||||
// que els sons.
|
||||
if (im.contains("palette")) {
|
||||
immunity_config.palette_key = im["palette"].get_value<std::string>();
|
||||
Resource::Cache::get().loadPalette(immunity_config.palette_key, "data/player/" + immunity_config.palette_key + ".pal");
|
||||
Resource::Cache::get().loadPalette(immunity_config.palette_key, std::string{Defaults::Paths::PLAYER_DIR} + immunity_config.palette_key + ".pal");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +240,7 @@ void Player::readWhipBlock(const fkyaml::node& yaml) {
|
||||
// clau al cache i de path. Si manca, queda buit i no es dispara.
|
||||
if (w.contains("sound")) {
|
||||
whip_config.sound_key = w["sound"].get_value<std::string>();
|
||||
Resource::Cache::get().loadSound(whip_config.sound_key, "data/sounds/" + whip_config.sound_key);
|
||||
Resource::Cache::get().loadSound(whip_config.sound_key, std::string{Defaults::Paths::AUDIO_SOUNDS_DIR} + whip_config.sound_key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class Player : public AnimatedSprite {
|
||||
DYING,
|
||||
};
|
||||
|
||||
// Geometria carregada des del YAML del player (p.ex. `data/player/sam.yaml`).
|
||||
// Geometria carregada des del YAML del player (p.ex. `data/entities/player/sam.yaml`).
|
||||
// `sprite_*` són
|
||||
// la mida del frame (sprite 12×24 amb perspectiva falsa: visualment, els
|
||||
// 12 píxels superiors són el cap i els 12 inferiors la base).
|
||||
@@ -362,7 +362,7 @@ class Player : public AnimatedSprite {
|
||||
// al respawn post-mort: mateixa entrada cinemàtica.
|
||||
void spawnFromAir(float x, float y);
|
||||
|
||||
// Arma un preset de reverb (catàleg a `data/sounds.yaml`) per al
|
||||
// Arma un preset de reverb (catàleg a `data/config/sounds.yaml`) per al
|
||||
// pròxim aterratge d'aquest jugador. Pensat per a la cinemàtica
|
||||
// d'INTRO de sala: GameScene crida aquesta funció just després de
|
||||
// `spawnFromAir`, i el primer LAND consumeix el preset (queda buit
|
||||
@@ -529,7 +529,7 @@ class Player : public AnimatedSprite {
|
||||
// gestiona `intended_vx_/vy_` escalats pel resolver.
|
||||
bool being_pushed_{false};
|
||||
|
||||
// Preset de reverb (catàleg de `data/sounds.yaml`) que el pròxim
|
||||
// Preset de reverb (catàleg de `data/config/sounds.yaml`) que el pròxim
|
||||
// LAND ha de fer servir; buit = so sec. L'arma `armNextLandReverb`
|
||||
// (cridada per GameScene al spawn aeri d'INTRO) i el consumeix
|
||||
// `integrateJump` quan el jugador toca terra. Cap altre punt
|
||||
@@ -636,7 +636,7 @@ class Player : public AnimatedSprite {
|
||||
struct HurtConfig {
|
||||
float initial_speed_px_per_s{0.0F}; // Velocitat amb què surt projectat (px/s).
|
||||
int brake_time_ms{0}; // Temps en que la velocitat decau a 0.
|
||||
// Fitxer .wav reproduït en entrar a HURT (relatiu a `data/sounds/`).
|
||||
// Fitxer .wav reproduït en entrar a HURT (relatiu a `data/audio/sounds/`).
|
||||
// Mateixa convenció que la resta de sons del jugador: el basename val
|
||||
// de clau al Resource::Cache i de path. Buit o absent = entrada
|
||||
// silenciosa.
|
||||
@@ -660,7 +660,7 @@ class Player : public AnimatedSprite {
|
||||
int cooldown_ms{0};
|
||||
int damage{0};
|
||||
// Fitxer .wav reproduït al moment de disparar el swing (relatiu a
|
||||
// `data/sounds/`). Convenció: el basename val tant de clau al
|
||||
// `data/audio/sounds/`). Convenció: el basename val tant de clau al
|
||||
// Resource::Cache com de path. Buit o absent = swing silenciós.
|
||||
std::string sound_key;
|
||||
};
|
||||
@@ -697,7 +697,7 @@ class Player : public AnimatedSprite {
|
||||
float duration_ms{0.0F};
|
||||
int blink_period_ms{0};
|
||||
// Clau al Resource::Cache de la paleta plana usada al blink (basename
|
||||
// del .pal a `data/player/`). Buida = no hi ha alternança visual,
|
||||
// del .pal a `data/entities/player/`). Buida = no hi ha alternança visual,
|
||||
// només la finestra lògica d'immunitat (que sense feedback visual
|
||||
// pot ser confusa, però no és incorrecte).
|
||||
std::string palette_key;
|
||||
@@ -706,7 +706,7 @@ class Player : public AnimatedSprite {
|
||||
|
||||
// Llig el bloc `immunity:` del YAML i n'omple `immunity_config`. Si
|
||||
// hi ha `palette`, registra la paleta corresponent al Resource::Cache
|
||||
// (path: `data/player/<palette_key>.pal`). Mateix patró que els altres
|
||||
// (path: `data/entities/player/<palette_key>.pal`). Mateix patró que els altres
|
||||
// readers — `loadFrom` el crida al final.
|
||||
static void readImmunityBlock(const fkyaml::node& yaml);
|
||||
|
||||
|
||||
@@ -229,10 +229,10 @@ auto GameScene::defaultConfig() -> Config {
|
||||
// concret de sala — només cap a on apunta la progressió ara mateix.
|
||||
return {
|
||||
.map_yaml = Levels::LevelManager::get().currentPath(),
|
||||
.player_sprite = Defaults::Pyramid::PLAYER_SPRITE,
|
||||
.player_yaml = Defaults::Pyramid::PLAYER_YAML,
|
||||
.player2_sprite = Defaults::Pyramid::PLAYER_SPRITE_P2,
|
||||
.player2_yaml = Defaults::Pyramid::PLAYER_YAML_P2,
|
||||
.player_sprite = Defaults::Pyramid::PLAYER_SAM_GIF,
|
||||
.player_yaml = Defaults::Pyramid::PLAYER_SAM_YAML,
|
||||
.player2_sprite = Defaults::Pyramid::PLAYER_MORCUS_GIF,
|
||||
.player2_yaml = Defaults::Pyramid::PLAYER_MORCUS_YAML,
|
||||
.music_track = Defaults::Pyramid::MUSIC_TRACK,
|
||||
.starting_players = DebugConfig::StartingPlayers::BOTH,
|
||||
};
|
||||
@@ -312,7 +312,7 @@ GameScene::GameScene(Config config)
|
||||
// També ens subscrivim a `player_jumped` i `player_landed` per
|
||||
// spawnejar el polvet de despegue / aterratge a la posició dels
|
||||
// peus que el Player ens dóna al payload.
|
||||
Resource::Cache::get().loadSurface("dust.gif", "data/entities/dust/dust.gif");
|
||||
Resource::Cache::get().loadSurface("dust.gif", Defaults::Paths::DUST_GIF);
|
||||
entity_manager_.getBus().subscribe("player_jumped", [this](const Event& ev) {
|
||||
const auto* pos = std::get_if<WorldPos>(&ev.payload);
|
||||
if (pos != nullptr) { spawnDust(pos->x, pos->y, false); }
|
||||
@@ -325,10 +325,10 @@ GameScene::GameScene(Config config)
|
||||
// Whip: precarreguem les 4 surfaces (una per cardinal) abans del
|
||||
// primer spawn perquè el Player no facte disc al primer atac.
|
||||
// Subscriu `whip_spawn` per crear el `WhipAttack` corresponent.
|
||||
Resource::Cache::get().loadSurface("whip_east.gif", "data/entities/whip_attack/whip_east.gif");
|
||||
Resource::Cache::get().loadSurface("whip_west.gif", "data/entities/whip_attack/whip_west.gif");
|
||||
Resource::Cache::get().loadSurface("whip_north.gif", "data/entities/whip_attack/whip_north.gif");
|
||||
Resource::Cache::get().loadSurface("whip_south.gif", "data/entities/whip_attack/whip_south.gif");
|
||||
Resource::Cache::get().loadSurface("whip_east.gif", Defaults::Paths::WHIP_EAST_GIF);
|
||||
Resource::Cache::get().loadSurface("whip_west.gif", Defaults::Paths::WHIP_WEST_GIF);
|
||||
Resource::Cache::get().loadSurface("whip_north.gif", Defaults::Paths::WHIP_NORTH_GIF);
|
||||
Resource::Cache::get().loadSurface("whip_south.gif", Defaults::Paths::WHIP_SOUTH_GIF);
|
||||
entity_manager_.getBus().subscribe("whip_spawn", [this](const Event& ev) {
|
||||
const auto* p = std::get_if<WhipSpawnPayload>(&ev.payload);
|
||||
if (p != nullptr) { spawnWhip(*p); }
|
||||
@@ -479,7 +479,7 @@ GameScene::GameScene(Config config)
|
||||
|
||||
// Timings i corbes de la FSM de sala. Llegits del YAML una sola
|
||||
// vegada; canvis requereixen reiniciar el joc.
|
||||
transition_config_ = RoomFsm::loadConfig(Defaults::GameScene::CONFIG_YAML);
|
||||
transition_config_ = RoomFsm::loadConfig(Defaults::GameScene::GAME_YAML);
|
||||
|
||||
// Cinemàtica d'entrada de la primera sala: arrenca la pista
|
||||
// `room_intro.ogg` i arma el callback de fi que farà spawn + salt
|
||||
@@ -856,7 +856,7 @@ void GameScene::renderRoomText() {
|
||||
// l'antic GameCanvas::CENTER_Y per descomptar la franja del marcador
|
||||
// i tenir el rètol equilibrat sobre el playfield.
|
||||
const int PLAY_CENTER_Y = (GameCanvas::HEIGHT + Map::hud_h) / 2;
|
||||
// Colors del rètol via UiConfig (`data/ui.yaml > colors.room_text` i
|
||||
// Colors del rètol via UiConfig (`data/config/ui.yaml > colors.room_text` i
|
||||
// `room_text_outline`). Independents dels colors de notificació.
|
||||
const Uint8 FILL = UiConfig::get().roomText();
|
||||
const Uint8 OUTLINE = UiConfig::get().roomTextOutline();
|
||||
|
||||
@@ -202,7 +202,7 @@ class GameScene : public Scene {
|
||||
// Font del rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO).
|
||||
// Distinta de `pause_font_` perquè el rètol de fase té estètica
|
||||
// pròpia (CaesarDressing per defecte, configurable via
|
||||
// `data/ui.yaml > fonts.room_text`). La pausa segueix amb la
|
||||
// `data/config/ui.yaml > fonts.room_text`). La pausa segueix amb la
|
||||
// placeholder.
|
||||
std::shared_ptr<Text> room_text_font_;
|
||||
|
||||
@@ -224,7 +224,7 @@ class GameScene : public Scene {
|
||||
} pause_;
|
||||
|
||||
// Configuració de la FSM de sala (intro/outro). Carregada al ctor des
|
||||
// de `data/scenes/game.yaml`; valors per defecte si manca el YAML.
|
||||
// de `data/scenes/game/game.yaml`; valors per defecte si manca el YAML.
|
||||
RoomFsm::Config transition_config_{};
|
||||
|
||||
// Estat actual de la FSM de sala. S'inicialitza a ROOM_INTRO al ctor
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace Placeholder {
|
||||
|
||||
// Retorna true si el scancode coincideix amb alguna tecla declarada al
|
||||
// KeyConfig::get() (les carregades de data/input/keys.yaml). Si KeyConfig
|
||||
// KeyConfig::get() (les carregades de data/config/input.yaml). Si KeyConfig
|
||||
// no s'ha carregat, totes les consultes retornaran SDL_SCANCODE_UNKNOWN i
|
||||
// aquesta funció tornarà false, de manera que el test/smoke no depèn de
|
||||
// l'estat global de la configuració.
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace RoomFsm {
|
||||
int elapsed_ms{0};
|
||||
};
|
||||
|
||||
// Timings i corbes carregats de `data/scenes/game.yaml`. Els valors
|
||||
// Timings i corbes carregats de `data/scenes/game/game.yaml`. Els valors
|
||||
// per defecte coincideixen amb els del YAML versionat: si manca el
|
||||
// fitxer, la FSM funciona igualment amb aquests fallbacks.
|
||||
struct Config {
|
||||
@@ -94,7 +94,7 @@ namespace RoomFsm {
|
||||
UiConfig::CurveFn text_enter_curve{nullptr};
|
||||
UiConfig::CurveFn text_exit_curve{nullptr};
|
||||
|
||||
// Preset de reverb (catàleg a `data/sounds.yaml`) que GameScene
|
||||
// Preset de reverb (catàleg a `data/config/sounds.yaml`) que GameScene
|
||||
// arma al jugador al spawn aeri d'INTRO. Es consumeix al primer
|
||||
// aterratge cinemàtic; els salts posteriors del joc i els
|
||||
// respawns post-mort cauen al so sec. Buit = sense reverb (la
|
||||
|
||||
@@ -17,7 +17,7 @@ class Text;
|
||||
// Escena TITLE provisional. Pinta dos blocs de text sobre un fons gairebé
|
||||
// negre i un prompt "press start" intermitent fins que apareix l'artwork
|
||||
// real. Tota la cosmètica (colors, durada, ritme del parpadeig) viu a
|
||||
// data/ui.yaml secció `title:` per poder afinar-la sense recompilar.
|
||||
// data/config/ui.yaml secció `title:` per poder afinar-la sense recompilar.
|
||||
class TitleScene : public Scene {
|
||||
public:
|
||||
// Fases de l'escena.
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
// Els colors del HUD viuen a data/ui.yaml (colors.hud_label/value/flash)
|
||||
// Els colors del HUD viuen a data/config/ui.yaml (colors.hud_label/value/flash)
|
||||
// via UiConfig. Les etiquetes ("P1", "V", "T") usen un to apagat per
|
||||
// crear jerarquia visual respecte als valors; el flash temporal usa un
|
||||
// to càlid que contrasta amb el valor normal.
|
||||
@@ -73,7 +73,7 @@ Hud::Hud(EventBus& bus, std::shared_ptr<Text> font)
|
||||
: bus_(bus),
|
||||
font_(std::move(font)) {
|
||||
// Geometria fixa dels tres blocs. Sumen exactament GameCanvas::WIDTH.
|
||||
// La durada de l'animació d'entrada ve de data/ui.yaml via UiConfig.
|
||||
// La durada de l'animació d'entrada ve de data/config/ui.yaml via UiConfig.
|
||||
const int ENTRY_MS = UiConfig::get().hudEntryMs();
|
||||
blocks_[0] = Block{
|
||||
.x = 0,
|
||||
|
||||
@@ -104,7 +104,7 @@ class Hud {
|
||||
|
||||
// Animació d'entrada: ms restants fins a quedar-se a la posició
|
||||
// final. Quan val 0 el bloc està quiet. El Hud ctor l'inicialitza
|
||||
// amb la durada viva a data/ui.yaml (hud.entry_ms).
|
||||
// amb la durada viva a data/config/ui.yaml (hud.entry_ms).
|
||||
int entry_ms_left{0};
|
||||
// Vector inicial des d'on entra: {-LEFT_W,0} per al bloc esquerre,
|
||||
// {0,-HEIGHT_PX} per al central i {+RIGHT_W,0} per al dret.
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Defaults {
|
||||
} // namespace Player
|
||||
|
||||
// Fallbacks del tema d'UI: índexs de paleta, timings (ms) i fonts.
|
||||
// El tema en viu és a data/ui.yaml, carregat per UiConfig a
|
||||
// El tema en viu és a data/config/ui.yaml, carregat per UiConfig a
|
||||
// l'arrencada; aquests valors només s'apliquen si el fitxer falta o
|
||||
// li manca alguna clau. Ací només cal tocar-los si es vol canviar el
|
||||
// fallback "de fàbrica".
|
||||
@@ -251,14 +251,14 @@ namespace Defaults {
|
||||
|
||||
// Sons del menú de servei. SELECT acompanya navegació (amunt/avall)
|
||||
// i back; ACCEPT acompanya modificació d'opció (esq/dret/retorn).
|
||||
// Els fitxers viuen a `data/sounds/`; només es referencia el nom.
|
||||
// Els fitxers viuen a `data/audio/sounds/`; només es referencia el nom.
|
||||
constexpr const char* MENU_SELECT_SOUND = "menu_select.wav";
|
||||
constexpr const char* MENU_ACCEPT_SOUND = "menu_accept.wav";
|
||||
|
||||
// So disparat quan un jugador prem START a la TITLE (tant la
|
||||
// primera pulsació que entra a STARTING com la del segon
|
||||
// jugador que reseteja a BOTH dins de la finestra). Fitxer a
|
||||
// `data/sounds/`.
|
||||
// `data/audio/sounds/`.
|
||||
constexpr const char* PLAYER_START_SOUND = "player_start.wav";
|
||||
|
||||
// So curt de "soroll/scratch" disparat al constructor de LogoScene
|
||||
@@ -447,7 +447,7 @@ namespace Defaults {
|
||||
// Independent de la piràmide concreta — quan un dia hi haja diferents
|
||||
// ritmes per piràmide, aquest YAML pot adoptar variants per nivell.
|
||||
namespace GameScene {
|
||||
constexpr const char* CONFIG_YAML = "data/scenes/game.yaml";
|
||||
constexpr const char* GAME_YAML = "data/scenes/game/game.yaml";
|
||||
} // namespace GameScene
|
||||
|
||||
// Rutes d'assets per piràmide. Centralitzats ací perquè `GameScene` no
|
||||
@@ -460,14 +460,67 @@ namespace Defaults {
|
||||
// hardcodejar el path d'una sala concreta — pregunteu-li al
|
||||
// `LevelManager` (`currentPath()`) i deixeu que ell decidisca.
|
||||
constexpr const char* LEVELS_YAML = "data/maps/levels.yaml";
|
||||
constexpr const char* PLAYER_SPRITE = "data/player/sam.gif";
|
||||
constexpr const char* PLAYER_YAML = "data/player/sam.yaml";
|
||||
constexpr const char* PLAYER_SAM_GIF = "data/entities/player/sam.gif";
|
||||
constexpr const char* PLAYER_SAM_YAML = "data/entities/player/sam.yaml";
|
||||
// Personatge del segon jugador. Clonat de sam amb repaletat (roig→blau);
|
||||
// la geometria del sprite i les animacions coincideixen amb les de P1,
|
||||
// així que Player::loadFrom només cal cridar-la amb un dels dos YAMLs.
|
||||
constexpr const char* PLAYER_SPRITE_P2 = "data/player/morcus.gif";
|
||||
constexpr const char* PLAYER_YAML_P2 = "data/player/morcus.yaml";
|
||||
constexpr const char* PLAYER_MORCUS_GIF = "data/entities/player/morcus.gif";
|
||||
constexpr const char* PLAYER_MORCUS_YAML = "data/entities/player/morcus.yaml";
|
||||
constexpr const char* MUSIC_TRACK = "playing.ogg";
|
||||
} // namespace Pyramid
|
||||
|
||||
// Rutes a recursos sota `data/`. Centralitzades ací perquè cap `.cpp`
|
||||
// tinga literals "data/..." hardcoded: si demà es reorganitza
|
||||
// l'arbre de `data/`, només cal tocar aquest namespace.
|
||||
//
|
||||
// Convenció: les constants que acaben en `_DIR` són prefixos (acaben
|
||||
// en `/`) pensats per concatenar amb una clau coneguda en runtime
|
||||
// (p.ex. nom de fitxer carregat des d'un YAML). La resta són rutes
|
||||
// completes a un fitxer concret.
|
||||
namespace Paths {
|
||||
// Arrel de tots els recursos del joc. La fan servir el carregador de
|
||||
// packs (per a stripping al lookup) i qualsevol consumidor que
|
||||
// necessite saber la prefix lògica abans del path real.
|
||||
constexpr const char* DATA_ROOT = "data/";
|
||||
|
||||
// Directoris (per concatenació amb claus dinàmiques).
|
||||
constexpr const char* AUDIO_MUSIC_DIR = "data/audio/music/";
|
||||
constexpr const char* AUDIO_SOUNDS_DIR = "data/audio/sounds/";
|
||||
constexpr const char* ENTITIES_DIR = "data/entities/";
|
||||
constexpr const char* PLAYER_DIR = "data/entities/player/";
|
||||
|
||||
// Configuració global (tema, sons, input, editor).
|
||||
constexpr const char* UI_YAML = "data/config/ui.yaml";
|
||||
constexpr const char* SOUNDS_YAML = "data/config/sounds.yaml";
|
||||
constexpr const char* INPUT_YAML = "data/config/input.yaml";
|
||||
constexpr const char* EDITOR_YAML = "data/config/editor.yaml";
|
||||
constexpr const char* UI_PALETTE = "data/palettes/uzebox.pal";
|
||||
|
||||
// Configuració d'escenes (yaml). El de la GameScene viu a
|
||||
// `Defaults::GameScene::GAME_YAML` per coherència amb la resta de
|
||||
// valors d'aquella escena.
|
||||
constexpr const char* LOGO_YAML = "data/scenes/logo/logo.yaml";
|
||||
constexpr const char* TITLE_YAML = "data/scenes/title/title.yaml";
|
||||
|
||||
// Música pre-carregada pel Director a l'arrencada.
|
||||
constexpr const char* MUSIC_TITLE = "data/audio/music/title.ogg";
|
||||
constexpr const char* MUSIC_PLAYING = "data/audio/music/playing.ogg";
|
||||
constexpr const char* MUSIC_ROOM_INTRO = "data/audio/music/room_intro.ogg";
|
||||
constexpr const char* MUSIC_ROOM_OUTRO = "data/audio/music/room_outro.ogg";
|
||||
|
||||
// Gràfics de logo / title pre-carregats pel Director.
|
||||
constexpr const char* LOGO_MINI_GIF = "data/scenes/logo/logo_jailgames_mini.gif";
|
||||
constexpr const char* LOGO_FULL_GIF = "data/scenes/logo/logo_jailgames.gif";
|
||||
constexpr const char* TITLE_GAME_LOGO_GIF = "data/scenes/title/game_logo.gif";
|
||||
constexpr const char* TITLE_BG_GIF = "data/scenes/title/title_bg.gif";
|
||||
|
||||
// Entitats pre-carregades a GameScene (dust + 4 direccions de whip).
|
||||
constexpr const char* DUST_GIF = "data/entities/dust/dust.gif";
|
||||
constexpr const char* WHIP_EAST_GIF = "data/entities/whip_attack/whip_east.gif";
|
||||
constexpr const char* WHIP_WEST_GIF = "data/entities/whip_attack/whip_west.gif";
|
||||
constexpr const char* WHIP_NORTH_GIF = "data/entities/whip_attack/whip_north.gif";
|
||||
constexpr const char* WHIP_SOUTH_GIF = "data/entities/whip_attack/whip_south.gif";
|
||||
} // namespace Paths
|
||||
|
||||
} // namespace Defaults
|
||||
Reference in new issue
Block a user