rust_pixel 1.0.8

2d pixel-art game engine & rapid prototype tools support terminal, wgpu, sdl2 and web...
Documentation
# CLAUDE.md

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

## Project Overview

RustPixel is a 2D game engine and rapid prototyping toolkit supporting both text and graphics rendering modes. It can compile to native binaries, FFI libraries, and WASM for web deployment.

- **Text Mode**: Uses `crossterm` for terminal rendering with ASCII/Unicode/Emoji
- **Graphics Mode**: Uses `wgpu`, `glow`, or `sdl2` for hardware-accelerated rendering with PETSCII/custom symbols
- **Web Mode**: Compiles to WASM with WebGL backend

## Build Commands

### Using cargo-pixel CLI

First-time setup (install from crates.io):
```bash
cargo install rust_pixel
cargo pixel  # First run clones repo to ~/rust_pixel_work
```

Or install from local source:
```bash
cargo install --path . --force
```

### Running Applications

```bash
# Run in terminal mode
cargo pixel run <app> term
cargo pixel r <app> t  # shorthand

# Run in SDL/graphics mode
cargo pixel run <app> sdl
cargo pixel r <app> s  # shorthand

# Run in Glow mode (winit + OpenGL)
cargo pixel r <app> glow
cargo pixel r <app> g  # shorthand

# Run in WGPU mode (winit + wgpu)
cargo pixel r <app> wgpu
cargo pixel r <app> wg  # shorthand

# Run in web mode (starts server on localhost:8080)
cargo pixel run <app> web
cargo pixel r <app> w  # shorthand
cargo pixel r <app> w --webport 8081  # custom port
cargo pixel r <app> w -r  # release mode

# Examples
cargo pixel r snake t
cargo pixel r tetris s -r
cargo pixel r tower w
cargo pixel r petview g -r
```

### Creating New Applications

```bash
# Create app in ./apps/ using template
cargo pixel c mygame

# Create standalone app in different directory
cargo pixel c myapp ..
cd ../myapp
cargo pixel r myapp t
```

### Tools

```bash
# palette: Terminal UI color tool
cargo pixel r palette t -r

# edit: Character art editor
cargo pixel edit term . assets/logo.txt
cargo pixel e t . assets/logo.txt
cargo pixel edit sdl . assets/logo.pix
cargo pixel e s . assets/logo.pix

# petii: Convert images to PETSCII art
cargo pixel p assets/image.png > output.pix
cargo pixel p assets/image.png 40 25 > output.pix

# ssf: Preview PETSCII animations
cargo pixel ssf . assets/animation.ssf

# cg: Convert GIF to PETSCII animation
cargo pixel cg assets/input.gif assets/output.ssf 40 25

# symbol: Generate symbol atlas from image
cargo pixel sy image.png 8

# ttf: Generate font texture from TTF
cargo pixel tf font.ttf output.png 8
```

### Testing

Run tests for specific apps or the core library:
```bash
# Test core library
cargo test

# Test specific app
cd apps/<app_name>
cargo test
```

## Architecture

### Core Design Pattern: Model-Render-Game

Every RustPixel application follows this pattern:

```
Game (orchestrator)
├── Model (game logic and state)
│   ├── init()
│   ├── update()
│   ├── handle_event()
│   ├── handle_timer()
│   ├── handle_input()
│   └── handle_auto()
└── Render (visual output)
    ├── init()
    ├── draw()
    ├── handle_event()
    └── handle_timer()
```

### Project Structure

```
rust_pixel/
├── src/                    # Core engine code
│   ├── algorithm/          # Pathfinding, disjoint-set, etc.
│   ├── event/              # Event system and timers
│   ├── render/             # Rendering subsystem
│   │   ├── adapter/        # Platform-specific adapters
│   │   │   ├── cross_adapter.rs      # Terminal mode
│   │   │   ├── sdl_adapter.rs        # SDL2 mode
│   │   │   ├── winit_glow_adapter.rs # Winit + OpenGL
│   │   │   ├── winit_wgpu_adapter.rs # Winit + WGPU
│   │   │   └── web_adapter.rs        # WASM/WebGL
│   │   ├── buffer.rs       # Screen buffer
│   │   ├── cell.rs         # Base rendering unit
│   │   ├── panel.rs        # Layered drawing surface
│   │   └── sprite.rs       # Sprite management
│   ├── ui/                 # Terminal UI framework
│   ├── util/               # Common utilities
│   ├── asset.rs            # Asset loading (.pix, .ssf, .esc)
│   ├── audio.rs            # Audio playback
│   ├── context.rs          # Shared runtime state
│   ├── game.rs             # Game loop implementation
│   ├── init.rs             # Asset initialization (GameConfig, texture loading)
│   ├── macros.rs           # app! macro for scaffolding applications
│   └── lib.rs              # Main entry point and re-exports
├── apps/                   # Demo games and applications
│   ├── template/           # Template for new apps
│   ├── tetris/
│   ├── snake/
│   ├── poker/
│   │   ├── ffi/            # C FFI bindings example
│   │   └── wasm/           # WASM bindings example
│   └── ...
├── tools/                  # Utilities
│   ├── cargo-pixel/        # CLI build tool
│   ├── asset/              # Asset packer
│   ├── edit/               # Character art editor
│   ├── petii/              # Image to PETSCII converter
│   ├── ssf/                # Animation format tool
│   └── ...
└── Cargo.toml              # Workspace configuration
```

### Application Structure

Each app follows this layout:

```
apps/my_game/
├── src/
│   ├── lib.rs              # Uses app! macro
│   ├── main.rs             # Native entry point
│   ├── model.rs            # Game state and logic
│   ├── render_terminal.rs  # Terminal rendering
│   └── render_graphics.rs  # Graphics rendering
├── lib/                    # Optional: core algorithms as library
│   └── src/
│       └── lib.rs
├── ffi/                    # Optional: C FFI bindings
├── wasm/                   # Optional: WASM bindings
├── assets/                 # Game assets
├── build.rs                # Build script for asset embedding
└── Cargo.toml
```

### Key Abstractions

**Panel**: Multi-layer drawing surface supporting both text and graphics modes
- Contains multiple layers, each holding sprites
- Handles z-order rendering and dirty region tracking
- Unified API across all rendering backends

**Sprite**: Positioned drawable element
- Contains a Buffer with Cells
- Can be static or animated
- Supports pixel-perfect positioning in graphics mode

**Cell**: Smallest rendering unit
- In text mode: a Unicode character with foreground/background colors
- In graphics mode: a glyph from a texture atlas (PETSCII, ASCII, or custom)

**Buffer**: 2D array of Cells with efficient diff-based updates

**Context**: Shared runtime state passed through the game loop
- Contains the active Adapter
- Manages input events, timers, and global state
- Provides access to AssetManager for loading resources

### Rendering Adapters

Each adapter implements platform-specific rendering:

- **CrossAdapter** (terminal): Direct terminal I/O with crossterm
- **SdlAdapter** (SDL2): Hardware-accelerated OpenGL via SDL2
- **WinitGlowAdapter** (Winit + Glow): Portable OpenGL via winit
- **WinitWgpuAdapter** (WGPU): Modern GPU API (Vulkan/Metal/DX12)
- **WebAdapter** (Web): WebGL via WASM

All adapters expose the same `Adapter` trait interface, allowing games to work across platforms without modification.

### The app! Macro

The `app!` macro in `src/macros.rs` scaffolds the application entry point:
- Generates the `{Name}Game` struct wrapping `Game<Model, Render>`
- Creates `init_game()` and `run()` functions
- Provides WASM exports (`new()`, `tick()`, `key_event()`, `wasm_init_pixel_assets()`) for web builds
- Conditionally compiles `render_terminal` or `render_graphics` modules based on build features

Example usage in app's `lib.rs`:
```rust
use rust_pixel::app;
app!(MyGame);
```

### Features and Conditional Compilation

```toml
# Cargo.toml features
default = ["log4rs", "crossterm", "rodio", "image"]
term = ["log4rs", "crossterm", "rodio", "image"]
sdl = ["log4rs", "rodio", "sdl2", "image"]
glow = ["log4rs", "rodio", "winit", "glutin", "glutin-winit", "raw-window-handle", "image"]
wgpu = ["log4rs", "rodio", "wgpu", "bytemuck", "pollster", "winit", "glutin", "glutin-winit", "raw-window-handle", "image"]
web = ["image"]
base = ["log4rs"]  # Minimal build for FFI/WASM libraries
```

The `cargo-pixel` tool automatically sets these features based on the mode argument.

### Asset System

RustPixel uses custom asset formats:
- **.pix**: PETSCII images (binary format with color info)
- **.ssf**: PETSCII animations (sequence of .pix frames)
- **.esc**: Escape-sequence based terminal graphics
- Standard formats: .png, .jpg, .mp3 for audio

Assets are loaded via `AssetManager` in `Context`, which supports both synchronous and asynchronous loading for WASM compatibility.

### Event System

Two event mechanisms:
1. **Input events**: Keyboard, mouse, window events stored in `context.input_events`
2. **Timer events**: Global timer system via `event::timer_register()` / `timer_update()`

Events are processed in the Model's `handle_event()` and `handle_timer()` methods.

## Development Workflow

### Adding a New Game

1. Create from template:
   ```bash
   cargo pixel c my_game
   ```

2. Implement game logic in `apps/my_game/src/`:
   - `model.rs`: Define state struct and implement `Model` trait
   - `render_terminal.rs`: Implement terminal rendering
   - `render_graphics.rs`: Implement graphics rendering
   - `lib.rs`: Call `pixel_game!(MyGame)` macro

3. Add assets to `apps/my_game/assets/`

4. Test in different modes:
   ```bash
   cargo pixel r my_game t
   cargo pixel r my_game s
   cargo pixel r my_game w
   ```

### Building for Web

Apps with WASM support have a `wasm/` directory:

```bash
cd apps/my_game/wasm
make run  # Builds WASM and starts local server
```

The WASM build uses `wasm-pack` and integrates with JavaScript via the web template in `web-templates/`.

### Creating FFI Bindings

Apps with FFI support have an `ffi/` directory with:
- `cbindgen.toml`: Configuration for C header generation
- `Makefile`: Build C/Python examples

```bash
cd apps/poker/ffi
make run  # Builds library and runs C++/Python examples
```

### Extending the Engine

To add a new rendering adapter:
1. Create `src/render/adapter/my_adapter.rs`
2. Implement the `Adapter` trait
3. Add feature flags in `Cargo.toml`
4. Update `cargo-pixel` to support the new mode

To add new asset formats:
1. Add loading logic to `src/asset.rs`
2. Update `AssetManager` to handle the format
3. Add conversion tools to `tools/` if needed

## Notes

- The main branch is `main`
- Minimum Rust version: 1.71+
- The engine uses a fixed 60 FPS game loop (configurable via `GAME_FRAME` constant)
- Graphics mode supports PETSCII character sets and custom symbol atlases
- The terminal UI system works in both terminal and graphics modes
- All rendering is done through the unified Panel/Sprite/Buffer abstraction