# 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