# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

---

# JailDoctor's Dilemma - Codebase Architecture Guide

## Overview

**JailDoctor's Dilemma** 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
```bash
# From project root
mkdir -p build
cd build
cmake ..
cmake --build .
```

### Rebuild After Changes
```bash
# From build directory
cmake --build .

# Or from project root
cmake --build build
```

### Clean Build
```bash
# From build directory
cmake --build . --clean-first

# Or from project root
cmake --build build --clean-first
```

### Run the Game
```bash
# Executable is placed in project root
./jaildoctors_dilemma
```

**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)
```bash
# Install Xvfb
sudo apt-get install xvfb
```

#### Running the Game in Headless Mode

**Option 1: Using xvfb-run directly (RECOMMENDED)**
```bash
xvfb-run -a ./jaildoctors_dilemma
```

**Option 2: Custom display configuration**
```bash
xvfb-run -a -s "-screen 0 1280x720x24" ./jaildoctors_dilemma
```

#### 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.

```bash
# 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
```

**Common clang-tidy Checks:**
- `modernize-*`: C++ modernization (use auto, range-for, etc.)
- `readability-*`: Code readability improvements
- `performance-*`: Performance optimizations
- `bugprone-*`: Potential bug detection

**Known False Positives:**
- `defaults.hpp`: May report errors in constant definitions
- `readability-magic-numbers`: Acceptable for game constants (block sizes, speeds, etc.)
- `cppcoreguidelines-avoid-magic-numbers`: Same as above, acceptable in game code

#### cppcheck (Bug Detection & Memory Safety)

**Purpose:** Detects bugs, memory leaks, undefined behavior, and style issues. Complementary to clang-tidy.

```bash
# 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`

**Common cppcheck Checks:**
- Memory leaks and resource management
- Null pointer dereferences
- Buffer overflows and array bounds
- Uninitialized variables
- Dead code and unused functions

**Known False Positives:**
- `unusedFunction`: May report false positives for callback functions or public API methods
- `passedByValue`: Acceptable for small types like SDL_FRect in game code
- `constParameter`: 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 |

#### Best Practices

1. **Run linters after compilation succeeds** - Fix compile errors first
2. **Analyze specific files** - Faster feedback, avoids unrelated errors
3. **Review before applying --fix** - Understand changes before accepting
4. **Context matters** - Game code may legitimately have "magic numbers" for gameplay constants
5. **Use both tools** - They catch different issues and complement each other
6. **Check suppressions file** - `tools/linter/cppcheck_suppressions` excludes external/ and system headers

#### Integration with Development Workflow

When refactoring code (especially with `/refactor-class` command):
1. Make structural changes
2. **Compile** to verify syntax
3. **Run clang-tidy** (without --fix) to identify issues
4. **Run cppcheck -w** to catch bugs
5. Review and fix legitimate issues
6. Apply automatic fixes if appropriate
7. Recompile and test

**Note:** The `/refactor-class` command automatically runs both linters after compilation and provides intelligent analysis of results.

---

## 1. High-Level Architecture Overview

The architecture follows a **layered, modular design** with clear separation of concerns:

```
┌─────────────────────────────────────┐
│        Application Layer             │
│  (Director, Scene Manager)           │
└─────────────────────────────────────┘
                  ↓
┌─────────────────────────────────────┐
│        Game Logic Layer              │
│  (Game Scene, Entities, Gameplay)    │
└─────────────────────────────────────┘
                  ↓
┌─────────────────────────────────────┐
│        Core Systems Layer            │
│  (Rendering, Audio, Input, Resources)│
└─────────────────────────────────────┘
                  ↓
┌─────────────────────────────────────┐
│     SDL3 & External Libraries        │
│  (jail_audio, stb_image, stb_vorbis) │
└─────────────────────────────────────┘
```

### Key Design Principles

- **Singleton Pattern:** Core systems (Director, Screen, Audio, Input, Resource, Asset) use singleton pattern for global access
- **Scene-Based Architecture:** Game flow managed through discrete scenes (Logo, Title, Loading, Game, Ending, etc.)
- **Component-Based Entities:** Player, enemies, and items are discrete entities with render/update patterns
- **Resource Management:** All assets (textures, sounds, animations, tilemaps) cached through Resource singleton
- **Delta Time:** Frame-rate independent physics using DeltaTimer class

---

## 2. Directory Structure

```
source/
├── core/                          # Core engine systems
│   ├── audio/                     # Audio management
│   │   ├── audio.hpp/cpp          # Audio singleton (music, sounds, volumes)
│   │   └── jail_audio.hpp         # Custom jail_audio library wrapper
│   ├── input/                     # Input handling
│   │   ├── input.hpp/cpp          # Input manager (keyboard, gamepad)
│   │   ├── input_types.hpp        # Input type definitions
│   │   ├── global_inputs.hpp      # Global input state
│   │   └── mouse.hpp              # Mouse input
│   ├── locale/                    # Localization
│   │   └── locale.hpp             # Locale/language support
│   ├── rendering/                 # Graphics rendering
│   │   ├── screen.hpp/cpp         # Screen/window singleton, SDL renderer
│   │   ├── surface.hpp/cpp        # 8-bit indexed color surface abstraction
│   │   ├── sprite/                # Sprite rendering classes
│   │   │   ├── sprite.hpp         # Static sprite rendering
│   │   │   ├── animated_sprite.hpp # Animated sprite with frame data
│   │   │   ├── moving_sprite.hpp  # Moving sprite with velocity
│   │   │   └── dissolve_sprite.hpp # Dissolve transition sprite
│   │   ├── text.hpp/cpp           # Text rendering system
│   │   ├── gif.hpp/cpp            # GIF image loader
│   │   ├── pixel_reveal.hpp       # Pixel reveal effect
│   │   ├── render_info.hpp        # Render information data
│   │   ├── palette_manager.hpp    # Palette management
│   │   ├── sdl3gpu/               # SDL3 GPU shader backend
│   │   │   ├── sdl3gpu_shader.hpp/cpp # CRT/post-processing shader effects
│   │   │   └── *_spv.h            # Pre-compiled SPIR-V shader headers
│   │   └── shader_backend.hpp     # Abstract shader interface
│   ├── resources/                 # Asset & Resource management
│   │   ├── resource_list.hpp      # Asset path registry (O(1) lookups)
│   │   ├── resource_cache.hpp     # Resource caching singleton
│   │   ├── resource_loader.hpp    # Asset loading logic
│   │   ├── resource_pack.hpp      # Resource pack handling
│   │   ├── resource_helper.hpp    # Resource utility functions
│   │   └── resource_types.hpp     # Resource type definitions
│   └── system/                    # System management
│       ├── director.hpp/cpp       # Main application controller
│       ├── debug.hpp/cpp          # Debug info overlay
│       └── global_events.hpp/cpp  # Global event broadcasting
├── game/                          # Game-specific logic
│   ├── entities/                  # Game objects
│   │   ├── player.hpp/cpp         # Player entity with physics
│   │   ├── enemy.hpp/cpp          # Enemy entities
│   │   └── item.hpp/cpp           # Collectible items
│   ├── gameplay/                  # Core gameplay systems
│   │   ├── room.hpp/cpp           # Room/level logic, collision
│   │   ├── room_loader.hpp/cpp    # Room loading from YAML files
│   │   ├── room_tracker.hpp/cpp   # Tracks visited rooms
│   │   ├── collision_map.hpp/cpp  # Collision map data
│   │   ├── tilemap_renderer.hpp/cpp # Tilemap rendering
│   │   ├── enemy_manager.hpp/cpp  # Enemy lifecycle management
│   │   ├── item_manager.hpp/cpp   # Item lifecycle management
│   │   ├── scoreboard.hpp/cpp     # Score display & data
│   │   ├── item_tracker.hpp/cpp   # Tracks collected items
│   │   ├── stats.hpp/cpp          # Game statistics
│   │   └── cheevos.hpp/cpp        # Achievement system
│   ├── scenes/                    # Game scenes (flow states)
│   │   ├── logo.hpp/cpp           # JailGames logo screen
│   │   ├── loading_screen.hpp/cpp # Resource loading progress
│   │   ├── title.hpp/cpp          # Title screen & menus
│   │   ├── game.hpp/cpp           # Main gameplay loop
│   │   ├── game_over.hpp/cpp      # Game over screen
│   │   ├── ending.hpp/cpp         # Ending sequence 1
│   │   ├── ending2.hpp/cpp        # Ending sequence 2
│   │   └── credits.hpp/cpp        # Credits screen
│   ├── ui/                        # User interface
│   │   ├── notifier.hpp/cpp       # Achievement/notification display
│   │   ├── console.hpp/cpp        # In-game debug console
│   │   └── console_commands.hpp/cpp # Console command definitions
│   ├── options.hpp/cpp            # Game configuration/options
│   ├── game_control.hpp           # Game control logic
│   ├── scene_manager.hpp          # Scene flow state machine
│   └── defaults.hpp               # Game defaults constants
├── external/                      # Third-party libraries
│   ├── fkyaml_node.hpp            # YAML parsing library
│   ├── stb_image.h                # Image loading library
│   └── stb_vorbis.h               # OGG Vorbis audio decoding
├── utils/                         # Utility code
│   ├── delta_timer.hpp/cpp        # Frame-rate independent timing
│   ├── easing_functions.hpp       # Easing/interpolation functions
│   ├── defines.hpp                # Game constants (resolutions, block sizes)
│   └── utils.hpp/cpp              # Helper functions (colors, math)
└── main.cpp                       # Application entry point

config/                            # Configuration files
└── assets.yaml                     # Asset registry (text-based configuration)

data/                              # Game assets
├── font/                          # Bitmap fonts + descriptors
├── palette/                       # Color palettes (.pal files)
├── shaders/                       # GLSL vertex/fragment shaders
├── room/                          # Tilemaps & room definitions (01.tmx-60.tmx)
├── tilesets/                      # Tileset graphics
├── enemies/                       # Enemy sprites & animations
├── player/                        # Player sprites & animations
├── items/                         # Item sprite sheets
├── music/                         # Background music (OGG)
├── sound/                         # Sound effects (WAV)
├── logo/                          # Logo images
├── loading/                       # Loading screen graphics
├── title/                         # Title screen graphics
├── ending/                        # Ending sequence images
└── credits/                       # Credits screen assets
```

---

## 3. Key Architectural Patterns

### 3.1 Singleton Pattern (Core Systems)

Most core systems use thread-safe singleton pattern:

```cpp
class Screen {
    private:
        static Screen* screen_;  // Singleton instance
        Screen();                // Private constructor
        ~Screen();
    public:
        static void init();      // Creates singleton
        static void destroy();   // Destroys singleton
        static Screen* get();    // Accesses singleton
};
```

**Singleton Systems:**
- `Screen` - Rendering, window management, palette/shader effects
- `Input` - Keyboard & gamepad input binding and checking
- `Audio` - Music and sound effect playback
- `Resource::Cache` - Asset loading, caching, streaming (with error handling)
- `Resource::List` - Asset path registry from assets.yaml (O(1) lookups)
- `Director` - Main application controller
- `Cheevos` - Achievement state management
- `Debug` - Debug information overlay

### 3.2 Scene-Based State Machine

The game uses a scene manager to control application flow:

```cpp
// namespace SceneManager
enum class Scene {
    LOGO, LOADING_SCREEN, TITLE, CREDITS, GAME, DEMO, 
    GAME_OVER, ENDING, ENDING2, RESTART_CURRENT, QUIT
};

inline Scene current = Scene::LOGO;  // Global scene state
inline Options options = ...;        // Transition options
```

**Scene Hierarchy:**
- Each scene runs its own update/render loop
- `Director` switches between scenes based on `SceneManager::current`
- Scenes can request transitions via `SceneManager::current` assignment

### 3.3 Entity-Component Pattern (Simplified)

Entities (Player, Enemies, Items) have:
- **Update** - Logic, physics, animation
- **Render** - Draw to screen surface
- **Collision** - Hit detection (player collides with room, enemies, items)

### 3.4 Surface-Based Rendering Pipeline

The rendering system uses a **8-bit indexed color** pipeline:

```
SurfaceData (pixel buffer)
     ↓
Surface (palette + rendering operations)
     ↓
SDL_Texture (GPU texture)
     ↓
SDL_Renderer (to SDL_Window)
     ↓
Display
```

**Key Components:**
- `Surface` - 8-bit indexed pixel buffer with palette support
- `Sprite` - Renders a fixed region of a surface
- `AnimatedSprite` - Frame-based animation on top of sprite
- `MovingSprite` - Adds velocity/position to animated sprite
- `DissolveSprite` - Dissolve transition effect sprite
- Supports color replacement, palette swapping, and shader effects (CRT)

### 3.5 Tile-Based Collision System

Rooms use a sophisticated collision detection system:

```cpp
class Room {
    std::vector<LineHorizontal> bottom_floors_;   // Ground surfaces
    std::vector<LineHorizontal> top_floors_;      // Ceiling surfaces
    std::vector<LineVertical> left_walls_;        // Left walls
    std::vector<LineVertical> right_walls_;       // Right walls
    std::vector<LineDiagonal> left_slopes_;       // Ramps going left
    std::vector<LineDiagonal> right_slopes_;      // Ramps going right
    std::vector<LineHorizontal> conveyor_belt_floors_; // Moving platforms
};
```

**Collision Detection:**
- Player has collision points and "feet" points for fine-grained detection
- Room provides `check*Surfaces()` methods for collision resolution
- Supports ramps, slopes, conveyor belts, and auto-surfaces
- Enemies have axis-aligned bounding boxes

### 3.6 Sprite Animation System

Animation is data-driven:

```cpp
struct AnimationData {
    std::string name;
    std::vector<SDL_FRect> frames;  // Frame rectangles
    int speed;                       // Milliseconds per frame
    int loop;                        // Frame to return to (-1 = no loop)
    bool completed;
    int current_frame;
    int counter;
};

// Loaded from .yaml animation definition files
// Rendered with AnimatedSprite
```

---

## 4. System Interactions & Data Flow

### 4.1 Application Lifecycle

```
main()
  ↓
Director::Director()  [Initialization]
  ├─ Resource::List::init()  - Initialize asset registry singleton
  ├─ Director::setFileList() - Load assets.yaml via Resource::List (no verification)
  ├─ Options::loadFromFile() - Load game configuration
  ├─ Audio::init()           - Initialize SDL audio
  ├─ Screen::init()          - Create window, SDL renderer
  ├─ Input::init()           - Bind keyboard/gamepad controls
  ├─ Resource::Cache::init() - Load ALL game resources (with verification)
  │   └─ Throws exception if any required asset is missing
  └─ Cheevos::init()         - Load achievement state

Director::run()        [Main loop]
  ├─ while (SceneManager::current != QUIT)
  │   ├─ Logo::run()
  │   ├─ LoadingScreen::run()
  │   ├─ Title::run()
  │   ├─ Game::run()
  │   ├─ Ending::run()
  │   └─ ...
  └─ return 0

Director::~Director() [Cleanup]
  ├─ Options::saveToFile()   - Save game settings
  ├─ Resource::Cache::destroy()
  ├─ Audio::destroy()
  ├─ Input::destroy()
  ├─ Screen::destroy()
  └─ Resource::List::destroy()
```

### 4.2 Game Scene Flow (Core Gameplay Loop)

```cpp
Game::run() {
    while (game is running) {
        // Update
        Input::checkInput()          - Get player commands
        Player::update()             - Physics, animation, collision
        Room::update()               - Enemy AI, animated tiles
        checkCollisions()            - Player vs enemies, items, room
        checkGameOver()              - Win/lose conditions
        
        // Render
        Screen::start()              - Prepare for drawing
        Room::renderMap()            - Draw tilemap
        Room::renderEnemies()        - Draw enemy sprites
        Room::renderItems()          - Draw item sprites
        Player::render()             - Draw player sprite
        renderScoreboard()           - Draw HUD
        Screen::render()             - Flush to GPU
    }
}
```

### 4.3 Resource Loading & Caching

```
Director::setFileList()
  └─ Resource::List::loadFromFile(config_path, PREFIX, system_folder_)
      ├─ Read config/assets.yaml                - Parse text configuration file
      ├─ Parse YAML structure: assets grouped by category
      ├─ Replace variables (${PREFIX}, ${SYSTEM_FOLDER})
      └─ Store in unordered_map (O(1) lookup) - Fast asset path retrieval

Game Scene initialization
  └─ Resource::Cache::init() - Loads all resources
      ├─ loadSounds()        - WAV files (with error handling)
      ├─ loadMusics()        - OGG files (with error handling)
      ├─ loadSurfaces()      - GIF/PNG images (with error handling)
      ├─ loadPalettes()      - PAL palette files (with error handling)
      ├─ loadTextFiles()     - Font definition files (with error handling)
      ├─ loadAnimations()    - YAML animation definitions (with error handling)
      └─ loadRooms()         - Room YAML files (with error handling)

      Note: Asset verification happens during actual loading.
            If a required file is missing, Cache::load() throws detailed exception.

During gameplay
  └─ Resource::Cache::get*(name) - Return cached resource
```

### 4.4 Input Flow

```
SDL_Event (from OS)
  ↓
Input::checkInput(action)
  ├─ Check keyboard bindings      - SDL_Scancode → InputAction
  ├─ Check gamepad bindings       - SDL_GamepadButton → InputAction
  └─ Return true if action active

Game logic uses checked inputs
  └─ Player responds to actions
```

### 4.5 Audio Control Flow

```
Game code
  ├─ Audio::playMusic(name, loop)
  ├─ Audio::playSound(name, group)
  └─ Audio::stopMusic()
      ↓
    Audio [wrapper/manager]
      ├─ Resource::getMusic(name)
      ├─ Resource::getSound(name)
      └─ jail_audio C library
          └─ SDL3 Audio device
```

---

## 5. Important Design Patterns & Conventions

### 5.1 Naming Conventions

**Classes:**
- `PascalCase` for classes: `Player`, `Room`, `Screen`, `Director`
- Suffix `Sprite` for sprite classes: `Sprite`, `AnimatedSprite`, `MovingSprite`

**Methods:**
- `get*()` for getters: `getWidth()`, `getRect()`
- `set*()` for setters: `setColor()`, `setPos()`
- `check*()` for boolean checks: `checkInput()`, `checkCollision()`
- `update()` for game logic updates
- `render()` for drawing

**Variables:**
- `snake_case` for member variables with `_` suffix: `x_`, `y_`, `sprite_`
- `UPPER_CASE` for constants: `BLOCK`, `MAX_VY`, `WIDTH`
- Private members: `private_member_`

**Structs for Data:**
- `XxxData` suffix: `PlayerData`, `RoomData`, `AnimationData`
- Used as initialization structures passed to constructors

### 5.2 Memory Management

- **Smart Pointers:** Uses `std::shared_ptr` for shared ownership (Surfaces, Sprites, Rooms)
- **Unique Pointers:** Uses `std::unique_ptr` for sole ownership (Director, local objects)
- **Raw Pointers:** Minimal use, mainly for singleton access or SDL objects
- **Static Allocation:** Singletons use static pointer pattern for RAII

### 5.3 Frame-Independent Physics

Uses `DeltaTimer` for delta time calculation:

```cpp
// In game loop
float delta = deltaTimer.tick();  // Get seconds since last frame

// Apply to physics
player.vy_ += gravity * delta;
player.y_ += player.vy_ * delta;
```

Provides **time scaling** for slow-motion effects.

### 5.4 Palette System

- 8-bit indexed color (256 colors per palette)
- Multiple palettes can be loaded and swapped via `PaletteManager`
- `Screen::setPaletteByName()` changes the active palette
- Supports palette sort modes (by luminosity, similarity to Spectrum palette, etc.)
- Supports color replacement per-render: `renderWithColorReplace()`
- CRT shader effects can modify colors in real-time

### 5.5 Configuration System

Game settings stored in configuration file:

```cpp
namespace Options {
    inline Video video{};           // Screen resolution, fullscreen, etc.
    inline Audio audio{};           // Music/sound volumes
    inline Notification notifications{};
    inline Cheat cheats{};          // Cheat codes
    inline ControlScheme keys{};    // Control mapping
    inline Stats stats{};           // Game statistics
}

Options::loadFromFile(path);  // Load from config.yaml
Options::saveToFile(path);    // Save on exit
```

### 5.6 Achievement System

```cpp
struct Achievement {
    int id;
    std::string caption;
    std::string description;
    int icon;
    bool completed;
    bool obtainable;
};

Cheevos::unlock(id);           // Unlock achievement
Cheevos::setUnobtainable(id);  // Lock achievement
Cheevos::saveToFile();         // Persist state
```

Achievements trigger notifications on unlock.

---

## 6. Technology Stack

### Core Technologies

| Component | Technology | Version | Role |
|-----------|-----------|---------|------|
| **Graphics** | SDL3 | Latest | Window, rendering, input |
| **GPU Rendering** | SDL3 GPU | Latest | Shader effects (CRT, post-processing via SPIR-V) |
| **Audio** | SDL3 Audio | Latest | Audio device, mixing |
| **Audio Decoding** | jail_audio (custom) | 1.x | OGG/WAV playback |
| **Image Loading** | stb_image | v2.x | PNG/GIF image loading |
| **Audio Decoding** | stb_vorbis | v1.x | OGG Vorbis support |
| **Language** | C++ | C++20 | Standard library features |
| **Build System** | CMake | 3.10+ | Cross-platform building |

### C++ Features Used

- **Smart Pointers:** `std::shared_ptr`, `std::unique_ptr`
- **Standard Containers:** `std::vector`, `std::array`
- **Modern Features:** `std::move`, lambda functions, constexpr
- **Namespaces:** Extensive use for organization
- **Inline Variables:** C++17 `inline` for global game state

### Platform Support

- **Windows:** MinGW/MSVC with SDL3
- **macOS:** Apple Clang, arm64 architecture, OpenGL
- **Linux:** GCC with SDL3 and OpenGL

---

## 7. Key Classes & Their Responsibilities

### Core System Classes

| Class | Purpose | Pattern |
|-------|---------|---------|
| `Director` | Main application controller, scene manager | Singleton |
| `Screen` | Rendering, window, palette management | Singleton |
| `Input` | Keyboard & gamepad input | Singleton |
| `Audio` | Music and SFX playback | Singleton |
| `Resource::Cache` | Asset caching and loading (with detailed error messages) | Singleton |
| `Resource::List` | Asset path registry from config/assets.yaml, O(1) lookups, variable substitution | Singleton |
| `PaletteManager` | Palette loading, switching, and sorting | Managed by Screen |
| `Debug` | Debug overlay information | Singleton |
| `globalEvents` | Global SDL event handling (quit, device reset, mouse) | Namespace |

### Game Logic Classes

| Class | Purpose |
|-------|---------|
| `Game` | Main gameplay scene, orchestrates update/render |
| `Player` | Player entity with physics and animation |
| `Room` | Level data, collision detection |
| `RoomLoader` | Room loading from YAML files |
| `TilemapRenderer` | Tilemap rendering |
| `CollisionMap` | Collision map data |
| `EnemyManager` | Enemy lifecycle management |
| `ItemManager` | Item lifecycle management |
| `Enemy` | Enemy entity behavior and rendering |
| `Item` | Collectible items |
| `Scoreboard` | HUD display data |
| `Cheevos` | Achievement unlock and state |
| `ItemTracker` | Tracks collected items |
| `RoomTracker` | Tracks visited rooms |

### Rendering Classes

| Class | Purpose |
|-------|---------|
| `Surface` | 8-bit indexed color pixel buffer with palette |
| `Sprite` | Renders a sprite region |
| `AnimatedSprite` | Frame-based animation rendering |
| `MovingSprite` | Sprite with velocity/position |
| `DissolveSprite` | Dissolve transition sprite |
| `Text` | Text rendering system |
| `Sdl3gpuShader` | SDL3 GPU shader compilation and effects |
| `PaletteManager` | Palette loading and management |

### Utility Classes

| Class/Header | Purpose |
|-------|---------|
| `DeltaTimer` | Frame-rate independent timing |
| `easing_functions.hpp` | Easing/interpolation functions for animations |

---

## 8. Common Development Workflows

### Adding a New Input Action

1. Add to `InputAction` enum in `core/input/input.hpp`
2. Bind in `Director::initInput()`:
   ```cpp
   Input::get()->bindKey(InputAction::NEW_ACTION, SDL_SCANCODE_X);
   ```
3. Check in game code:
   ```cpp
   if (Input::get()->checkInput(InputAction::NEW_ACTION)) {
       // Handle action
   }
   ```

### Adding a New Scene

1. Create class inheriting appropriate base (usually standalone `run()` method)
2. Add to `SceneManager::Scene` enum
3. Implement in `Director::run()` switch statement
4. Set `SceneManager::current` to transition

### Adding Game Assets

1. Place file in `data/` directory
2. Add entry to `config/assets.yaml` under the appropriate category:
   ```yaml
   assets:
     category_name:  # e.g., player, enemies, music, etc.
       - type: BITMAP
         path: ${PREFIX}/data/path/file.ext
   ```
   Available types: `DATA`, `BITMAP`, `ANIMATION`, `MUSIC`, `SOUND`, `FONT`, `ROOM`, `PALETTE`
3. Optional flags can be added:
   ```yaml
   - type: DATA
     path: ${SYSTEM_FOLDER}/file.txt
     required: false  # Don't fail if missing
     absolute: true   # Path is absolute
   ```
4. Resource loads automatically during `Resource::init()`
5. Access via: `Resource::Cache::get()->getSurface("name")`

**Note:** No recompilation needed when adding/removing/modifying assets in `config/assets.yaml`

### Modifying Collision Detection

1. Update `Room::setBottomSurfaces()`, `setLeftSlopes()`, etc.
2. Modify Player collision point generation in `Player::updateColliderPoints()`
3. Adjust tile classification in `TileType` enum
4. Test with debug visualization (F12 key)

---

## 9. Debug Features

### Available at Runtime

- **F12** - Toggle debug info overlay (FPS, player position, collision points)
- **F1/F2** - Decrease/increase window zoom
- **F3** - Toggle fullscreen mode
- **F4** - Toggle shader effects
- **F5/F6** - Next/previous palette
- **F7** - Toggle integer scaling
- **M** - Toggle music
- **B** - Toggle border display
- **P** - Pause game

### Debug Mode Compilation

In debug builds (`#ifdef DEBUG`), renders:
- Player collision boxes
- Collision point visualization
- Debug information overlay
- Special debug event handling

---

## 10. Performance Considerations

### Optimization Points

1. **Rendering:** Uses indexed color (8-bit) to reduce memory bandwidth
2. **Surfaces:** Shared smart pointers reduce copying
3. **Collision:** Pre-computed tile surface lists avoid per-frame searches
4. **Animation:** Frame-based animation reduces computation vs. bone systems
5. **Audio:** Cached music and sound effects, no runtime decoding
6. **Delta Time:** Frame-rate independent logic for smooth gameplay

### Known Limitations

- Single-threaded architecture (SDL3 requires single-thread rendering)
- Surfaces stored entirely in CPU memory (not GPU-side textures)
- Palette system requires full surface redraw when changing colors

---

## 11. File Format Reference

### Asset Configuration File (config/assets.yaml)
YAML-based asset registry with grouped structure:
```yaml
# JailDoctor's Dilemma - Asset Configuration
# Variables: ${PREFIX}, ${SYSTEM_FOLDER}

assets:
  # FONTS
  fonts:
    - type: BITMAP
      path: ${PREFIX}/data/font/smb2.gif
    - type: FONT
      path: ${PREFIX}/data/font/smb2.fnt

  # PLAYER
  player:
    - type: BITMAP
      path: ${PREFIX}/data/player/player.gif
    - type: ANIMATION
      path: ${PREFIX}/data/player/player.yaml

  # MUSIC
  music:
    - type: MUSIC
      path: ${PREFIX}/data/music/title.ogg

  # SYSTEM FILES (optional, absolute paths)
  system:
    - type: DATA
      path: ${SYSTEM_FOLDER}/config.yaml
      required: false
      absolute: true
```

**Asset Structure:**
- Assets are organized into categories (fonts, palettes, shaders, player, enemies, etc.)
- Each asset entry contains:
  - `type` - Asset type (required)
  - `path` - File path with variable substitution (required)
  - `required` - Whether file must exist (optional, default: `true`)
  - `absolute` - Whether path is absolute (optional, default: `false`)

**Available Asset Types:**
- `DATA` - General data files (text, JSON, etc.)
- `BITMAP` - Images (GIF, PNG)
- `ANIMATION` - Animation definition files (.yaml)
- `MUSIC` - Music files (OGG)
- `SOUND` - Sound effects (WAV)
- `FONT` - Font definition files
- `ROOM` - Room data files (.yaml)
- `PALETTE` - Color palette files (.pal)

**Variables:**
- `${PREFIX}` - Replaced with `/../Resources` on macOS bundles, empty otherwise
- `${SYSTEM_FOLDER}` - Replaced with user's system config folder

### Animation Files (.yaml)
YAML-based animation definitions with frame data:
```yaml
animations:
  - name: default
    frameWidth: 16
    frameHeight: 16
    speed: 100
    loop: 0
    frames: [...]
```

### Room Data Files (.yaml)
YAML-based room definitions:
```yaml
room:
  name_en: Starting Room
  bgColor: 0x000000
  connections: [...]
  tilemap: [...]
```

### Tilemap Files (.tmx)
Tiled map format with tileset and collision data.

### Palette Files (.pal)
Binary 256-color palette format (256 × 4 bytes RGBA).

---

## 12. Quick Reference: Main Entry Points

### For Graphics Issues
- `Screen::render()` - Main rendering method
- `Screen::setPaletteByName()` - Palette switching
- `PaletteManager` - Palette loading and sorting
- `Surface` class - Pixel buffer operations

### For Input Issues
- `Input::checkInput()` - Input state checking
- `Director::initInput()` - Binding configuration

### For Audio Issues
- `Audio::playMusic()` - Music playback
- `Audio::playSound()` - SFX playback
- `jail_audio` library - Low-level audio operations

### For Game Logic
- `Game::run()` - Main game loop
- `Room` class - Collision and level logic
- `Player::update()` - Physics and movement

### For Asset Management
- `config/assets.yaml` - Asset configuration file (text-based, no recompilation needed)
- `Resource::List::loadFromFile()` - Loads asset registry from config file
- `Resource::List::get()` - Retrieves asset path (O(1) lookup with unordered_map)
- `Resource::Cache` - Asset loading and caching
- `Director::setFileList()` - Calls `Resource::List::loadFromFile()` with PREFIX and system_folder

---

## 13. Future Enhancement Points

### Identified Areas for Expansion

1. **Network Play:** Stats upload to online service
2. **More Scenes:** Additional game modes
3. **Custom Rooms:** Level editor integration
4. **Audio Streaming:** Background music without loading entire file
5. **Particle System:** Visual effects for pickups/collisions
6. **Controller Feedback:** Haptic feedback for game events
7. **Accessibility:** Font scaling, color-blind modes, key remapping UI

---

## Development Notes

- **Language:** All code comments and some variable names are in Spanish (maintaining original author style)
- **Compilation:** Use CMake - automatically handles platform differences
- **Performance Profiling:** Use debug overlay (F12) for basic metrics; consider external profilers for deeper analysis
- **Common Warnings:** The codebase has been cleaned of the `struct`/`class` forward declaration inconsistency warnings that previously appeared

### Important Code Consistency Rules

1. **Forward Declarations:** Always use `class` for forward declarations of classes defined with `class` (not `struct`). The `Surface` class is defined as `class Surface` in `surface.hpp:57`, so all forward declarations must use `class Surface;`

2. **Singleton Pattern:** When creating new singletons, follow the existing pattern:
   - Private static instance pointer
   - Private constructor/destructor
   - Public `init()`, `destroy()`, and `get()` methods

3. **Delta Time:** Always use `DeltaTimer` for frame-rate independent physics calculations

4. **Memory Management:** Prefer `std::shared_ptr` for shared resources (Surfaces, Sprites) and `std::unique_ptr` for sole ownership

---

**Last Updated:** April 2026
**Original Author:** JailDesigner
**Repository:** Gitea (internal)
