New System Skill
Scaffolds new game systems implementing the ISystem interface.
Invocation
User-only: /new-system <SystemName>
Example: /new-system CollisionSystem
System Pattern
All systems implement ISystem from src/game/systems/ISystem.ts and follow these conventions:
Required Structure
import { YOUR_CONFIG } from "../config/GameConfig"
import { ISystem } from "./ISystem"
export class SystemNameSystem implements ISystem {
private scene: Phaser.Scene | null
private dependency1: Type | null
// ... other dependencies as null-initialized
constructor(scene: Phaser.Scene, dependency1: Type) {
this.scene = scene
this.dependency1 = dependency1
this.setupEventListeners()
}
private setupEventListeners() {
if (!this.scene) return
this.scene.events.on('event-name', this.handleEventName, this)
this.scene.events.on(Phaser.Scenes.Events.UPDATE, this.update, this)
}
private update() {
if (!this.scene || this.scene.physics.world.isPaused) return
// Per-frame logic
}
private handleEventName(data: EventDataType) {
if (!this.scene) return
// Event handling logic
}
destroy() {
if (this.scene) {
this.scene.events.off('event-name', this.handleEventName, this)
this.scene.events.off(Phaser.Scenes.Events.UPDATE, this.update, this)
}
// Clear collections
// this.collection.clear()
// Null all references
this.dependency1 = null
this.scene = null
}
}
Key Patterns
- •
ISystem interface: Must implement
destroy(): voidmethod - •
Null-initialized properties: All dependencies stored as
Type | nulland initialized to the passed value in constructor - •
setupEventListeners(): Separate method for registering all event listeners, called from constructor
- •
Handler naming: Event handlers named
handle*(e.g.,handleWaveStarted,handleEnemyDestroyed) - •
Null guards: Every method checks
if (!this.scene) returnat the start - •
Pause awareness: Update methods check
this.scene.physics.world.isPausedwhen appropriate - •
destroy() cleanup order:
- •Unregister all listeners with
.off()and same handler reference - •Clear any Maps/Sets/Arrays
- •Set all dependencies to
null - •Set
this.scene = nulllast
- •Unregister all listeners with
GameScene Integration
Systems are instantiated in GameScene.create() and destroyed in shutdown():
// In GameScene.ts // Property declaration private _mySystem: MySystem | undefined // In create() this._mySystem = new MySystem(this, dependency1, dependency2) // In shutdown() this._mySystem?.destroy() this._mySystem = undefined
Reference Files
- •ISystem interface:
src/game/systems/ISystem.ts - •Simple system:
src/game/systems/WaveSystem.ts - •Complex system:
src/game/systems/PowerUpSystem.ts - •State system:
src/game/systems/PlayerPowerUpState.ts - •GameScene integration:
src/game/scenes/GameScene.ts
Common Events
| Event | Payload | Purpose |
|---|---|---|
score-changed | { score } | Score updates |
enemy-destroyed | { points, x, y } | Enemy death |
player-hit | - | Player damage |
wave-started | { currentWave, scoreInWave, scoreRequired, spawnRate, enemyVelocity } | New wave |
wave-difficulty-changed | { spawnRate, enemyVelocity } | Difficulty scaling |
game-paused / game-resumed | - | Pause state |
game-over | - | End game |
After Scaffolding
- •Add config constants to
GameConfig.tsif needed - •Import and instantiate in
GameScene.create() - •Call
destroy()inGameScene.shutdown() - •Document new events in CLAUDE.md if adding custom events