Loading...
Loading...
Use this skill when working with Phaser 4 scenes. Covers scene lifecycle methods, scene transitions, parallel scenes, scene communication, sleeping, pausing, restarting, and the SceneManager. Triggers on: Scene, scene lifecycle, preload, create, update, scene transition, SceneManager.
npx skill4agent add phaserjs/phaser scenesScenes are the organizational backbone of a Phaser game. Each Scene has its own lifecycle (init, preload, create, update), its own set of injected systems (this.add, this.input, this.cameras, etc.), and can be started, stopped, paused, slept, or run in parallel with other Scenes. The ScenePlugin () controls all multi-scene orchestration.this.scene
src/scene/Scene.jssrc/scene/Systems.jssrc/scene/SceneManager.jssrc/scene/ScenePlugin.jssrc/scene/Settings.jssrc/scene/const.jssrc/scene/events/src/scene/InjectionMap.js// Minimal scene with all lifecycle methods
class GameScene extends Phaser.Scene {
constructor() {
super('GameScene');
}
init(data) {
// Called first. Receives data passed from other scenes.
// 'data' is whatever was passed via scene.start('GameScene', { level: 1 })
this.level = data.level || 1;
}
preload() {
// Called after init. Load assets here.
this.load.image('logo', 'assets/logo.png');
}
create(data) {
// Called after preload completes. Set up game objects.
// 'data' is the same object passed to init.
this.add.image(400, 300, 'logo');
}
update(time, delta) {
// Called every frame while scene is RUNNING.
// time: current time (ms), delta: ms since last frame (smoothed)
}
}
const config = {
width: 800,
height: 600,
scene: [GameScene]
};
const game = new Phaser.Game(config);SceneManager.bootScene()SceneManager.create()scene.init(data)settings.dataSystems.start()startreadyscene.preload()scene.create(data)datascene.update(time, delta)shutdownPhaser.ScenesPhaser.Scenes.PENDINGPhaser.Scenes.RUNNINGinit()create()update()init()preload()create()update()src/scene/InjectionMap.js| Scene Property | Type | Description |
|---|---|---|
| | The Game instance |
| | The active renderer |
| | Global animation manager |
| | Global cache for non-image assets |
| | Global plugin manager |
| | Global data manager (shared between scenes) |
| | Global scale manager |
| | Sound manager |
| | Global texture manager |
| Scene Property | Type | Description |
|---|---|---|
| | Scene systems (never overwrite) |
| | Scene-specific event emitter |
| | Scene camera manager |
| | Factory: creates and adds to display list |
| | Creator: creates but does NOT add to display list |
| | Scene manager plugin (start/stop/launch) |
| | The scene display list |
| | Scene lights (plugin) |
| | Scene-specific data manager |
| | Scene input manager (plugin) |
| | Scene loader (plugin) |
| | Scene time/clock (plugin) |
| | Scene tween manager (plugin) |
| | Arcade physics (if configured) |
| | Matter physics (if configured) |
// Rename injected properties via scene config
const config = {
key: 'MyScene',
map: {
add: 'makeStuff', // this.makeStuff instead of this.add
load: 'loader' // this.loader instead of this.load
}
};SceneManagersrc/scene/SceneManager.jsthis.scene// start() -- shuts down current scene, starts target scene
// Current scene gets SHUTDOWN event; target gets full lifecycle
this.scene.start('LevelTwo', { score: 100 });
// restart() -- shuts down and restarts the same scene
this.scene.restart({ score: 0 });
// switch() -- sleeps current scene, starts/wakes target scene
// Current scene state is preserved in memory
this.scene.switch('PauseMenu', { fromScene: 'GameScene' });
// transition() -- animated transition with duration
this.scene.transition({
target: 'LevelTwo',
duration: 1000,
moveAbove: true, // render target above this scene
sleep: false, // false = stop this scene (default), true = sleep it
remove: false, // true = remove this scene from manager after transition
allowInput: false, // allow input on this scene during transition
data: { score: 100 },
onUpdate: function (progress) {
// progress: 0 to 1 over duration
}
});// launch() -- starts another scene in parallel (does NOT stop current scene)
this.scene.launch('UIScene', { lives: 3 });
// run() -- smart launcher: starts if not running, resumes if paused, wakes if sleeping
this.scene.run('UIScene', { lives: 3 });
// Control render order of parallel scenes
this.scene.bringToTop('UIScene'); // render last (on top)
this.scene.sendToBack('Background'); // render first (behind)
this.scene.moveAbove('GameScene', 'UIScene'); // UIScene renders above GameScene
this.scene.moveBelow('GameScene', 'Background');
this.scene.moveUp('UIScene'); // move one position up
this.scene.moveDown('UIScene'); // move one position down
this.scene.swapPosition('SceneA', 'SceneB');// Method 1: Pass data via start/launch/restart/switch/wake/run
this.scene.start('LevelScene', { level: 5, score: 1200 });
// In LevelScene:
// init(data) { data.level === 5 }
// create(data) { data.score === 1200 }
// Method 2: Access data later via sys.getData()
// In receiving scene, at any time:
const data = this.sys.getData(); // returns settings.data
// Method 3: Global registry (shared across ALL scenes)
// In Scene A:
this.registry.set('playerHP', 100);
// In Scene B:
const hp = this.registry.get('playerHP'); // 100
// Method 4: Scene-specific data manager
this.data.set('localValue', 42);
this.data.get('localValue'); // 42
// Method 5: Direct scene reference
const otherScene = this.scene.get('OtherScene');
otherScene.somePublicProperty;
// Method 6: Events on the global registry
// In Scene A:
this.registry.events.on('changedata-playerHP', (parent, value, previousValue) => {
// react to change
});
// In Scene B:
this.registry.set('playerHP', 50); // triggers the event in Scene A// Pause: stops update loop, still renders
this.scene.pause(); // pause this scene
this.scene.pause('OtherScene'); // pause another scene
// Resume: restart update loop
this.scene.resume();
this.scene.resume('OtherScene', { message: 'welcome back' });
// Sleep: no update AND no render, but state preserved
this.scene.sleep();
this.scene.sleep('OtherScene');
// Wake: restore from sleep
this.scene.wake();
this.scene.wake('OtherScene', { data: 'here' });
// Stop: full shutdown, clears display list and timers
this.scene.stop();
this.scene.stop('OtherScene');
// Check state
this.scene.isActive('OtherScene'); // boolean
this.scene.isPaused('OtherScene'); // boolean
this.scene.isSleeping('OtherScene'); // boolean
this.scene.isVisible('OtherScene'); // boolean
// Control visibility/activity independently
this.scene.setActive(false); // pause
this.scene.setActive(true); // resume
this.scene.setVisible(false); // hide but still update
this.scene.setVisible(true); // show// Add a new scene dynamically
this.scene.add('BonusLevel', BonusLevelScene, false, { someData: true });
// args: key, sceneConfig, autoStart, data
// Remove a scene entirely (destroyed, cannot be restarted)
this.scene.remove('BonusLevel');
// Spawn multiple instances from one class
for (let i = 0; i < 5; i++) {
this.scene.add('Level' + i, new LevelScene('Level' + i), false);
}// GameScene emits events
class GameScene extends Phaser.Scene {
collectCoin(coin) {
coin.destroy();
this.events.emit('addScore', 10);
}
}
// UIScene listens (launched in parallel with { active: true })
class UIScene extends Phaser.Scene {
constructor() {
super({ key: 'UIScene', active: true });
}
create() {
this.score = 0;
this.scoreText = this.add.text(10, 10, 'Score: 0');
// Listen for events from GameScene
const gameScene = this.scene.get('GameScene');
gameScene.events.on('addScore', (points) => {
this.score += points;
this.scoreText.setText('Score: ' + this.score);
});
}
}super({ key: 'MinimalScene', plugins: [] });
// No this.load, this.tweens, this.time, this.input, this.data, this.lightssuper({ key: 'PreloadScene', plugins: ['Loader'] });
// Only this.load is available; this.tweens, this.time, etc. are undefinedsuper()class Level1 extends Phaser.Scene {
constructor() {
super({
key: 'Level1',
physics: { arcade: { debug: true, gravity: { y: 200 } } },
loader: { path: 'assets/levels/1/' },
// 'pack' loads files before preload() runs -- good for progress bar assets
pack: {
files: [
{ type: 'image', key: 'bar', url: 'loaderBar.png' }
]
}
});
}
}init()init()class GameScene extends Phaser.Scene {
constructor() {
super('GameScene');
// BAD: this.gameOver = false; -- only set once, not on restart
}
init() {
// GOOD: reset state every time the scene starts
this.gameOver = false;
this.score = 0;
}
create() {
// Clean up on shutdown to avoid stale references
this.events.once('shutdown', () => {
// Clear any arrays holding game object references
this.enemies = [];
});
}
}this.eventsthis.events.on('eventname', callback)| Event String | Constant | Callback Signature | When |
|---|---|---|---|
| | | Once, when scene is first instantiated (for plugins) |
| | | Scene systems start (for plugins) |
| | | After start, for user code |
| | | After |
| | | Before update each frame |
| | | During update each frame |
| | | After update each frame |
| | | Before scene renders |
| | | After scene renders |
| Event String | Constant | Callback Signature | When |
|---|---|---|---|
| | | Scene is paused |
| | | Scene is resumed |
| | | Scene is sent to sleep |
| | | Scene is woken up |
| | | Scene is shutting down |
| | | Scene is being destroyed |
| Event String | Constant | Callback Signature | Emitted On |
|---|---|---|---|
| | | Source scene |
| | | Target scene (during init) |
| | | Target scene (after create) |
| | | Target scene (if woken from sleep) |
| | | Target scene (when done) |
| Event String | Constant | Callback Signature |
|---|---|---|
| | |
| | |
this.scene.start('X')start()this.scene.start('X')launch()run()switch()start()switch()start()pause()sleep()this.systhis.systhis.scene.start()this.scene.restart()start()launch()init(data)create(data)settings.datathis.sys.getData()bringToTop()sendToBack()moveAbove()moveBelow()shutdowndestroy'shutdown''destroy'this.physicsthis.mattercreatecreate()init()init()shutdownthis.events.once('shutdown', ...)switch()run()