Add project documentation (README.md) and AI agent guidelines (AGENTS.md)
This commit is contained in:
parent
e0a6e6d116
commit
d0b7b79af0
|
|
@ -0,0 +1,199 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
# Overrun
|
||||
|
||||
A Smash TV-style top-down arena shooter built with Phaser 3.
|
||||
|
||||
## Overview
|
||||
|
||||
Overrun is a fast-paced twin-stick shooter where you battle waves of enemies across multiple zones. Kill enemies to earn XP, level up, and unlock powerful skills from a branching skill tree.
|
||||
|
||||
## How to Play
|
||||
|
||||
### Running the Game
|
||||
|
||||
Since the game uses ES6 modules, it must be served over HTTP (not `file://`):
|
||||
|
||||
```bash
|
||||
# Option 1: Using npx
|
||||
npx serve .
|
||||
|
||||
# Option 2: Using Python
|
||||
python3 -m http.server 8080
|
||||
|
||||
# Option 3: Using the provided script
|
||||
./start_web.sh
|
||||
```
|
||||
|
||||
Then open `http://localhost:8080` in your browser.
|
||||
|
||||
### Controls
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| **W / A / S / D** | Move player |
|
||||
| **Mouse** | Aim direction |
|
||||
| **Left Click** | Fire weapon |
|
||||
| **R** | Restart (on game over) |
|
||||
|
||||
### Gameplay
|
||||
|
||||
- **Lives**: Start with 3 lives, 100 HP per life
|
||||
- **XP & Leveling**: Earn XP by killing enemies. When you level up, the game pauses and you can pick a skill
|
||||
- **Zones**: Progress through multiple zones, each with increasingly difficult enemy waves
|
||||
- **Victory**: Complete all zones to win
|
||||
|
||||
### Skill Tree
|
||||
|
||||
The skill tree branches into two main paths:
|
||||
|
||||
**Defense**
|
||||
- Take 10% less damage (and additional upgrades)
|
||||
|
||||
**Offense**
|
||||
- Increase damage by 20%
|
||||
- Increase fire rate by 40%
|
||||
|
||||
New skills can be added by editing `js/data/skillTree.json`.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
overrun/
|
||||
├── index.html # Entry HTML file
|
||||
├── main.js # Game entry point, Phaser config
|
||||
├── phaser.min.js # Phaser 3 library (minified)
|
||||
├── start_web.sh # Convenience script to start server
|
||||
│
|
||||
├── js/
|
||||
│ ├── main.js # Phaser game configuration
|
||||
│ ├── scenes/ # Game scenes
|
||||
│ │ ├── IntroScene.js
|
||||
│ │ ├── GameScene.js
|
||||
│ │ └── GameOverScene.js
|
||||
│ │
|
||||
│ ├── entities/ # Game entities
|
||||
│ │ ├── Player.js
|
||||
│ │ └── enemies/
|
||||
│ │ ├── BaseEnemy.js
|
||||
│ │ ├── ChaseEnemy.js
|
||||
│ │ ├── BomberEnemy.js
|
||||
│ │ ├── SprayerEnemy.js
|
||||
│ │ ├── ShooterEnemy.js
|
||||
│ │ └── SwarmerEnemy.js
|
||||
│ │
|
||||
│ ├── systems/ # Game systems
|
||||
│ │ ├── WaveManager.js
|
||||
│ │ ├── SkillTree.js
|
||||
│ │ ├── XPSystem.js
|
||||
│ │ └── BarrierManager.js
|
||||
│ │
|
||||
│ ├── ui/ # UI components
|
||||
│ │ ├── HUD.js
|
||||
│ │ ├── SkillTreeUI.js
|
||||
│ │ └── Reticle.js
|
||||
│ │
|
||||
│ └── data/ # JSON data files
|
||||
│ ├── zones.json
|
||||
│ └── skillTree.json
|
||||
│
|
||||
└── assets/
|
||||
└── sprites/ # Game sprites (player, enemies)
|
||||
```
|
||||
|
||||
## Enemy Types
|
||||
|
||||
| Enemy | Behavior |
|
||||
|-------|----------|
|
||||
| **Chaser** | Directly pursues the player |
|
||||
| **Swarmer** | Fast, erratic movement in groups |
|
||||
| **Shooter** | Fires projectiles at the player |
|
||||
| **Sprayer** | Fires multiple projectiles in a spread |
|
||||
| **Bomber** | Explodes on contact or when near player |
|
||||
|
||||
## Development
|
||||
|
||||
### Adding New Enemies
|
||||
|
||||
1. Create a new file in `js/entities/enemies/`
|
||||
2. Extend `BaseEnemy` or create a new class
|
||||
3. Implement `update()`, `takeDamage()`, and `attack()` methods
|
||||
4. Register the enemy in `js/data/zones.json`
|
||||
|
||||
### Adding New Skills
|
||||
|
||||
1. Edit `js/data/skillTree.json`
|
||||
2. Add a new node with:
|
||||
- `id`: Unique identifier
|
||||
- `parent`: ID of the parent node (or `null` for root)
|
||||
- `effect`: Object with `stat`, `add`, and/or `multiply` values
|
||||
|
||||
### Adding New Zones
|
||||
|
||||
Edit `js/data/zones.json` to define new zones with increasing difficulty.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Phaser 3** - Game framework
|
||||
- **Vanilla JavaScript** - No bundlers, ES6 modules
|
||||
- **No build tools** - Runs directly in browser
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
Loading…
Reference in New Issue