| name | create-phaser-game-object |
| description | Scaffolds a new Phaser game object (NPC, decoration, portal, item, or interactive element) in a Knowledge Dungeon scene, following the project's patterns for texture loading, positioning, animation, and state integration.
|
Skill: Create a Phaser Game Object
Adds a new renderable element to either the DungeonScene or VillageScene, including texture/sprite setup, positioning, animations, and Zustand store integration where needed.
Process
Step 1: Determine the Scene and Object Type
Identify which scene the object belongs to:
| Scene | File | Object Types |
|---|
| DungeonScene | src/game/scenes/DungeonScene.ts | Room decorations, NPCs, chests, portals, stairs, items, environmental effects |
| VillageScene | src/game/scenes/VillageScene.ts | Buildings, NPCs, signposts, decorations (trees, bushes, ponds, etc.), portal vortexes, birds |
Step 2: Load the Texture
In the scene's preload() method, add a texture load:
this.load.svg('texture-key', '/assets/sprites/my-object.svg', { width: 32, height: 32 });
this.load.image('texture-key', '/assets/sprites/my-object.png');
- SVG assets go in
public/assets/sprites/
- If the object has multiple frames, use a sprite sheet with
this.load.spritesheet()
- For procedural textures, call the relevant generator from
proceduralTextures.ts
Step 3: Create the Game Object
In the scene's create() or the relevant generation function, instantiate the object:
const obj = this.add.image(x, y, 'texture-key');
this.physics.add.existing(obj);
const label = this.add.text(x, y, 'Label', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '12px',
color: '#ffffff',
}).setOrigin(0.5);
Step 4: Add Animation
For animated objects (portals, NPCs, floating items), add a tween in create():
this.tweens.add({
targets: obj,
y: obj.y - 4,
duration: 1500,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
});
this.tweens.add({
targets: obj,
scaleX: 1.1,
scaleY: 1.1,
alpha: 0.8,
duration: 2000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
});
Step 5: Add Interactivity
If the object is interactive (NPC, portal, chest):
obj.setInteractive({ pixelPerfect: true });
obj.on('pointerdown', () => {
useSessionStore.getState().setInteractTarget(objectId);
});
obj.on('pointerover', () => obj.setTint(0xaaaaaa));
obj.on('pointerout', () => obj.clearTint());
Step 6: Integrate with Room/Village State
Connect the object to game state:
const roomState = subjectStore.getState().getRoom(roomId);
if (roomState.encounterState === 'ArtifactCollected') {
obj.setVisible(false);
}
Step 7: Add to Procedural Generation (if applicable)
For dungeon decorations, add the object to the decor placement in DungeonScene.ts's buildDecorForRoom() function, using the deterministic PRNG.
The PRNG seed chain is roomIndex * 7 + floor - decor for any given room on a given floor is fully deterministic from this seed. Do not alter the seed formula without coordinating with core-logic-engineer. Deterministic generation is a hard requirement (NF-02: same topic graph must always produce the same dungeon layout).
const decorType = seededRandom(roomIndex * 7 + floor);
if (decorType < 0.3) {
}
Load assets/code-templates.md for full TypeScript snippets when implementing all steps.
Output Format
The new object should be:
- Rendered in the correct scene (DungeonScene or VillageScene)
- Positioned at integer tile coordinates (48px grid)
- Animated appropriately (idle float, pulse, spin, or static)
- Connected to Zustand state if interactive
- Visible/hidden based on game state (room cleared, phase active, etc.)
Validation
Gotchas
- Phaser texture keys must be unique across the entire game - use namespaced keys like
village-tree-1, dungeon-chest-open
- Do NOT load textures in
create() - always use preload() to ensure textures are ready before rendering
- The village uses a 48px tile grid - positions should be
tileX * 48 + offset to align with the tilemap
- NPC dialog bubbles must emit world coordinates for the React overlay - use
scene.cameras.main.getWorldPoint() for conversion
- For objects that need to persist state (opened chests, collected items), update
RoomMetadata via subjectStore rather than Phaser data manager
- Interactive objects must register in the scene's input handler list for E key support - add to
interactiveObjects array in DungeonScene
Reference
See docs/PRD.md for the full specification:
- Section 8.2 - Dungeon generation and room decoration
- Section 8.3 - Interactive navigation objects (stairs, portals)
- Section 8.8 - Village decorative elements and buildings
- Section 8.10 - NPC rendering and animation
- Section 14 - Phase 3c - Boss rooms, biome decorations