6.0 KiB
6.0 KiB
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://):
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 .orpython3 -m http.server 8080or./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/exportfor 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
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')orconsole.error('message') - Validate inputs at function entry points when needed
Phaser-Specific Patterns
- Extend Phaser classes:
export class GameScene extends Phaser.Scene - Use
this.scenereference to access scene in entity classes - Use
this.add.*for creating game objects - Use
this.physics.add.*for physics objects - Use
this.events.emit()andthis.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')thenthis.cache.json.get('key')
Adding New Features
Adding a New Enemy Type
- Create new file in
js/entities/enemies/ - Extend
BaseEnemyor create new class - Implement required methods:
update(),takeDamage(),attack() - Register in wave definitions (zones.json)
Adding a New Skill
- Add skill definition to
js/data/skillTree.json - Define node id, parent, effect (stat, add/multiply values)
- Implement effect logic in
SkillTree.applyNode()
Adding a New Scene
- Create new file in
js/scenes/ - Extend
Phaser.Scene - Implement
preload(),create(),update()methods - Add to scene array in
js/main.jsconfig
Important Patterns
Player Stats Object
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
// 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
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