- README: installation, dev server, gameplay controls, screens, sound - AGENTS.md: project structure, stack, implementation patterns, git workflow
72 lines
2.5 KiB
Markdown
72 lines
2.5 KiB
Markdown
# Working in The Clanked Game
|
||
|
||
## Stack
|
||
|
||
- **React 19** — UI rendering
|
||
- **Vite 8** — Dev server and build tooling
|
||
- **WebAudio API** — All sound synthesis (no audio files)
|
||
- **pnpm** — Package manager
|
||
|
||
## Project Layout
|
||
|
||
```
|
||
src/
|
||
App.jsx — Root component, screen state (home/main-menu/game)
|
||
components/
|
||
Game.jsx — Core game loop: canvas rendering, state, collision, input
|
||
soundEffects.js — WebAudio sound synthesis functions
|
||
```
|
||
|
||
## Key Implementation Notes
|
||
|
||
- The game loop runs in `Game.jsx` via `requestAnimationFrame`. All game logic (`updateStars`, `updatePlayer`, `updateAliens`, `checkCollisions`, etc.) is defined inside the `useEffect` and operates on `gameStateRef.current`.
|
||
- Sound effects use the WebAudio API and are stateless helpers in `soundEffects.js`. Call `getAudioContext()` lazily on first use (browser autoplay policy).
|
||
- Shields are stored as 2D boolean grids (pixel-level destruction without canvas complexity).
|
||
- The canvas renders at **800×600** (`CANVAS_WIDTH`, `CANVAS_HEIGHT`).
|
||
|
||
## Adding Sound Effects
|
||
|
||
Functions in `soundEffects.js` follow the same pattern:
|
||
|
||
```js
|
||
export const playXSound = () => {
|
||
const ctx = getAudioContext();
|
||
const currentTime = ctx.currentTime;
|
||
|
||
const oscillator = ctx.createOscillator();
|
||
const gainNode = ctx.createGain();
|
||
|
||
oscillator.type = 'square'; // or 'sine', 'sawtooth', or white noise via AudioBuffer
|
||
// configure frequency...
|
||
// configure gain envelope...
|
||
oscillator.connect(gainNode);
|
||
gainNode.connect(ctx.destination);
|
||
|
||
oscillator.start(currentTime);
|
||
oscillator.stop(currentTime + duration);
|
||
};
|
||
```
|
||
|
||
For white noise, create an `AudioBuffer` filled with `Math.random() * 2 - 1` values and use a `BufferSourceNode`.
|
||
|
||
## Adding Gameplay Features
|
||
|
||
- New game state fields go in `gameStateRef.current` (line ~95).
|
||
- New per-frame update functions follow `updateStars`, `updatePlayer`, etc. pattern and are called in the game loop in order.
|
||
- New draw functions follow `drawStars`, `drawPlayer`, etc. pattern and are called in the render section of `gameLoop()`.
|
||
- Screen transitions happen via `setCurrentScreen()` in `App.jsx` — pass an `onExit` callback from `Game` to return to main menu.
|
||
|
||
## Git Workflow
|
||
|
||
- Branch: `develop`
|
||
- Push to `origin/develop` after meaningful changes.
|
||
|
||
## npm Scripts
|
||
|
||
| Command | Description |
|
||
|---------|-------------|
|
||
| `pnpm dev` | Start Vite dev server with HMR |
|
||
| `pnpm build` | Production build to `dist/` |
|
||
| `pnpm lint` | Run ESLint |
|
||
| `pnpm preview` | Preview production build locally |
|