overrun/AGENTS.md

200 lines
6.0 KiB
Markdown

# AGENTS.md - Agent Coding Guidelines
This file provides guidance for AI agents working on this codebase.
## Project Overview
This is a Phaser 3 HTML game (Smash TV-style top-down arena shooter) built with vanilla JavaScript and ES6 modules. No build tools or bundlers are used — the game runs directly in the browser.
## Running the Game
Since there is no bundler, serve the files with a local HTTP server (ES6 modules require HTTP, not `file://`):
```bash
npx serve .
# or
python3 -m http.server 8080
# or
./start_web.sh
```
Then open `http://localhost:8080` (or whatever port) in a browser.
## Build/Lint/Test Commands
This project has **no build tools, no linting, and no test framework**. It uses vanilla JavaScript with ES6 modules.
- **Run game**: `npx serve .` or `python3 -m http.server 8080` or `./start_web.sh`
- **No lint command**: Manually review code for style consistency
- **No test command**: No tests exist; manually verify functionality in browser
## Code Style Guidelines
### General Principles
- Keep code modular — each major concern in its own file/class
- Use ES6 `import`/`export` for all inter-module dependencies
- No TypeScript — plain JavaScript only
- No bundlers (Webpack, Vite, etc.)
### File Organization
```
js/
├── main.js # Entry point, game config
├── scenes/ # Phaser scenes (IntroScene, GameScene, GameOverScene)
├── entities/ # Game entities (Player, enemies)
│ └── enemies/ # Enemy classes (BaseEnemy, ChaseEnemy, etc.)
├── systems/ # Game systems (WaveManager, SkillTree, XPSystem)
├── ui/ # UI components (HUD, SkillTreeUI, Reticle)
└── data/ # JSON data files (zones.json, skillTree.json)
```
### Naming Conventions
- **Classes**: PascalCase (e.g., `Player`, `WaveManager`, `GameScene`)
- **Files**: PascalCase with .js extension (e.g., `Player.js`, `WaveManager.js`)
- **Constants**: UPPER_SNAKE_CASE (e.g., `BULLET_SPEED`, `TURN_RATE_DEG`)
- **Private methods**: underscore prefix (e.g., `_createAnims`, `_move`)
- **Private fields**: underscore prefix (e.g., `_fireCooldown`, `_isMoving`)
### Imports/Exports
- Use absolute paths from project root: `import { Player } from '../entities/Player.js';`
- Group imports at top of file
- Export classes as named exports: `export class Player { ... }`
### Formatting
- 2 spaces for indentation
- No semicolons at statement end (optional in JS)
- Use template literals for string interpolation: `` `Player at ${x}, ${y}` ``
- Use const for all variables that don't change
- Use let for mutable variables, avoid var
### Code Structure
#### Class Structure Example
```javascript
const CONSTANT_VALUE = 100;
export class MyClass {
constructor(scene, x, y) {
this.scene = scene;
this.x = x;
this.y = y;
this._privateField = 0;
this._setup();
}
_setup() {
// initialization
}
update(delta) {
this._updatePhysics(delta);
this._updateAnimation();
}
_updatePhysics(delta) {
// physics logic
}
_updateAnimation() {
// animation logic
}
publicMethod() {
// public API
}
destroy() {
// cleanup
}
}
```
### Error Handling
- No try/catch blocks required for simple operations
- Use Phaser's built-in error handling where applicable
- Log errors to console for debugging: `console.warn('message')` or `console.error('message')`
- Validate inputs at function entry points when needed
### Phaser-Specific Patterns
- Extend Phaser classes: `export class GameScene extends Phaser.Scene`
- Use `this.scene` reference to access scene in entity classes
- Use `this.add.*` for creating game objects
- Use `this.physics.add.*` for physics objects
- Use `this.events.emit()` and `this.events.on()` for event-driven communication
- Use Phaser's built-in groups: `this.add.group()`, `this.physics.add.group()`
### Data Files (JSON)
- Store game data in `js/data/` directory
- Examples: `zones.json`, `skillTree.json`
- Load via: `this.load.json('key', 'path')` then `this.cache.json.get('key')`
### Adding New Features
#### Adding a New Enemy Type
1. Create new file in `js/entities/enemies/`
2. Extend `BaseEnemy` or create new class
3. Implement required methods: `update()`, `takeDamage()`, `attack()`
4. Register in wave definitions (zones.json)
#### Adding a New Skill
1. Add skill definition to `js/data/skillTree.json`
2. Define node id, parent, effect (stat, add/multiply values)
3. Implement effect logic in `SkillTree.applyNode()`
#### Adding a New Scene
1. Create new file in `js/scenes/`
2. Extend `Phaser.Scene`
3. Implement `preload()`, `create()`, `update()` methods
4. Add to scene array in `js/main.js` config
### Important Patterns
#### Player Stats Object
```javascript
this.stats = {
speed: 200,
damage: 20,
fireRate: 1,
damageReduction: 0,
maxHp: 100,
};
```
- Stats are modified by skill tree
- Use getters/setters for x, y position from sprite
#### Event Communication
```javascript
// Emitting events
this.events.emit('enemy-killed', { xp: 10 });
this.events.emit('level-up', newLevel);
// Listening events
this.events.on('enemy-killed', ({ xp }) => { ... });
```
#### Physics Collisions
```javascript
this.physics.add.collider(playerSprite, enemyGroup);
```
### Browser Testing
- Open browser devtools (F12)
- Use Console for logging and debugging
- Use Network tab to verify asset loading
- Use Elements tab to inspect game canvas
### Common Issues
- **Modules not loading**: Ensure running via HTTP server, not file://
- **Assets not loading**: Check paths are relative to web root
- **Physics not working**: Ensure physics config in game config and physics added to objects
### Code Review Checklist
- [ ] ES6 imports/exports used correctly
- [ ] File naming follows PascalCase convention
- [ ] Constants use UPPER_SNAKE_CASE
- [ ] Private methods/fields use underscore prefix
- [ ] No console.log in production code (use console.warn for warnings)
- [ ] Code follows existing patterns in similar files
- [ ] New files added to appropriate directory structure
- [ ] JSON data files are valid