diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f858ba9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,366 @@ +# AI Agent Instructions for TS-Games + +This document provides guidelines for AI agents working with the TS-Games project. + +## Project Overview + +TS-Games is a custom framework/build system for creating simple single-file TypeScript games. All games compile into one standalone HTML file with no external dependencies—all assets are inlined as data URLs. + +## Key Concepts + +### Two Types of Applications + +1. **Games** - Interactive applications with game loops + - Located in `src/games//` + - Entry point: `index.ts` or `index.tsx` + - Default export: `runGame()` function + - Use `gameLoop()` from `@common/game` for structured game development + +2. **Apps** - More complex applications (like AI-Story) + - Also located in `src/games//` + - Entry point: `index.tsx` + - Default export: `main()` function + - May use Preact components and complex state management + +### Single HTML File Architecture + +- All games build into a single `.html` file in `dist/` +- No external dependencies at runtime +- All assets (images, audio, fonts, WASM) are inlined as base64 data URLs +- Build process uses Bun's plugin system to transform assets + +## Creating a New Game + +### Step 1: Create Directory Structure + +```bash +mkdir -p src/games//assets +``` + +### Step 2: Create Entry Point + +Create `src/games//index.ts` or `index.tsx`: + +```typescript +// Simple game example (index.ts) +import { gameLoop } from "@common/game"; +import Input from "@common/input"; + +const setup = () => { + // Initialize game state + return { x: 0, y: 0 }; +}; + +const frame = (dt: number, state: ReturnType) => { + // Update game state + state.x += Input.getHorizontal() * dt; + state.y += Input.getVertical() * dt; +}; + +export default gameLoop(setup, frame); +``` + +```tsx +// Preact component example (index.tsx) +import { render } from "preact"; +import App from "./components/app"; + +export default function main() { + render(, document.body); +} +``` + +### Step 3: Add Assets (Optional) + +Place assets in `src/games//assets/`: + +- **Images**: `.png`, `.jpg`, `.jpeg` → Import as `HTMLImageElement` +- **Audio**: `.wav`, `.mp3`, `.ogg` → Import as `HTMLAudioElement` +- **CSS**: `.css`, `.module.css` → Import as styles +- **Fonts**: `.font.css` → Import font faces +- **WASM**: `.c`, `.cpp`, `.wasm` → Import as WASM module +- **Icons**: `favicon.ico` → Auto-used as page icon +- **PWA**: `pwa_icon.png` → Used for PWA manifest + +### Step 4: Import Assets + +```typescript +// Import image +import spritesheet from './assets/spritesheet.png'; +console.log(spritesheet); // + +// Import audio +import heal from './assets/heal.ogg'; +heal.play(); + +// Import CSS +import './assets/styles.css'; + +// Import CSS modules +import styles from './assets/styles.module.css'; +
+ +// Import WASM (C/C++) +import wasmModule from './assets/game.c'; +// Access exports: wasmModule.memory, wasmModule.functionName() + +// Import GLSL shader +import shader from './assets/shader.glsl'; +``` + +## Development Workflow + +### Running Development Server + +```bash +bun start +``` + +Navigate to `http://localhost:3000` to see the game list. Games rebuild on each page reload. + +To run a specific game: +```bash +bun start --game= +``` + +### Building for Production + +Build a specific game: +```bash +bun run build +``` + +Or select from interactive list: +```bash +bun run build +``` + +Output: `dist/.html` + +### Building with Options + +- `--local`: Build for local testing (no PWA, different index) +- `--production`: Minify JS/CSS/HTML (default for build) + +## Project Structure + +``` +tsgames/ +├── src/ +│ ├── games/ # All games/apps live here +│ │ ├── / # Individual game directory +│ │ │ ├── index.ts # Entry point (required) +│ │ │ └── assets/ # Game assets +│ │ └── index/ # Special: game list page +│ ├── common/ # Shared utilities +│ │ ├── game.ts # Game loop helper +│ │ ├── input.ts # Input handling +│ │ ├── dom.ts # DOM utilities +│ │ ├── utils.ts # General utilities +│ │ ├── errors.ts # Error formatting +│ │ ├── components/ # Shared Preact components +│ │ ├── hooks/ # React-like hooks +│ │ ├── display/ # Canvas/graphics utilities +│ │ └── physics/ # Physics utilities +│ └── types.d.ts # Global type definitions +├── build/ +│ ├── build.ts # Build script +│ ├── server.ts # Dev server +│ ├── html.ts # HTML generation +│ ├── isGame.ts # Game detection +│ ├── imagePlugin.ts # Image bundler plugin +│ ├── audioPlugin.ts # Audio bundler plugin +│ ├── fontPlugin.ts # Font bundler plugin +│ ├── wasmPlugin.ts # WASM bundler plugin +│ └── filePlugin.ts # Generic file plugin +├── dist/ # Built HTML files +└── test/ # Tests +``` + +## Technical Details + +### Bun Configuration + +- Use `bun` for all package management and script running +- `.env` files are automatically loaded (no dotenv needed) +- Use `Bun.serve()` for servers (not express) +- Use `Bun.file()` for file operations (not fs) +- Use `Bun.$` for shell commands (not execa) + +### TypeScript Configuration + +- JSX: `react-jsx` with Preact +- Module resolution: `bundler` +- Path aliases: `@common/*` → `./src/common/*` +- Strict mode enabled + +### Asset Processing + +All asset processing happens at build time via Bun plugins: + +1. **Images** (`.png`, `.jpg`, `.jpeg`): + - Converted to base64 data URLs + - Return `HTMLImageElement` that's ready to use + +2. **Audio** (`.wav`, `.mp3`, `.ogg`): + - Converted to base64 data URLs + - Return `HTMLAudioElement` with loaded source + +3. **CSS**: + - Bundled and inlined in `