# New game

Copy the sandbox pattern; do not reimplement locomotion.

## Quick start

1. Copy `src/games/template.js` to `src/games/my-game.js`
2. Implement `createMyGame(canvas)` — level geometry, game rules, UI
3. Point `src/main.js` at your module:

```js
import { createMyGame } from "./games/my-game.js";

const canvas = document.getElementById("canvas");
createMyGame(canvas);
```

4. Run: `php -S localhost:8080` → http://localhost:8080/game.html

## What to keep

Always wire these the same way as `src/sandbox.js`:

- `createEngine`, `createInputManager`, `createPhysicsWorld`
- `createEnvironment`, `createMaterialLibrary`
- `createCharacterModel`, `createPlayer`
- Matching colliders for every solid mesh (`physics.addStaticBox`)
- `engine.onUpdate` hooks only for _your_ game logic — movement is inside `createPlayer`

## What to change

- Ground size, obstacles, materials, environment preset
- `settings` defaults and lil-gui folders (or remove GUI)
- Game state, win/lose, NPCs, pickups — in your module’s closures or small FP modules
- `game.html` title and `#hint` text

## HTML page

Reuse `game.html` import map (Three.js 0.185 WebGPU, Jolt 1.1.0, lil-gui CDN). Swap title/hint as needed. One canvas, one module entry.

Vehicles: `createVehicle` after the player — see [vehicle-module.md](./vehicle-module.md).  
Water / boat: [water-module.md](./water-module.md). Carry / inventory: [interaction-module.md](./interaction-module.md).

Pass `engine` to `createInputManager(canvas, engine)` so `wasPressed` works.

## Checklist

- [ ] Every walkable surface has a static collider aligned with the mesh
- [ ] Character spawn is handled by `createPlayer` (no custom height math needed)
- [ ] `input.setLookMode(settings.lookMode)` on boot
- [ ] Resize handler calls `engine.resize(canvas.clientWidth, canvas.clientHeight)`
- [ ] `await engine.start()` after setup

See [walking-module.md](./walking-module.md) for full API reference.
