or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actions.mdanimation.mdaudio.mdcameras.mddata-management.mdevents.mdgame-objects.mdindex.mdinput.mdloading.mdmath-geometry.mdphysics.mdrendering.mdscenes.mdtweens.mdutilities.md

scenes.mddocs/

0

# Scene Management

1

2

Scenes are self-contained game states that manage their own display lists, update loops, input handling, and systems. They form the structural backbone of Phaser games, representing different screens like menus, gameplay, pause screens, and game over states.

3

4

## Scene Basics

5

6

### Scene Class

7

The base `Phaser.Scene` class provides the foundation for all game scenes.

8

9

```javascript { .api }

10

class GameScene extends Phaser.Scene {

11

constructor() {

12

super({ key: 'GameScene' });

13

}

14

15

init(data) {

16

// Initialize scene with passed data

17

this.score = data.score || 0;

18

this.level = data.level || 1;

19

}

20

21

preload() {

22

// Load assets for this scene

23

this.load.image('player', 'assets/player.png');

24

this.load.audio('bgm', 'assets/music.mp3');

25

}

26

27

create(data) {

28

// Create game objects and set up scene

29

this.player = this.add.sprite(400, 300, 'player');

30

this.music = this.sound.add('bgm');

31

this.music.play({ loop: true });

32

}

33

34

update(time, delta) {

35

// Game logic updated every frame

36

if (this.input.keyboard.addKey('SPACE').isDown) {

37

this.player.y -= 200 * (delta / 1000);

38

}

39

}

40

}

41

```

42

43

### Scene Configuration

44

Scenes can be configured with various options:

45

46

```javascript { .api }

47

class MenuScene extends Phaser.Scene {

48

constructor() {

49

super({

50

key: 'MenuScene',

51

active: true, // Start active

52

visible: true, // Start visible

53

pack: { // Preload pack

54

files: [

55

{ type: 'image', key: 'logo', url: 'assets/logo.png' }

56

]

57

},

58

cameras: { // Camera configuration

59

name: 'menuCam',

60

x: 0,

61

y: 0,

62

width: 800,

63

height: 600

64

},

65

map: { // Tilemap auto-load

66

key: 'menu_map',

67

tileWidth: 32,

68

tileHeight: 32

69

},

70

physics: { // Physics configuration

71

default: 'arcade',

72

arcade: {

73

gravity: { y: 300 }

74

}

75

}

76

});

77

}

78

}

79

```

80

81

## Scene Lifecycle

82

83

### Lifecycle Methods

84

Scenes have a defined lifecycle with specific callback methods:

85

86

```javascript { .api }

87

class LifecycleScene extends Phaser.Scene {

88

init(data) {

89

// Called first when scene starts

90

// Use for variable initialization

91

console.log('Scene initializing with data:', data);

92

this.playerName = data.playerName || 'Player';

93

}

94

95

preload() {

96

// Called after init, used for asset loading

97

this.load.image('background', 'assets/bg.jpg');

98

this.load.spritesheet('character', 'assets/char.png', {

99

frameWidth: 32,

100

frameHeight: 48

101

});

102

103

// Show loading progress

104

this.load.on('progress', (percent) => {

105

console.log('Loading:', Math.round(percent * 100) + '%');

106

});

107

}

108

109

create(data) {

110

// Called after preload completes

111

// Create game objects and set up scene

112

this.add.image(400, 300, 'background');

113

this.character = this.add.sprite(100, 400, 'character');

114

115

// Set up input

116

this.cursors = this.input.keyboard.createCursorKeys();

117

118

// Scene is now ready for interaction

119

console.log('Scene ready for', this.playerName);

120

}

121

122

update(time, delta) {

123

// Called every frame while scene is active

124

if (this.cursors.left.isDown) {

125

this.character.x -= 150 * (delta / 1000);

126

}

127

if (this.cursors.right.isDown) {

128

this.character.x += 150 * (delta / 1000);

129

}

130

}

131

}

132

```

133

134

### Scene Events

135

Scenes emit events during their lifecycle:

136

137

```javascript { .api }

138

class EventScene extends Phaser.Scene {

139

create() {

140

// Listen to scene events

141

this.events.on('create', () => {

142

console.log('Scene created');

143

});

144

145

this.events.on('wake', (sys, data) => {

146

console.log('Scene woken up with data:', data);

147

});

148

149

this.events.on('sleep', () => {

150

console.log('Scene going to sleep');

151

});

152

153

this.events.on('pause', () => {

154

console.log('Scene paused');

155

});

156

157

this.events.on('resume', () => {

158

console.log('Scene resumed');

159

});

160

161

this.events.on('shutdown', () => {

162

console.log('Scene shutting down');

163

});

164

165

this.events.on('destroy', () => {

166

console.log('Scene destroyed');

167

});

168

}

169

}

170

```

171

172

## Scene Management

173

174

### Scene Plugin

175

The Scene Plugin (`this.scene`) provides methods for managing scenes:

176

177

```javascript { .api }

178

class GameScene extends Phaser.Scene {

179

create() {

180

// Start another scene

181

this.scene.start('NextScene', { score: this.score });

182

183

// Launch scene in parallel

184

this.scene.launch('UIScene');

185

this.scene.launch('BackgroundScene');

186

187

// Switch to scene (stops current, starts new)

188

this.scene.switch('MenuScene');

189

190

// Pause/Resume scenes

191

this.scene.pause('GameScene');

192

this.scene.resume('GameScene');

193

194

// Sleep/Wake scenes (like pause but stops updates)

195

this.scene.sleep('GameScene');

196

this.scene.wake('GameScene', { newData: 'value' });

197

198

// Stop scene

199

this.scene.stop('GameScene');

200

201

// Restart current scene

202

this.scene.restart({ resetScore: true });

203

204

// Set scene visibility

205

this.scene.setVisible(false, 'BackgroundScene');

206

207

// Move scenes up/down in render order

208

this.scene.moveUp('UIScene');

209

this.scene.moveDown('BackgroundScene');

210

this.scene.bringToTop('UIScene');

211

this.scene.sendToBack('BackgroundScene');

212

}

213

}

214

```

215

216

### Scene Manager

217

Access the global scene manager through `this.scene.manager`:

218

219

```javascript { .api }

220

class ManagerScene extends Phaser.Scene {

221

create() {

222

const manager = this.scene.manager;

223

224

// Get scene references

225

const gameScene = manager.getScene('GameScene');

226

const activeScenes = manager.getScenes(true); // Only active

227

const allScenes = manager.getScenes(false); // All scenes

228

229

// Scene queries

230

const isActive = manager.isActive('GameScene');

231

const isVisible = manager.isVisible('UIScene');

232

const isSleeping = manager.isSleeping('BackgroundScene');

233

234

// Scene operations

235

manager.start('GameScene', { level: 2 });

236

manager.pause('GameScene');

237

manager.resume('GameScene');

238

manager.sleep('GameScene');

239

manager.wake('GameScene');

240

manager.stop('GameScene');

241

manager.switch('MenuScene');

242

243

// Batch operations

244

manager.pauseAll();

245

manager.resumeAll();

246

247

// Scene events on manager

248

manager.on('start', (event, scene) => {

249

console.log('Scene started:', scene.sys.settings.key);

250

});

251

252

manager.on('ready', (event, scene) => {

253

console.log('Scene ready:', scene.sys.settings.key);

254

});

255

}

256

}

257

```

258

259

## Multiple Scene Architecture

260

261

### Parallel Scenes

262

Run multiple scenes simultaneously for layered functionality:

263

264

```javascript { .api }

265

// Main game scene

266

class GameScene extends Phaser.Scene {

267

constructor() {

268

super({ key: 'GameScene' });

269

}

270

271

create() {

272

// Set up main game

273

this.add.image(400, 300, 'background');

274

this.player = this.add.sprite(100, 400, 'player');

275

276

// Launch UI overlay

277

this.scene.launch('UIScene');

278

279

// Launch background effects

280

this.scene.launch('ParticleScene');

281

282

// Communication between scenes

283

this.events.on('updateScore', (score) => {

284

this.scene.get('UIScene').events.emit('scoreChanged', score);

285

});

286

}

287

}

288

289

// UI overlay scene

290

class UIScene extends Phaser.Scene {

291

constructor() {

292

super({ key: 'UIScene' });

293

}

294

295

create() {

296

// Create UI elements that stay on top

297

this.scoreText = this.add.text(16, 16, 'Score: 0', {

298

fontSize: '32px',

299

fill: '#000'

300

});

301

302

// Listen for score updates

303

this.events.on('scoreChanged', (score) => {

304

this.scoreText.setText('Score: ' + score);

305

});

306

307

// UI doesn't scroll with camera

308

this.cameras.main.setScroll(0, 0);

309

}

310

}

311

312

// Background effects scene

313

class ParticleScene extends Phaser.Scene {

314

constructor() {

315

super({ key: 'ParticleScene' });

316

}

317

318

create() {

319

// Background particle effects

320

this.particles = this.add.particles(400, 300, 'particle', {

321

speed: 50,

322

lifespan: 2000,

323

quantity: 2,

324

scale: { start: 0.5, end: 0 }

325

});

326

327

// Render behind main scene

328

this.scene.moveDown();

329

}

330

}

331

```

332

333

### Scene Communication

334

Scenes can communicate through events and data:

335

336

```javascript { .api }

337

// Game scene sends events

338

class GameScene extends Phaser.Scene {

339

playerDied() {

340

// Send event to UI

341

this.events.emit('playerDied');

342

343

// Send event to other scenes via scene manager

344

this.scene.manager.scenes.forEach(scene => {

345

if (scene.sys.settings.key !== 'GameScene') {

346

scene.events.emit('gameOver', { score: this.score });

347

}

348

});

349

350

// Switch to game over with data

351

this.scene.start('GameOverScene', {

352

score: this.score,

353

level: this.level,

354

time: this.gameTime

355

});

356

}

357

}

358

359

// UI scene listens for events

360

class UIScene extends Phaser.Scene {

361

create() {

362

// Listen to game scene events

363

const gameScene = this.scene.get('GameScene');

364

gameScene.events.on('playerDied', () => {

365

this.showGameOverUI();

366

});

367

368

// Global scene events

369

this.events.on('gameOver', (data) => {

370

this.displayFinalScore(data.score);

371

});

372

}

373

}

374

```

375

376

## Scene Transitions

377

378

### Transition Effects

379

Create smooth transitions between scenes:

380

381

```javascript { .api }

382

class TransitionScene extends Phaser.Scene {

383

fadeToScene(sceneKey, duration = 1000) {

384

// Fade out current scene

385

this.cameras.main.fadeOut(duration, 0, 0, 0);

386

387

// When fade completes, switch scenes

388

this.cameras.main.once('camerafadeoutcomplete', () => {

389

this.scene.start(sceneKey);

390

});

391

}

392

393

slideToScene(sceneKey, direction = 'left') {

394

const camera = this.cameras.main;

395

const targetX = direction === 'left' ? -800 : 800;

396

397

// Slide camera off screen

398

this.tweens.add({

399

targets: camera,

400

scrollX: targetX,

401

duration: 1000,

402

ease: 'Power2',

403

onComplete: () => {

404

this.scene.start(sceneKey);

405

}

406

});

407

}

408

409

create() {

410

// Transition buttons

411

this.add.text(100, 100, 'Fade Transition', { fontSize: '24px' })

412

.setInteractive()

413

.on('pointerdown', () => {

414

this.fadeToScene('NextScene');

415

});

416

417

this.add.text(100, 150, 'Slide Transition', { fontSize: '24px' })

418

.setInteractive()

419

.on('pointerdown', () => {

420

this.slideToScene('NextScene', 'left');

421

});

422

}

423

}

424

```

425

426

### Loading Scenes

427

Handle asset loading with dedicated loading scenes:

428

429

```javascript { .api }

430

class LoadingScene extends Phaser.Scene {

431

constructor() {

432

super({ key: 'LoadingScene' });

433

}

434

435

preload() {

436

// Create loading UI

437

const progressBar = this.add.graphics();

438

const progressBox = this.add.graphics();

439

progressBox.fillStyle(0x222222);

440

progressBox.fillRect(240, 270, 320, 50);

441

442

const loadingText = this.add.text(400, 240, 'Loading...', {

443

fontSize: '20px',

444

fill: '#ffffff'

445

}).setOrigin(0.5);

446

447

const percentText = this.add.text(400, 300, '0%', {

448

fontSize: '18px',

449

fill: '#ffffff'

450

}).setOrigin(0.5);

451

452

// Update progress

453

this.load.on('progress', (percent) => {

454

progressBar.clear();

455

progressBar.fillStyle(0xffffff);

456

progressBar.fillRect(250, 280, 300 * percent, 30);

457

percentText.setText(Math.round(percent * 100) + '%');

458

});

459

460

this.load.on('complete', () => {

461

loadingText.setText('Complete!');

462

this.time.delayedCall(500, () => {

463

this.scene.start('GameScene');

464

});

465

});

466

467

// Load game assets

468

this.loadGameAssets();

469

}

470

471

loadGameAssets() {

472

this.load.image('background', 'assets/bg.jpg');

473

this.load.spritesheet('player', 'assets/player.png', {

474

frameWidth: 32,

475

frameHeight: 48

476

});

477

this.load.audio('music', 'assets/music.mp3');

478

// ... more assets

479

}

480

}

481

```

482

483

## Scene Data Management

484

485

### Scene Data

486

Each scene has its own data manager for storing scene-specific data:

487

488

```javascript { .api }

489

class DataScene extends Phaser.Scene {

490

create() {

491

// Set scene data

492

this.data.set('score', 100);

493

this.data.set('level', 1);

494

this.data.set('player', {

495

name: 'Hero',

496

health: 100,

497

mana: 50

498

});

499

500

// Get scene data

501

const score = this.data.get('score');

502

const player = this.data.get('player');

503

504

// Increment values

505

this.data.inc('score', 10);

506

this.data.inc('level');

507

508

// Toggle boolean

509

this.data.toggle('paused');

510

511

// Listen for data changes

512

this.data.on('setdata', (parent, key, value) => {

513

console.log('Data set:', key, value);

514

});

515

516

this.data.on('changedata-score', (parent, value, prevValue) => {

517

console.log('Score changed from', prevValue, 'to', value);

518

});

519

520

// Remove data

521

this.data.remove('temporaryValue');

522

523

// Reset all data

524

this.data.reset();

525

}

526

}

527

```

528

529

### Global Registry

530

Access game-wide data through the global registry:

531

532

```javascript { .api }

533

class RegistryScene extends Phaser.Scene {

534

create() {

535

// Global data accessible from any scene

536

this.registry.set('playerName', 'Hero');

537

this.registry.set('highScore', 5000);

538

this.registry.set('unlockedLevels', [1, 2, 3]);

539

540

// Get global data

541

const playerName = this.registry.get('playerName');

542

const highScore = this.registry.get('highScore');

543

544

// Listen for global data changes

545

this.registry.on('setdata', (parent, key, value) => {

546

if (key === 'highScore') {

547

this.updateHighScoreDisplay(value);

548

}

549

});

550

551

// Any scene can update global data

552

this.registry.inc('highScore', 100);

553

}

554

}

555

```

556

557

## Scene Systems

558

559

### Scene Systems Access

560

Each scene has access to various game systems:

561

562

```javascript { .api }

563

class SystemsScene extends Phaser.Scene {

564

create() {

565

// Core systems

566

const game = this.game; // Game instance

567

const scene = this.scene; // Scene plugin

568

const anims = this.anims; // Animation manager

569

const cache = this.cache; // Cache manager

570

const registry = this.registry; // Global registry

571

const sound = this.sound; // Sound manager

572

const textures = this.textures; // Texture manager

573

574

// Scene-specific systems

575

const cameras = this.cameras; // Camera manager

576

const add = this.add; // GameObject factory

577

const make = this.make; // GameObject creator

578

const physics = this.physics; // Physics world

579

const input = this.input; // Input manager

580

const load = this.load; // Loader plugin

581

const time = this.time; // Clock

582

const tweens = this.tweens; // Tween manager

583

const lights = this.lights; // Lights system

584

const data = this.data; // Scene data manager

585

586

// Display management

587

const children = this.children; // Display list

588

const displayList = this.displayList; // Same as children

589

const updateList = this.updateList; // Update list

590

591

// Events

592

const events = this.events; // Scene events

593

}

594

}

595

```

596

597

### Custom Scene Systems

598

Extend scenes with custom functionality:

599

600

```javascript { .api }

601

class CustomScene extends Phaser.Scene {

602

constructor(config) {

603

super(config);

604

605

// Custom properties

606

this.gameState = 'playing';

607

this.enemies = [];

608

this.powerUps = [];

609

}

610

611

init() {

612

// Custom initialization

613

this.setupCustomSystems();

614

}

615

616

setupCustomSystems() {

617

// Custom enemy manager

618

this.enemyManager = {

619

spawn: (x, y, type) => {

620

const enemy = this.add.sprite(x, y, type);

621

this.enemies.push(enemy);

622

return enemy;

623

},

624

625

update: () => {

626

this.enemies.forEach(enemy => {

627

// Update enemy logic

628

});

629

},

630

631

removeAll: () => {

632

this.enemies.forEach(enemy => enemy.destroy());

633

this.enemies = [];

634

}

635

};

636

637

// Custom event system

638

this.gameEvents = new Phaser.Events.EventEmitter();

639

this.gameEvents.on('enemyDefeated', this.onEnemyDefeated, this);

640

this.gameEvents.on('powerUpCollected', this.onPowerUpCollected, this);

641

}

642

643

update(time, delta) {

644

if (this.gameState === 'playing') {

645

this.enemyManager.update();

646

}

647

}

648

649

onEnemyDefeated(enemy) {

650

// Handle enemy defeat

651

this.data.inc('score', 100);

652

this.gameEvents.emit('scoreUpdated', this.data.get('score'));

653

}

654

655

onPowerUpCollected(powerUp) {

656

// Handle power-up collection

657

this.data.set('powerUpActive', true);

658

this.time.delayedCall(5000, () => {

659

this.data.set('powerUpActive', false);

660

});

661

}

662

}

663

```

664

665

This comprehensive scene management system provides the structure and flexibility needed to create complex, multi-state games with smooth transitions and robust data management.