| name | dev-phaser-scene-management |
| description | Scene transitions, data passing, and scene lifecycle management |
Phaser Scene Management
"Orchestrating your game scenes with smooth transitions and data flow."
Before/After: Manual Screen Management vs Phaser Scene System
❌ Before: Manual Screen Management
type ScreenType = 'title' | 'game' | 'pause' | 'gameover';
let currentScreen: ScreenType = 'title';
const screens: { [key in ScreenType]: HTMLElement } = {};
function showScreen(screen: ScreenType, data?: any) {
if (screens[currentScreen]) {
screens[currentScreen].style.display = 'none';
}
if (!screens[screen]) {
screens[screen] = document.getElementById(`screen-${screen}`)!;
}
screens[screen].style.display = 'block';
if (data && screen === 'game') {
const levelElement = screens[screen].querySelector('.level')!;
levelElement.textContent = data.level || '1';
}
if (currentScreen === 'game') {
saveGameState();
}
currentScreen = screen;
}
✅ After: Phaser Scene System
export class TitleScene extends Phaser.Scene {
create() {
this.scene.start('GameScene', { level: 1, difficulty: 'normal' });
}
}
export class GameScene extends Phaser.Scene {
init(data: { level: number; difficulty: string }) {
this.level = data.level || 1;
this.difficulty = data.difficulty || 'normal';
}
create() {
this.scene.launch('UIScene', { health: 100 });
this.events.once(, {
});
}
() {
..();
..();
}
() {
...(, , , );
...(, {
..(, {
: .,
: .
});
});
}
}
When to Use This Skill
Use when:
- Managing multiple game scenes
- Passing data between scenes
- Implementing scene transitions
- Running parallel scenes (UI overlay)
- Pausing/resuming game state
Quick Start
this.scene.start("GameScene", { level: 1, score: 0 });
this.scene.launch("UIScene", { health: 100 });
this.scene.sleep("BackgroundScene");
Decision Framework
| Need | Use |
|---|
| Switch scenes | scene.start() |
| Parallel scene | scene.launch() |
| Pause scene | scene.pause() |
| Scene transition effects | Transition effects |
| Pass data to scene | Data parameter |
Progressive Guide
Level 1: Basic Scene Operations
export class TitleScene extends Phaser.Scene {
create() {
this.input.on("pointerdown", () => {
this.scene.start("GameScene", { difficulty: "normal" });
});
}
}
export class GameScene extends Phaser.Scene {
private difficulty!: string;
init(data: { difficulty: string }) {
this.difficulty = data.difficulty || "normal";
}
create() {
this.events.on("shutdown", () => {
console.log("Game scene shutting down");
});
this.input.keyboard!.on("keydown-ESC", {
..();
});
}
}
Level 2: Scene Transitions with Data
export class LevelSelectScene extends Phaser.Scene {
selectLevel(level: number) {
const sceneData = {
level: level,
stars: this.getPlayerStars(level),
unlocked: this.isLevelUnlocked(level),
};
this.cameras.main.fadeOut(300, 0, 0, 0);
this.cameras.main.once("camerafadeoutcomplete", () => {
this.scene.start("GameScene", sceneData);
});
}
}
export class GameScene extends Phaser.Scene {
private level!: number;
private stars!: number;
private unlocked!: boolean;
private score = 0;
init() {
. = data. || ;
. = data. || ;
. = data. || ;
}
() {
returnData = {
: .,
: .(),
: .,
};
..(, returnData);
}
}
Level 3: Parallel Scenes (UI Overlay)
export class GameScene extends Phaser.Scene {
create() {
this.scene.launch("UIScene", { maxHealth: 100 });
const uiScene = this.scene.get("UIScene") as UIScene;
this.scene.get("UIScene").events.on("pause", () => {
this.scene.pause();
});
this.scene.get("UIScene").events.on("resume", () => {
this.scene.resume();
});
}
update() {
const uiScene = this.scene.() ;
uiScene.(..);
uiScene.(.);
}
}
{
healthBar!: ..;
scoreText!: ..;
() {
. = ..();
. = ..(, , );
pauseBtn = ..(.. - , , );
pauseBtn.();
pauseBtn.(, {
..();
});
..();
}
() {
..();
..();
..(, , current * , );
}
() {
..();
}
}
Level 4: Scene Sleep and Wake
export class BackgroundScene extends Phaser.Scene {
private stars!: Phaser.GameObjects.Group;
create() {
this.stars = this.add.group();
for (let i = 0; i < 100; i++) {
const star = this.add.image(
Phaser.Math.Between(0, this.scale.width),
Phaser.Math.Between(0, this.scale.height),
"star",
);
star.setScrollFactor(0.1);
this.stars.add(star);
}
this.events.on("sleep", () => {
console.log();
});
..(, {
.();
});
}
() {
....( {
star. -= ;
(star. < -) star. = .. + ;
});
}
}
{
() {
..();
overlay = ..(
.. / ,
.. / ,
..,
..,
,
,
);
resumeBtn = ..(.. / , , );
resumeBtn.();
resumeBtn.();
resumeBtn.(, {
..();
..();
});
quitBtn = ..(.. / , , );
quitBtn.();
quitBtn.();
quitBtn.(, {
..();
..();
..();
});
}
}
Level 5: Advanced Scene Manager
class SceneManager {
private scene: Phaser.Scene;
private sceneData = new Map<string, any>();
constructor(scene: Phaser.Scene) {
this.scene = scene;
}
transition(targetKey: string, data?: any, transition?: string) {
this.sceneData.set(this.scene.scene.key, this.getCurrentSceneData());
const combinedData = {
...this.sceneData.get(targetKey),
...data,
};
if (transition === "fade") {
this.fadeTransition(targetKey, combinedData);
} else if (transition === "slide") {
.(targetKey, combinedData);
} {
...(targetKey, combinedData);
}
}
() {
camera = ...;
camera.(, , , );
camera.(, {
...(targetKey, data);
});
}
() {
width = ...;
camera = ...;
...({
: camera,
: -width,
: ,
: {
camera. = width;
...(targetKey, data);
},
});
}
(): {
{
: (. ). || ,
: (. ).?. || ,
};
}
() {
...(overlayKey, data);
...();
}
() {
...(overlayKey);
...();
(returnData) {
.(returnData);
}
}
() {
(data. === ) {
.();
}
}
}
{
sceneManager!: ;
() {
. = ();
}
() {
..(, {
: .,
: .,
});
}
() {
..(
,
{ : ., : },
,
);
}
}
Anti-Patterns
❌ DON'T:
- Use
start() when you need launch() for UI
- Forget to handle scene shutdown cleanup
- Pass circular references in scene data
- Use
restart() frequently - expensive
- Stop scenes before retrieving data
- Mix scene keys as strings (use constants)
✅ DO:
- Use
launch() for parallel UI scenes
- Clean up in shutdown event handler
- Keep scene data serializable
- Use scene manager for complex flows
- Retrieve data before stopping scenes
- Define scene key constants
Code Patterns
Scene Key Constants
export const SCENE_KEYS = {
BOOT: "BootScene",
PRELOAD: "PreloadScene",
TITLE: "TitleScene",
GAME: "GameScene",
UI: "UIScene",
PAUSE: "PauseScene",
} as const;
this.scene.start(SCENE_KEYS.GAME, { level: 1 });
Global Scene Manager
const config: Phaser.Types.Core.GameConfig = {
scene: [BootScene, PreloadScene, TitleScene, GameScene, UIScene],
};
const gameScene = this.scene.get(SCENE_KEYS.GAME);
Scene Methods Reference
| Method | Description | Data Passed |
|---|
start(key, data) | Switch to scene, stop current | Yes |
launch(key, data) | Start scene in parallel | Yes |
sleep(key) | Pause scene updates | No |
wake(key, data) | Resume sleeping scene | Optional |
stop(key, data) | Stop and remove scene | Optional |
pause() | Pause current scene | No |
resume() | Resume current scene | No |
get(key) | Get scene reference | No |
Checklist
Reference