#pragma once #include #include namespace Defaults { // Mode de presentació lògica (escala finestra). Mapeja als valors de // SDL_RendererLogicalPresentation des de Screen via una funció helper, // perquè aquest header no depengui de detalls de SDL3 més enllà del scancode. enum class ScalingMode : std::uint8_t { DISABLED = 0, STRETCH = 1, LETTERBOX = 2, OVERSCAN = 3, INTEGER = 4, }; // Filtre de textura per a l'upscale final. enum class TextureFilter : std::uint8_t { NEAREST = 0, LINEAR = 1, }; // Posició de l'overlay RenderInfo: apagat, a dalt o a baix del canvas. // Cicle OFF → TOP → BOTTOM → OFF amb la hotkey corresponent. enum class RenderInfoPosition : std::uint8_t { OFF = 0, TOP = 1, BOTTOM = 2, }; constexpr int RENDER_INFO_POSITION_COUNT = 3; namespace Window { constexpr int ZOOM = 3; constexpr bool FULLSCREEN = false; } // namespace Window namespace I18n { constexpr const char* LOCALE = "ca"; // Idioma per defecte (codi ISO 639-1). constexpr const char* LOCALE_DIR = "data/locale/"; // Carpeta amb els YAML per idioma. } // namespace I18n namespace Video { constexpr bool VSYNC = true; constexpr ScalingMode SCALING_MODE = ScalingMode::LETTERBOX; constexpr TextureFilter TEXTURE_FILTER = TextureFilter::NEAREST; constexpr bool GPU_ACCELERATION = true; // Path SDL3 GPU per defecte; fallback a SDL_Renderer si falla. constexpr const char* GPU_PREFERRED_DRIVER = ""; // Buit = auto. Aplica a l'arrencada. constexpr bool SHADER_ENABLED = true; // Aplica PostFX; si false, sempre passthrough. constexpr const char* CURRENT_SHADER = "postfx"; // Shader actiu: "postfx" o "crtpi". constexpr const char* POSTFX_DEFAULT_PRESET = "CRT"; // Preset inicial PostFX. constexpr const char* CRTPI_DEFAULT_PRESET = "Default"; // Preset inicial CrtPi. constexpr const char* POSTFX_FILE = "shaders/postfx.yaml"; // Relatiu a la carpeta de sistema. constexpr const char* CRTPI_FILE = "shaders/crtpi.yaml"; // Relatiu a la carpeta de sistema. constexpr RenderInfoPosition RENDER_INFO_POSITION = RenderInfoPosition::OFF; // Overlay de debug amagat per defecte. constexpr bool RENDER_INFO_SHOW_TIME = true; // Si l'overlay és visible, mostra el temps de joc. } // namespace Video namespace Audio { constexpr bool ENABLED = true; constexpr float VOLUME = 1.0F; constexpr bool MUSIC_ENABLED = true; constexpr float MUSIC_VOLUME = 1.0F; constexpr bool SOUND_ENABLED = true; constexpr float SOUND_VOLUME = 0.2F; constexpr float VOLUME_STEP = 0.05F; // Pas estàndard per a la UI (5%). constexpr int FREQUENCY = 48000; // Freqüència de mostreig del dispositiu (Hz). constexpr int CROSSFADE_MS = 1500; // Durada per defecte del crossfade entre pistes (ms). constexpr SDL_AudioFormat FORMAT = SDL_AUDIO_S16; // Format PCM 16-bit signat natiu. constexpr int CHANNELS = 2; // Nombre de canals de sortida (estèreo). } // namespace Audio namespace KeysGame { constexpr SDL_Scancode UP = SDL_SCANCODE_UP; constexpr SDL_Scancode DOWN = SDL_SCANCODE_DOWN; constexpr SDL_Scancode LEFT = SDL_SCANCODE_LEFT; constexpr SDL_Scancode RIGHT = SDL_SCANCODE_RIGHT; constexpr SDL_Scancode JUMP = SDL_SCANCODE_M; constexpr SDL_Scancode ATTACK = SDL_SCANCODE_N; constexpr SDL_Scancode START = SDL_SCANCODE_1; constexpr SDL_Scancode EXIT = SDL_SCANCODE_ESCAPE; } // namespace KeysGame // Tecles del segon jugador local (WASD). Simètriques a KeysGame però // mapejades a la mà esquerra del teclat. Cada Player instancia amb els // seus propis Controls, així que aquests són un recull de fàbrica: // canviar-los ací canvia el mapatge per a qualsevol escena que els use. namespace KeysGameP2 { constexpr SDL_Scancode UP = SDL_SCANCODE_W; constexpr SDL_Scancode DOWN = SDL_SCANCODE_S; constexpr SDL_Scancode LEFT = SDL_SCANCODE_A; constexpr SDL_Scancode RIGHT = SDL_SCANCODE_D; constexpr SDL_Scancode JUMP = SDL_SCANCODE_V; constexpr SDL_Scancode ATTACK = SDL_SCANCODE_C; constexpr SDL_Scancode START = SDL_SCANCODE_2; } // namespace KeysGameP2 namespace Player { constexpr float SPEED_PX_PER_S = 60.0F; // Velocitat base del jugador (sense sprint / slow-zones). // Factor multiplicatiu aplicat a la velocitat quan un jugador empenta // l'altre (0.30 = el pusher es ralentitza al 30% i el pushed és // arrossegat a la mateixa velocitat). Sobrescrivible des del YAML // del mapa amb la clau `push_factor`. constexpr float PUSH_FACTOR = 0.30F; } // namespace Player // Fallbacks del sistema d'il·luminació. El gradient en viu viu a // data/config/lighting.yaml; aquests valors només s'apliquen si el // fitxer falta o li manca alguna clau. La forma final (3 anells) es // descriu al YAML; veure `Lighting::GradientConfig` per a la semàntica. namespace Lighting { constexpr float INNER_RATIO = 0.8F; constexpr float MID_RATIO = 0.9F; constexpr float INNER_INTENSITY = 1.0F; constexpr float MID_INTENSITY = 0.9F; constexpr float OUTER_INTENSITY = 0.8F; // Nivell d'il·luminació de sala per defecte. Una sala sense la // clau `light_level` queda totalment il·luminada (com hui). constexpr float ROOM_LIGHT_DEFAULT = 1.0F; } // namespace Lighting // Fallbacks del tema d'UI: índexs de paleta, timings (ms) i fonts. // 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". namespace UI { // Fonts d'UI centralitzades: un únic lloc per conèixer la carpeta // (data/fonts/), el nom-clau al Resource::Cache i els fitxers .gif / // .fnt de cada font. Afegir-ne una nova és una constant ací i ja. namespace Font { constexpr const char* DIR = "data/fonts/"; // HUD/Notifier/RenderInfo: font principal de UI del joc. // El kerning és la separació extra entre glifs (sumat a l'amplada // natural). 1 és el valor clàssic; valors negatius ajunten glifs // per a fonts de display amb sidebearings amples. constexpr const char* HUD_NAME = "8bithud"; constexpr const char* HUD_GIF = "data/fonts/8bithud.gif"; constexpr const char* HUD_FNT = "data/fonts/8bithud.fnt"; constexpr int HUD_KERNING = 1; // Placeholders (LOGO / TITLE / INTRO): font temporal fins que els // placeholders es substitueixin per les seues escenes finals. constexpr const char* PLACEHOLDER_NAME = "ari-w9500-condensed-display"; constexpr const char* PLACEHOLDER_GIF = "data/fonts/ari-w9500-condensed-display.gif"; constexpr const char* PLACEHOLDER_FNT = "data/fonts/ari-w9500-condensed-display.fnt"; constexpr int PLACEHOLDER_KERNING = 1; // Text de transició de sala (ROOM_INTRO "Piràmide N / Sala M" i // ROOM_OUTRO "Fase completada"). Font temàtica diferenciada de la // del HUD i de la dels placeholders perquè el rètol de fase tinga // pes visual propi. La pausa segueix amb la PLACEHOLDER. constexpr const char* ROOM_TEXT_NAME = "CaesarDressing-Regular"; constexpr const char* ROOM_TEXT_GIF = "data/fonts/CaesarDressing-Regular.gif"; constexpr const char* ROOM_TEXT_FNT = "data/fonts/CaesarDressing-Regular.fnt"; constexpr int ROOM_TEXT_KERNING = 1; // Menú de servei (F9): títol en display normal, items en la // variant condensed-display (més compacta, perquè caben més // files sense encongir la caixa). Kerning 0 a totes dues perquè // els glifs de display ja porten sidebearings generosos. constexpr const char* MENU_TITLE_NAME = "ari-w9500-display"; constexpr const char* MENU_TITLE_GIF = "data/fonts/ari-w9500-display.gif"; constexpr const char* MENU_TITLE_FNT = "data/fonts/ari-w9500-display.fnt"; constexpr int MENU_TITLE_KERNING = 0; constexpr const char* MENU_ITEMS_NAME = "ari-w9500-condensed-display"; constexpr const char* MENU_ITEMS_GIF = "data/fonts/ari-w9500-condensed-display.gif"; constexpr const char* MENU_ITEMS_FNT = "data/fonts/ari-w9500-condensed-display.fnt"; constexpr int MENU_ITEMS_KERNING = 0; // Copyright al peu de la TITLE: pixel-art estricte, generat amb // font-gen a partir de Tiny5-Regular size 5 (caixa 3×6 px). La // separem de la `placeholder` (que la fa servir el "press start") // per diferenciar tipogràficament jerarquia: prompt destacat amb // outline gros, copyright net i micro a baix. constexpr const char* COPYRIGHT_NAME = "Tiny5-Regular"; constexpr const char* COPYRIGHT_GIF = "data/fonts/Tiny5-Regular.gif"; constexpr const char* COPYRIGHT_FNT = "data/fonts/Tiny5-Regular.fnt"; constexpr int COPYRIGHT_KERNING = 0; } // namespace Font // Overlay de RenderInfo (F12). constexpr Uint8 RENDER_INFO_TEXT = 58; constexpr Uint8 RENDER_INFO_SHADOW = 16; // Fons del canvas (zona fora del tilemap en letterbox/integer). constexpr Uint8 CANVAS_BG = 72; // Preset per defecte del Notifier. constexpr Uint8 NOTIFICATION_TEXT = 232; constexpr Uint8 NOTIFICATION_BG = 64; constexpr int NOTIFICATION_TIME_MS = 4000; // Geometria del Notifier (en píxels del canvas). Asimètric a // propòsit: PADDING_TOP > PADDING_BOTTOM puja una mica el text // dins la caixa i deixa la base més arrapada al vora inferior. // MARGIN_TOP és la separació entre la vora superior del canvas i // la línia exterior de la caixa. SLIDE_MS és la durada de l'entrada // i de l'eixida (independent de la mida de la caixa, perquè el // moviment va per temps i no per velocitat). Les corbes són noms // del registre d'`Easing` (veure UiConfig::curveByName). namespace Notifier { constexpr int PADDING_H = 6; constexpr int PADDING_TOP = 4; constexpr int PADDING_BOTTOM = 3; constexpr int LINE_GAP = 1; constexpr int MARGIN_TOP = 3; constexpr int BORDER_PX = 1; constexpr int SLIDE_MS = 400; constexpr const char* SLIDE_IN_CURVE = "outCubic"; constexpr const char* SLIDE_OUT_CURVE = "inCubic"; } // namespace Notifier // Preset per a la confirmació d'eixida (ESC doble). La durada ha // de coincidir amb la del Notifier perquè el missatge i la finestra // de confirmació expiren alhora (veure GlobalInputs::onExit). constexpr Uint8 EXIT_TEXT = 71; constexpr Uint8 EXIT_BG = 2; constexpr int EXIT_TIME_MS = 4000; // Índexs de paleta per al menú de servei (F9). constexpr Uint8 MENU_BG = 2; // Fons de la caixa. constexpr Uint8 MENU_BORDER = 232; // Vora. constexpr Uint8 MENU_TITLE = 237; // Títol i subtítol. constexpr Uint8 MENU_LABEL = 58; // Etiquetes dels items. constexpr Uint8 MENU_VALUE = 232; // Valor actual. constexpr Uint8 MENU_CURSOR = 71; // Item seleccionat. constexpr Uint8 MENU_DISABLED = 16; // Label en gris quan no aplica. // Índexs de paleta per al marcador de joc (HUD de la GameScene). // Tres "famílies" de color — un parell (label, value) + sombra per // cada bloc — donen jerarquia visual: P1 càlid (vermell+crema), // CENTER ambiental (ambre+or), P2 fred (cian+blau pàl·lid). La // sombra és un to més fosc del mateix matís per donar volum. constexpr Uint8 HUD_BG = 0; // Fons de cada bloc. constexpr Uint8 HUD_P1_LABEL = 7; // P1 label: vermell pur (#ff0000). constexpr Uint8 HUD_P1_VALUE = 183; // P1 value: crema-préssec (#ffdaaa). constexpr Uint8 HUD_P1_SHADOW = 2; // P1 ombra: vermell fosc (#480000). constexpr Uint8 HUD_CENTER_LABEL = 29; // CENTER label: ambre cremat (#b66d00). constexpr Uint8 HUD_CENTER_VALUE = 55; // CENTER value: or brillant (#ffda00). constexpr Uint8 HUD_CENTER_SHADOW = 10; // CENTER ombra: marró cremat (#482400). constexpr Uint8 HUD_P2_LABEL = 248; // P2 label: cian pur (#00ffff). constexpr Uint8 HUD_P2_VALUE = 253; // P2 value: blau pàl·lid (#b6ffff). constexpr Uint8 HUD_P2_SHADOW = 64; // P2 ombra: blau marí (#000055). constexpr Uint8 HUD_FLASH = 63; // Flash (groc neó, comú a totes les famílies). // Rètol de transició de sala (ROOM_INTRO i ROOM_OUTRO). // Comparteix la família CENTER del HUD: or sobre marró cremat, // per coherència visual ("Piràmide N / Sala N" és sempre // daurat arreu del joc). constexpr Uint8 ROOM_TEXT = 55; // Or brillant (= HUD_CENTER_VALUE). constexpr Uint8 ROOM_TEXT_OUTLINE = 10; // Marró cremat (= HUD_CENTER_SHADOW). // Timings d'animació del HUD. L'entrada són els tres blocs lliscant // a la seua posició; flash i shake acompanyen un `player_hit`. constexpr int HUD_ENTRY_MS = 400; constexpr int HUD_FLASH_MS = 250; constexpr int HUD_SHAKE_MS = 300; // Parpadeig dels prompts inactius del HUD ("Polsa start..." / // "Espera..."). Un únic temporitzador global al Hud sincronitza // P1 i P2. cycle<=0 o ratio>=1 → sempre visible (disable trivial). constexpr int HUD_BLINK_CYCLE_MS = 1000; constexpr float HUD_BLINK_VISIBLE_RATIO = 0.8F; // 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/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/audio/sounds/`. constexpr const char* PLAYER_START_SOUND = "player_start.wav"; // So curt de "soroll/scratch" disparat al constructor de LogoScene // i sincronitzat amb la fase SCAN del scanline reveal. Playback // únic via Audio::Group::INTERFACE; si dura més que el scan, la // cua sona pinçada al començament de MIDDLE — pretès com a // "eco" sonor de l'efecte. constexpr const char* LOGO_GLITCH_SOUND = "glitch.wav"; // Escena TITLE (provisional fins que tinguem artwork). Colors // referits a la paleta "ui" (uzebox.pal): BG_COLOR és el to més // proper al negre sense ser-ho (índex 1 = 36,0,0); TEXT_COLOR és // el taronja més pur de la paleta (índex 31 = 255,109,0). Els // ms del cicle de parpadeig sumen el cicle complet del prompt // "press start" — 80% visible / 20% ocult per defecte. namespace Title { constexpr int DURATION_MS = 30000; constexpr Uint8 BG_COLOR = 1; constexpr Uint8 TEXT_COLOR = 31; // Color del text de "© 2026 JailDesigner": off-white càlid (índex // 183 = 255,218,170, peach/cream) — ~90% blanc amb tint càlid. constexpr Uint8 COPYRIGHT_COLOR = 183; // Color de l'outline del prompt "PRESS START" (no del copyright, // tot i compartir-se a versions antigues). Marró fosc càlid // (índex 19 = 109,72,0) coherent amb la paleta del logo. constexpr Uint8 PRESS_START_OUTLINE_COLOR = 19; // Posicions Y dels tres elements verticals de la TITLE, en // percentatge sobre `GameCanvas::HEIGHT`. El logo s'ancora pel // seu top (la imatge cau cap avall des d'aquest Y); el prompt // i el copyright es centren verticalment sobre la línia. constexpr int LOGO_Y_PERCENT = 15; constexpr int PROMPT_Y_PERCENT = 68; constexpr int COPYRIGHT_Y_PERCENT = 92; // Separació vertical entre el minilogo i el text del © al peu. constexpr int MINI_LOGO_GAP_PX = 2; constexpr int BLINK_VISIBLE_MS = 800; constexpr int BLINK_HIDDEN_MS = 200; // Fase STARTING: durada fixa entre la primera pulsació de // START i la transició a la següent escena. Durant aquesta // fase, el parpadeig del prompt commuta a un cicle simètric // 50/50 (visible/ocult) amb període `STARTING_BLINK_PERIOD_MS`, // pensat per a un ritme molt més ràpid que l'animació // atràctil del IDLE (200 ms = 5 Hz). constexpr int STARTING_MS = 3000; constexpr int STARTING_BLINK_PERIOD_MS = 200; // Fade-out estil mosaic dissolve dins l'última part de la // fase STARTING. `FADE_OUT_MS` ha de ser <= STARTING_MS; // si és més gran, comença ja a t=0 i acaba abans del salt. // `FADE_OUT_MAX_BLOCK` és la mida màxima de bloc en píxels // (32 al canvas de 320×240 dóna 10×8 blocs al final). constexpr int FADE_OUT_MS = 800; constexpr int FADE_OUT_MAX_BLOCK = 32; // Fade-out de la música de la TITLE en entrar a STARTING. // Independent del visual: no cal que coincidisca amb FADE_OUT_MS // (la música pot acabar abans/després del mosaic). constexpr int MUSIC_FADE_OUT_MS = 2000; // Fade-to-black per a la sortida d'attract (timeout). És una // capa negra lineal sobre el canvas — sense mosaic — perquè // l'eixida silenciosa cap a LOGO siga neta. NO toca la música: // el title.ogg continua sonant durant la transició; LOGO ja // veurà què en fa. constexpr int ATTRACT_FADE_TO_BLACK_MS = 800; // Seqüència d'aparició dels elements de la TITLE en fase IDLE. // Tots els temps són absoluts des de l'entrada a l'escena. // `FADE_IN_MS` és la capa negra inicial que s'esvaeix cap al fons // (mateixa convenció que `room_intro.fade_in_ms` del joc perquè // l'arribada a la TITLE i a una sala de joc tinguin el mateix // ritme). Els altres temps marquen quan apareix cada element; // `SLIDE_*` defineixen el slide-in des del marge inferior amb // la corba `SLIDE_CURVE`. Si l'usuari prem START durant la // seqüència, aquesta es completa instantàniament. namespace Intro { constexpr int FADE_IN_MS = 500; constexpr int GAME_LOGO_AT_MS = 1500; constexpr int MINI_LOGO_AT_MS = 2000; constexpr int MINI_LOGO_SLIDE_MS = 500; constexpr int COPYRIGHT_AT_MS = 2200; constexpr int COPYRIGHT_SLIDE_MS = 500; constexpr const char* SLIDE_CURVE = "outCubic"; constexpr int PRESS_START_AT_MS = 3000; } // namespace Intro // Distorsió sinusoidal horitzontal de l'imatge de fons // (efecte de calor del desert). `amplitude_px` és el // desplaçament màxim per fila; `wavelength_px` la distància // vertical entre dos pics; `speed_hz` la velocitat amb què // avança la fase (cicles/segon). Si `enabled` és false el // fons es pinta sense distorsió. namespace HeatHaze { constexpr bool ENABLED = true; constexpr float AMPLITUDE_PX = 1.5F; constexpr float WAVELENGTH_PX = 32.0F; constexpr float SPEED_HZ = 0.6F; } // namespace HeatHaze } // namespace Title // Escena LOGO (logotip de l'editora). La timeline és lineal i // composta per fases independents amb durades configurables des // del YAML (`logo.timeline.*`). L'efecte CRT de revelat (scan // line + glitch tail) ho gestiona `Effects::ScanReveal` i les // seves constants viuen al sub-namespace `Scan` d'aquí baix. namespace Logo::Timeline { // Negre inicial abans que comence el revelat. Permet entrar // a l'escena des d'una transició/fade extern sense talls. constexpr int BLACK_INTRO_MS = 2000; // Silenci amb logo estable abans d'arrencar la música del // títol — espai per "respirar" entre el glitch i la pista. constexpr int HOLD_SILENT_MS = 1000; // Logo estable amb música del títol sonant. Quan acaba, // comença el fade-out. constexpr int HOLD_WITH_MUSIC_MS = 2500; // Fade lineal a negre. constexpr int FADE_OUT_MS = 500; // Negre final amb música encara sonant — la TitleScene // continuarà la pista de manera idempotent. constexpr int BLACK_OUTRO_MS = 1000; } // namespace Logo::Timeline // Constants del revelat CRT pròpiament dit. La banda lluminosa // baixa de dalt a baix amb glitch al seu voltant i bursts VHS // ocasionals damunt la part ja revelada. Quan la banda toca el // peu del logo, un flash blanc remata l'efecte; després un // "tail" manté el logo visible amb bursts durant `TAIL_GLITCH_MS` // abans que `isFinished()` retorne true. namespace Logo::Scan { constexpr int DURATION_MS = 1500; constexpr int TAIL_GLITCH_MS = 1500; constexpr int BAND_HEIGHT_PX = 4; constexpr int BAND_ALPHA = 200; // Pulse de brillantor sinusoidal sobre l'alpha base de la // banda — simula el ritme de refresc d'un CRT. La fase // avança a `BAND_PULSE_HZ` cicles/segon i la profunditat // marca quant cau l'alpha al ventre (0 = sense pulse, // 1 = la banda arriba a alpha 0 als ventres). Valors per // defecte: 20 Hz pulsacional ben visible a 60 fps sense // aliasing dur, profunditat 0.45 (alpha oscil·la entre el // 55% i el 100% de BAND_ALPHA). constexpr float BAND_PULSE_HZ = 20.0F; constexpr float BAND_PULSE_DEPTH = 0.45F; // Glitch a la banda d'impacte: les files dins del radi // reben un offset horitzontal aleatori d'amplitud // decreixent amb la distància a la banda. constexpr int GLITCH_AMPLITUDE_PX = 6; constexpr int GLITCH_BAND_RADIUS_PX = 12; // Bursts VHS damunt la part ja revelada: ocasionalment // (~per_sec mitjà) una franja horitzontal es desplaça // durant `duration_ms` per simular tracking error. constexpr int VHS_BURST_PER_SEC = 3; constexpr int VHS_BURST_DURATION_MS = 80; constexpr int VHS_BURST_HEIGHT_PX = 8; constexpr int VHS_BURST_AMPLITUDE_PX = 8; // Flash blanc final quan la banda surt per sota — punt // visual de tancament del scan abans d'entrar a MIDDLE. constexpr int FLASH_MS = 100; } // namespace Logo::Scan } // namespace UI #ifdef _DEBUG // Constants de l'editor de tilemap. Només presents en Debug — en // Release l'editor no existeix, així que ni les constants tenen sentit. namespace Editor { // Color del rectangle 1 px que envolta el canvas durant l'edició. constexpr std::uint32_t BORDER_ARGB = 0xFF2244FFU; // Píxels entre el canvas i el rectangle del TilePicker per totes // les vores. Prou perquè el border blau de l'editor no es // superpose amb la graella del picker. constexpr int PICKER_MARGIN = 8; // Píxels de separació entre tiles dins de la graella del picker. // 1 px deixa veure clarament on acaba un tile i on comença l'altre, // útil sobretot quan dos tiles veïns tenen colors molt similars. constexpr int PICKER_SPACING = 1; // Fons del TilePicker (blau fosc, prou contrastat amb els tiles // de color clar i clarament diferent del canvas). constexpr std::uint32_t PICKER_BG_ARGB = 0xFF101824U; // Vora 1 px del tile sota el cursor al picker. constexpr std::uint32_t PICKER_HOVER_ARGB = 0xFFFFFFFFU; } // namespace Editor #endif // Configuració de l'escena de joc (timings i corbes de la FSM de sala). // 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* GAME_YAML = "data/scenes/game/game.yaml"; } // namespace GameScene // Rutes d'assets per piràmide. Centralitzats ací perquè `GameScene` no // en contingui cap literal; afegir una piràmide nova serà un altre // conjunt de constants + un Config distint passat al ctor. namespace Pyramid { // Índex ordenat de les 30 sales (5 piràmides × 6 sales). El consumeix // `Levels::LevelManager` a la primera invocació; cada entrada apunta // a un `data/maps/p/r.yaml`. Cap altre punt del codi hauria de // 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_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_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* LIGHTING_YAML = "data/config/lighting.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"; constexpr const char* MUSIC_GAME_OVER = "data/audio/music/game_over.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