# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Coffee Crisis is a C++20 arcade game built with SDL3. The player controls a character defending the UPV (university) from bouncing coffee-ball enemies across 10 stages. Supports 1-2 players, keyboard and gamepad input, and multiple languages (Spanish, Basque, English). ## Build Commands Dependencies: `libsdl3-dev` and `g++` (Linux) or `clang++` (macOS). Build system is CMake (driven by `Makefile` wrappers). ```bash make # Release build make debug # Debug build (defines DEBUG) make release # Empaqueta .tar.gz / .dmg / .zip segons SO make pack # Regenera resources.pack make compile_shaders # Compila shaders GLSL → headers SPIR-V (requereix glslc) make controllerdb # Descarga gamecontrollerdb.txt make format # clang-format -i make tidy # clang-tidy make cppcheck # cppcheck ``` ## Architecture Source layout (alineat amb la resta de projectes germans): ``` source/ ├── main.cpp ├── core/ │ ├── audio/ jail_audio.hpp │ ├── input/ input.*, mouse.* │ ├── locale/ lang.* │ ├── rendering/ screen, fade, text, writer, texture, sprite + animated/moving/smart │ │ ├── shader_backend.hpp (interfície abstracta de post-procesado) │ │ └── sdl3gpu/ (pipeline SDL3 GPU) │ │ ├── sdl3gpu_shader.* (implementació del backend GPU) │ │ └── spv/ (headers SPIR-V generats — protegits amb dummies `.clang-*`) │ ├── resources/ asset, resource, resource_pack, resource_loader, resource_helper │ └── system/ director ├── game/ │ ├── defaults.hpp (constants de gameplay: block size, canvas, áreas, colors) │ ├── game.* (hub de gameplay) │ ├── entities/ player, balloon, bullet, item │ ├── scenes/ logo, intro, title, instructions │ └── ui/ menu ├── utils/ │ ├── defines.hpp (macros de build) │ └── utils.* (helpers, enum de dificultat, circle_t, ...) └── external/ (stb_image, stb_vorbis — protegits amb dummies `.clang-*`) ``` Flux general controlat per la classe **Director** (`core/system/director.h`): inicialitza SDL, finestra/renderer i executa seccions en seqüència **Logo → Intro → Title → Game → Quit**. Les classes principals: - **Game** (`game/game.h`): gameplay nuclear. Gestiona jugadors, balloons, bullets, items, stages, nivell d'amenaça i col·lisions. Té el seu bucle d'update/render i sub-bucles per pausa i game-over. - **Screen** (`core/rendering/screen.h`): abstracció de render. Canvas virtual 256×192 escalat a la finestra. Fullscreen/windowed, borders, fades. - **Input** (`core/input/input.h`): abstracció de teclat i gamepad. - **Asset** (`core/resources/asset.h`): índex de fitxers de recurs (`add`/`get` per nom). - **Lang** (`core/locale/lang.h`): i18n, carrega strings des de `data/lang/`. ### Sprite hierarchy (`core/rendering/`) - **Sprite** → base per dibuixar des d'un spritesheet PNG - **AnimatedSprite** → afegeix animació per frames (arxius `.ani`) - **MovingSprite** → sprite amb posició/velocitat - **SmartSprite** → sprite autònom (score popups, objectes llençats) ### Audio **jail_audio** (`core/audio/jail_audio.hpp`): wrapper audio SDL3 first-party. Usa stb_vorbis per OGG. API `JA_*` per música i efectes amb mesclat per canals. ### GPU / shaders (post-procesado) Pipeline SDL3 GPU portat de `coffee_crisis_arcade_edition`. El canvas 256×192 es pot passar per un backend GPU que aplica PostFX (vinyeta, scanlines, chroma, gamma, mask, curvatura, bleeding, flicker) o CrtPi (scanlines continues amb bloom). Fallback transparent al `SDL_Renderer` clàssic si la GPU falla o si es desactiva. - **Interfície**: `core/rendering/shader_backend.hpp` (`Rendering::ShaderBackend`). - **Implementació**: `core/rendering/sdl3gpu/sdl3gpu_shader.*` + shaders GLSL a `data/shaders/` compilats a `spv/*_spv.h` via `glslc` (o precompilats si no hi ha `glslc`). - **Emscripten**: compile-time `NO_SHADERS` → sempre ruta clàssica. - **macOS**: shaders Metal (MSL) inline dins `sdl3gpu_shader.cpp`; no SPIR-V. - **Opcions persistents** a `config.txt` (migració a YAML pendent): - `videoGpuAcceleration` (bool) - `videoGpuPreferredDriver` (string, buit = auto) - `videoShaderEnabled` (bool) - `videoShaderType` (0=POSTFX, 1=CRTPI) - **Hotkeys** (provisionals fins que hi hagi menú d'opcions): `F4` activa/desactiva post-procesado · `F5` alterna POSTFX ↔ CRTPI (només si està actiu) · `F6` següent preset (només si està actiu) · `F7` següent skin. No hi ha tecla per a preset anterior. - **API** a `Screen`: `setGpuAcceleration`/`toggleGpuAcceleration`/`isGpuAccelerated`, `setShaderEnabled`/`toggleShaderEnabled`/`isShaderEnabled`, `setActiveShader`/`toggleActiveShader`/`getActiveShader`. Presets PostFX/CrtPi i cicle de presets encara **no** estan implementats — arribaran amb la migració a YAML. Per ara, valors per defecte hardcoded. ### Skins Els gràfics viuen sota `data/skins//gfx/`. Cada skin té un `skin.yaml` (id, display_name, gfx_dir). `SkinManager` (`core/resources/skin_manager.*`) escaneja manifests al boot, recorda l'skin activa (`Options::settings.skin`) i composa paths per a `Asset::addSkinAware()`. El canvi en calent (F7) és lliure: `Resource::reloadForSkin()` recorre el cache de Texture* i .ani fent `reLoadFromPath`/re-parse, mantenint stable pointer identity perquè els Sprites no s'invaliden. Les skins han de mantenir paritat de basenames i dimensions (recoloreds purs). De moment només es varia el contingut gràfic; logo, fades i altres comportaments són comuns. ## Data Directory - `data/skins//gfx/` — PNG spritesheets and `.ani` animation definition files per skin (`classic`, `nes`, ...) - `data/skins//skin.yaml` — manifest de la skin (id, display_name, gfx_dir) - `data/font/` — bitmap font files - `data/music/` and `data/sound/` — audio assets - `data/lang/` — language files (es_ES, ba_BA, en_UK) - `data/demo/` — demo recording data (gamecontrollerdb.txt vive en la raíz del proyecto, fuera del pack) - `data/menu/` — menu definition files - `data/shaders/` — fonts GLSL per al post-procesado SDL3 GPU (no van al pack; s'empotren al binari via headers SPIR-V) ## Language Code comments and variable names are primarily in Spanish/Catalan-Valencian. README is in Catalan-Valencian.