refactor(data): reorganitza data/ i centralitza paths a defaults.hpp

This commit is contained in:
JailDesigner committed 2026-05-07 19:28:28 +02:00
1 parent 9949096fba
commit 05465b791e
54 files changed
+368 -304

No files matched your search

+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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.
//
+2 -2
View File
@@ -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.");
}
+1 -1
View File
@@ -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(),
+2 -1
View File
@@ -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); }
+28 -21
View File
@@ -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);
+4 -4
View File
@@ -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_; }
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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:
+2 -1
View File
@@ -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")) {
+10 -9
View File
@@ -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);
}
}
+7 -7
View File
@@ -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);
+11 -11
View File
@@ -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();
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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ó.
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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.
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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.
+61 -8
View File
@@ -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