11 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Projecte 2026 - Nuevo juego (derivado de JailDoctor's Dilemma)
IMPORTANTE: Este repositorio parte del código de JailDoctor's Dilemma como base, pero es un juego nuevo. projecte_2026 es un nombre placeholder hasta tener el diseño final. Gran parte de la arquitectura documentada más abajo describe el código heredado; varios subsistemas se van a reescribir.
Cambios de diseño previstos respecto al juego original
- Habitaciones más grandes — aprovechar el espacio del marcador (scoreboard) para ampliar el área jugable. Esto implica revisar la resolución de canvas, el layout de la HUD y el tamaño de los tilemaps.
Nueva física del jugador✅ HECHO — Player reescrito con pipeline de 6 fases, colisiones tile-based, ~20 métodos eliminados.Motor de colisiones por tiles✅ HECHO —TileCollidercon queries directas al grid. Collision tilemap editado desde el editor (tecla 7). Sistema antiguo de superficies preservado pero no usado. Pendiente: tiles kill (5) y conveyor (6).Transición de pantalla animada✅ HECHO — Scroll con easingcubicInOut(0.5s), ambas rooms visibles, enemigos activos, jugador puede moverse durante la transición.- Paleta Amstrad CPC — subir de la paleta actual (8-bit indexada limitada) a la paleta del Amstrad CPC (27 colores / más colores que la actual). Afecta a
PaletteManagery a todos los assets de color.
Estado del renombrado
Se han renombrado las referencias de JailDoctor's Dilemma → Projecte 2026 y jaildoctors_dilemma → projecte_2026 en código, configs, Makefile, CMake, LICENSE, Info.plist, scripts, locales, etc. Copyright actualizado a 2026. Se han mantenido como placeholders:
- La clave de locale
jaildoctor:endata/locale/*.yamly su uso ensource/game/scenes/ending2.cpp(es contenido de juego, pendiente de rediseño). - El publisher
jailgames(carpeta de config de sistema:~/.config/jailgames/projecte_2026). - Los archivos
release/windows/jdd.rcyjdd.res(solo bundlean el icono).
Pendiente
- PaletteColor enum en
utils.hppsigue con los 16 índices antiguos (ZX Spectrum). Los índices 0-4 coinciden con CPC, pero 5+ mapean a colores diferentes (ej.PaletteColor::BRIGHT_RED=5ahora renderiza MAGENTA en CPC).stringToColor()ySPECTRUM_REFERENCEenpalette_manager.cpptampoco están actualizados. Falta decidir cómo migrar cuando se vea el resultado visual. - Tile 6 (conveyor) no soportado aún en el nuevo motor de Player.
next()/previous()en PaletteManager desactivados de facto (solo 1 paleta). Posible futura reutilización para ciclar modos de ordenación.
Overview
Projecte 2026 is a retro-style 2D puzzle platformer game built in C++20 using SDL3 for graphics and audio. The game features 60+ rooms, collectible items, enemies, and an achievement system. It targets multiple platforms (Windows, macOS, Linux) with a focus on retro aesthetics and precise collision detection.
Language: C++20 Graphics: SDL3, OpenGL Audio: SDL3 + custom jail_audio library Build: CMake 3.10+ Game Canvas: 256x192 pixels (retro resolution)
Build Commands
Initial Setup & Build
# From project root
mkdir -p build
cd build
cmake ..
cmake --build .
Rebuild After Changes
# From build directory
cmake --build .
# Or from project root
cmake --build build
Clean Build
# From build directory
cmake --build . --clean-first
# Or from project root
cmake --build build --clean-first
Run the Game
# Executable is placed in project root
./projecte_2026
Important: The build directory is build/ relative to the project root and the output executable is placed in the project root directory.
Testing in Headless Environment (SSH/Remote Server)
IMPORTANT: When working on a remote server via SSH without a physical display, the game MUST be run using Xvfb (X Virtual Framebuffer) to avoid SDL3 display initialization errors.
Required Setup (One-time)
# Install Xvfb
sudo apt-get install xvfb
Running the Game in Headless Mode
Option 1: Using xvfb-run directly (RECOMMENDED)
xvfb-run -a ./projecte_2026
Option 2: Custom display configuration
xvfb-run -a -s "-screen 0 1280x720x24" ./projecte_2026
Why This Is Critical
- SDL3 requires a display: The game uses SDL3 which requires X11/Wayland display
- No code changes needed: Xvfb simulates a virtual display without modifying the codebase
- Full logging: Console output and logs work normally, essential for debugging resource loading
- Testing resource loading: When modifying asset loading code, running with xvfb-run allows seeing all initialization logs
ALWAYS use xvfb-run when testing on the remote server, especially when:
- Modifying resource loading code
- Testing asset initialization
- Debugging startup issues
- Verifying configuration changes
Static Analysis Tools (Linters)
This project uses two complementary static analysis tools for code quality:
clang-tidy (Modernization & Best Practices)
Purpose: Detects style issues, modernization opportunities, and potential bugs. Best for refactoring and applying C++20 best practices.
IMPORTANT: Always run on specific files, NOT on the entire project, to avoid long execution times and errors in unrelated files.
# Analyze a specific file (RECOMMENDED)
tools/linter/run_clang-tidy.sh source/game/entities/player.cpp
# Analyze multiple specific files
tools/linter/run_clang-tidy.sh source/game/entities/player.cpp source/game/entities/enemy.cpp
# Apply fixes automatically to a specific file
tools/linter/run_clang-tidy.sh --fix source/game/entities/player.cpp
# Analyze entire project (SLOW, may have errors in defaults.hpp)
tools/linter/run_clang-tidy.sh
Known False Positives:
defaults.hpp: May report errors in constant definitionsreadability-magic-numbers/cppcoreguidelines-avoid-magic-numbers: Acceptable for game constants (block sizes, speeds, etc.)
cppcheck (Bug Detection & Memory Safety)
Purpose: Detects bugs, memory leaks, undefined behavior, and style issues. Complementary to clang-tidy.
# Warning, style, and performance analysis (RECOMMENDED for daily use)
tools/linter/run_cppcheck.sh -w --path source/game/entities/player.cpp
# Exhaustive analysis (slower, more thorough)
tools/linter/run_cppcheck.sh -a --path source/game/entities/
# Detect unused functions (whole project analysis)
tools/linter/run_cppcheck.sh -u
# Analyze entire project with warning level
tools/linter/run_cppcheck.sh -w
Output: Results are saved in tools/linter/cppcheck-result-*.txt
Known False Positives:
unusedFunction: May report false positives for callback functions or public API methodspassedByValue: Acceptable for small types like SDL_FRect in game codeconstParameter: Not always applicable for API consistency
When to Use Each Tool
| Scenario | Tool | Reason |
|---|---|---|
| Daily refactoring | clang-tidy | Fast, auto-fixable issues |
| Before committing | Both | Comprehensive quality check |
| After major changes | cppcheck -a | Deep bug analysis |
| Hunting memory leaks | cppcheck | Specialized detection |
| Code modernization | clang-tidy --fix | Automatic C++20 upgrades |
Integration with Development Workflow
When refactoring code (especially with /refactor-class command):
- Make structural changes
- Compile to verify syntax
- Run clang-tidy (without --fix) to identify issues
- Run cppcheck -w to catch bugs
- Review and fix legitimate issues
- Apply automatic fixes if appropriate
- Recompile and test
Note: The /refactor-class command automatically runs both linters after compilation and provides intelligent analysis of results.
Important Code Consistency Rules
-
Forward Declarations: Always use
classfor forward declarations of classes defined withclass(notstruct). TheSurfaceclass is defined asclass Surfaceinsurface.hpp:57, so all forward declarations must useclass Surface; -
Singleton Pattern: When creating new singletons, follow the existing pattern:
- Private static instance pointer
- Private constructor/destructor
- Public
init(),destroy(), andget()methods
-
Delta Time: Always use
DeltaTimerfor frame-rate independent physics calculations -
Memory Management: Prefer
std::shared_ptrfor shared resources (Surfaces, Sprites) andstd::unique_ptrfor sole ownership -
Room file format — single source of truth: Cualquier cambio al formato
data/room/*.yaml(añadir/quitar/renombrar campos) se hace exclusivamente ensource/game/gameplay/room_format.cpp. Esa clase es la única autoridad: combina parser (loadYAML), serializer (saveYAML, debug-only) ycreateDefaultpara rooms nuevas. Cuando añadas un campo nuevo:- Añade el field a
Room::Dataensource/game/gameplay/room.hpp. - Actualiza
parseRoomConfig/buildContent/createDefaultenroom_format.cpp(los tres en el mismo módulo). - Nunca escribas yaml a pelo con
std::ofstreamdesde otro sitio (especialmente desdeMapEditor::createNewRoom, que ya delega enRoomFormat::createDefault+RoomFormat::saveYAML). El editor solo manipulaRoom::Data; el formato yaml es invisible para él. Saltarse esta regla causa bugs como el del crash de06.yaml(formato hardcoded encreateNewRoomque se desincroniza del parser real).
- Añade el field a
-
Nuevas entidades de room — soporte completo en editor y consola: Cuando añadas un tipo nuevo de entidad a las rooms (al estilo de
enemies,items,platforms,keys,doors), no basta con el parser/serializer y el manager runtime. Debes implementar también su contrapartida en el editor y en la consola, en paridad con los tipos existentes:- Selección visual en
MapEditor(click sobre la entidad →selection_con su tipo y índice). - Drag & drop para mover la entidad por el grid (con autosave al soltar).
- Entry en la statusbar del editor cuando la entidad está seleccionada (mostrar id, animación, etc).
- Comandos de consola:
add <tipo>,delete,set <propiedad> <valor>para esa entidad (ver el bloquesetEnemyProperty/setItemProperty/setPlatformPropertyenmap_editor.cppycmdSetenconsole_commands.cpp). - Renderizado de hitbox/boundary en
renderEntityBoundariescuando esté seleccionada o cuando el jugador active el overlay de debug. - EntityType enum en
map_editor.hppextendido con el nuevo tipo.
Pendiente histórico: las llaves (
Key) y puertas (Door) se añadieron al sistema de rooms en su día sin esta contrapartida en el editor. Hay que migrarlas siguiendo este patrón. Cualquier entidad nueva debe nacer ya con soporte completo, no diferirlo "para después". - Selección visual en
Last Updated: April 2026 Original Author: JailDesigner Repository: Gitea (internal)