Phaser 场景系统 #

场景概述 #

场景(Scene)是 Phaser 游戏的基本组织单元。每个场景都是一个独立的功能模块,可以包含自己的游戏对象、逻辑和资源。

text
┌─────────────────────────────────────────────────────────────┐
│                    游戏场景结构                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Game                                                       │
│  ├── BootScene        启动场景                              │
│  ├── PreloadScene     资源加载场景                          │
│  ├── MenuScene        菜单场景                              │
│  ├── GameScene        游戏主场景                            │
│  ├── UIScene          UI 覆盖层场景                         │
│  └── PauseScene       暂停场景                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

场景生命周期 #

完整生命周期 #

text
┌─────────────────────────────────────────────────────────────┐
│                    场景生命周期                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   new Scene()                                               │
│        │                                                    │
│        ▼                                                    │
│   init(data)           ◄── 初始化,接收数据                 │
│        │                                                    │
│        ▼                                                    │
│   preload()           ◄── 加载资源                          │
│        │                                                    │
│        ▼                                                    │
│   create()            ◄── 创建游戏对象                      │
│        │                                                    │
│        ▼                                                    │
│   ┌────────────────┐                                        │
│   │  update()      │ ◄── 游戏循环                           │
│   │    ▲    │      │                                        │
│   │    └────┘      │                                        │
│   └────────────────┘                                        │
│        │                                                    │
│        ▼                                                    │
│   shutdown()          ◄── 场景关闭清理                      │
│        │                                                    │
│        ▼                                                    │
│   destroy()           ◄── 场景销毁                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

生命周期详解 #

javascript
class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
    console.log('1. Constructor');
  }

  init(data) {
    console.log('2. Init - 接收数据:', data);
    this.level = data.level || 1;
    this.score = data.score || 0;
  }

  preload() {
    console.log('3. Preload - 加载资源');
    this.load.image('player', 'assets/player.png');
  }

  create() {
    console.log('4. Create - 创建对象');
    this.player = this.add.sprite(100, 100, 'player');
  }

  update(time, delta) {
    console.log('5. Update - 游戏循环');
  }

  shutdown() {
    console.log('6. Shutdown - 清理资源');
    this.events.off('customEvent');
  }
}

场景配置 #

基本配置 #

javascript
const config = {
  key: 'GameScene',
  active: false,
  visible: true,
  pack: {
    files: []
  }
};

class GameScene extends Phaser.Scene {
  constructor() {
    super(config);
  }
}

配置选项 #

javascript
const sceneConfig = {
  key: 'GameScene',
  
  active: false,
  
  visible: true,
  
  pack: {
    files: [
      { type: 'image', key: 'loading', url: 'loading.png' }
    ]
  },
  
  mapAdd: {
    score: 0,
    lives: 3
  },
  
  map: {
    game: 'game',
    anims: 'anims'
  }
};

class GameScene extends Phaser.Scene {
  constructor() {
    super(sceneConfig);
  }
}

使用装饰器风格(TypeScript) #

typescript
@sceneConfig({
  key: 'GameScene'
})
class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
  }
}

场景管理 #

场景管理器 #

javascript
const sceneManager = this.scene;

sceneManager.start('GameScene', { level: 1 });
sceneManager.stop('GameScene');
sceneManager.pause('GameScene');
sceneManager.resume('GameScene');
sceneManager.sleep('GameScene');
sceneManager.wake('GameScene');
sceneManager.switch('GameScene');
sceneManager.launch('UIScene');
sceneManager.remove('GameScene');

启动场景 #

javascript
this.scene.start('GameScene');

this.scene.start('GameScene', { 
  level: 2, 
  score: 1000 
});

暂停与恢复 #

javascript
this.scene.pause('GameScene');

this.scene.resume('GameScene');

this.scene.pause();
this.scene.resume();

休眠与唤醒 #

javascript
this.scene.sleep('GameScene');

this.scene.sleep('GameScene', { data: 'value' });

this.scene.wake('GameScene');

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

停止与移除 #

javascript
this.scene.stop('GameScene');

this.scene.remove('GameScene');

切换场景 #

javascript
this.scene.switch('MenuScene');

this.scene.switch('GameScene');

并行运行场景 #

javascript
create() {
  this.scene.launch('UIScene');
  
  this.scene.launch('UIScene', { score: 100 });
}

场景间通信 #

使用事件系统 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.score = 0;
    
    this.events.on('collectStar', () => {
      this.score += 10;
      this.events.emit('scoreUpdate', this.score);
    });
  }
}

class UIScene extends Phaser.Scene {
  create() {
    const gameScene = this.scene.get('GameScene');
    
    gameScene.events.on('scoreUpdate', (score) => {
      this.scoreText.setText('Score: ' + score);
    });
  }
}

使用全局事件 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.game.events.on('gameOver', (data) => {
      console.log('Game Over!', data);
    });
  }
}

class UIScene extends Phaser.Scene {
  showGameOver() {
    this.game.events.emit('gameOver', { score: 1000 });
  }
}

使用场景数据传递 #

javascript
class MenuScene extends Phaser.Scene {
  startGame() {
    this.scene.start('GameScene', {
      level: 1,
      difficulty: 'hard'
    });
  }
}

class GameScene extends Phaser.Scene {
  init(data) {
    this.level = data.level;
    this.difficulty = data.difficulty;
  }
}

使用共享数据对象 #

javascript
const gameState = {
  score: 0,
  lives: 3,
  level: 1
};

class GameScene extends Phaser.Scene {
  create() {
    this.registry.set('gameState', gameState);
    
    const state = this.registry.get('gameState');
    state.score += 10;
  }
}

class UIScene extends Phaser.Scene {
  create() {
    this.registry.events.on('changedata', (parent, key, value) => {
      if (key === 'gameState') {
        this.updateUI(value);
      }
    });
  }
}

多场景协作 #

游戏场景 + UI 场景 #

javascript
const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  scene: [GameScene, UIScene]
};

class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene', active: true });
  }
  
  create() {
    this.scene.launch('UIScene');
    
    this.player = this.physics.add.sprite(400, 300, 'player');
    
    this.events.on('scoreUpdate', (score) => {
      this.registry.set('score', score);
    });
  }
}

class UIScene extends Phaser.Scene {
  constructor() {
    super({ key: 'UIScene', active: false });
  }
  
  create() {
    this.scoreText = this.add.text(16, 16, 'Score: 0', {
      fontSize: '32px',
      fill: '#fff'
    });
    
    this.registry.events.on('changedata-score', (parent, value) => {
      this.scoreText.setText('Score: ' + value);
    });
  }
}

场景层级管理 #

javascript
const config = {
  scene: [
    { key: 'Boot', class: BootScene },
    { key: 'Preload', class: PreloadScene },
    { key: 'Menu', class: MenuScene },
    { key: 'Game', class: GameScene },
    { key: 'UI', class: UIScene },
    { key: 'Pause', class: PauseScene }
  ]
};

class BootScene extends Phaser.Scene {
  create() {
    this.scene.start('Preload');
  }
}

class PreloadScene extends Phaser.Scene {
  create() {
    this.scene.start('Menu');
  }
}

class MenuScene extends Phaser.Scene {
  startGame() {
    this.scene.start('Game');
  }
}

class GameScene extends Phaser.Scene {
  create() {
    this.scene.launch('UI');
  }
  
  pause() {
    this.scene.pause();
    this.scene.launch('Pause');
  }
}

class PauseScene extends Phaser.Scene {
  resume() {
    this.scene.stop();
    this.scene.get('Game').scene.resume();
  }
}

场景过渡效果 #

淡入淡出 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.cameras.main.fadeIn(1000);
  }
  
  goToMenu() {
    this.cameras.main.fadeOut(1000);
    
    this.cameras.main.once('camerafadeoutcomplete', () => {
      this.scene.start('MenuScene');
    });
  }
}

过渡动画 #

javascript
class GameScene extends Phaser.Scene {
  transitionTo(sceneKey) {
    this.cameras.main.fade(500, 0, 0, 0);
    
    this.cameras.main.once('camerafadeoutcomplete', () => {
      this.scene.start(sceneKey);
    });
  }
}

class MenuScene extends Phaser.Scene {
  create() {
    this.cameras.main.fadeIn(500);
    
    this.cameras.main.once('camerafadeincomplete', () => {
      console.log('Transition complete');
    });
  }
}

自定义过渡 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.transitionOverlay = this.add.rectangle(
      400, 300, 800, 600, 0x000000
    );
    this.transitionOverlay.setAlpha(0);
    this.transitionOverlay.setDepth(1000);
  }
  
  transitionTo(sceneKey) {
    this.tweens.add({
      targets: this.transitionOverlay,
      alpha: 1,
      duration: 500,
      onComplete: () => {
        this.scene.start(sceneKey);
      }
    });
  }
}

场景插件 #

注册场景插件 #

javascript
const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  plugins: {
    scene: [
      { key: 'MyPlugin', plugin: MyPlugin, mapping: 'myPlugin' }
    ]
  },
  scene: GameScene
};

class GameScene extends Phaser.Scene {
  create() {
    this.myPlugin.doSomething();
  }
}

自定义场景插件 #

javascript
class MyPlugin extends Phaser.Plugins.ScenePlugin {
  constructor(scene, pluginManager) {
    super(scene, pluginManager, 'MyPlugin');
  }
  
  doSomething() {
    console.log('Plugin method called in', this.scene.scene.key);
  }
  
  shutdown() {
    console.log('Scene shutting down');
  }
  
  destroy() {
    this.shutdown();
    super.destroy();
  }
}

场景最佳实践 #

场景职责分离 #

text
┌─────────────────────────────────────────────────────────────┐
│                    场景职责划分                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  BootScene                                                  │
│  ├── 加载必要的启动资源                                     │
│  └── 初始化游戏设置                                         │
│                                                             │
│  PreloadScene                                               │
│  ├── 加载所有游戏资源                                       │
│  └── 显示加载进度                                           │
│                                                             │
│  MenuScene                                                  │
│  ├── 显示主菜单                                             │
│  └── 处理菜单交互                                           │
│                                                             │
│  GameScene                                                  │
│  ├── 游戏主逻辑                                             │
│  └── 游戏对象管理                                           │
│                                                             │
│  UIScene                                                    │
│  ├── 显示游戏 UI                                            │
│  └── 处理 UI 交互                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

场景状态管理 #

javascript
class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
    this.state = {
      score: 0,
      lives: 3,
      level: 1,
      paused: false
    };
  }
  
  init(data) {
    this.state.level = data.level || 1;
  }
  
  create() {
    this.events.on('collectItem', (points) => {
      this.state.score += points;
      this.events.emit('stateChanged', this.state);
    });
  }
  
  shutdown() {
    this.events.removeAllListeners();
  }
}

场景资源清理 #

javascript
class GameScene extends Phaser.Scene {
  create() {
    this.timer = this.time.addEvent({
      delay: 1000,
      callback: this.updateTimer,
      callbackScope: this,
      loop: true
    });
    
    this.input.keyboard.on('keydown-SPACE', this.jump, this);
    
    this.events.on('customEvent', this.handleEvent, this);
  }
  
  shutdown() {
    this.timer.remove();
    
    this.input.keyboard.off('keydown-SPACE', this.jump, this);
    
    this.events.off('customEvent', this.handleEvent, this);
  }
}

完整示例 #

游戏场景流程 #

javascript
const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  scene: [BootScene, PreloadScene, MenuScene, GameScene, UIScene]
};

class BootScene extends Phaser.Scene {
  constructor() {
    super({ key: 'BootScene' });
  }
  
  preload() {
    this.load.image('logo', 'assets/logo.png');
  }
  
  create() {
    this.scene.start('PreloadScene');
  }
}

class PreloadScene extends Phaser.Scene {
  constructor() {
    super({ key: 'PreloadScene' });
  }
  
  preload() {
    const progressBar = this.add.graphics();
    const progressBox = this.add.graphics();
    
    progressBox.fillStyle(0x222222, 0.8);
    progressBox.fillRect(240, 270, 320, 50);
    
    this.load.on('progress', (value) => {
      progressBar.clear();
      progressBar.fillStyle(0x00ff00, 1);
      progressBar.fillRect(250, 280, 300 * value, 30);
    });
    
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.spritesheet('dude', 'assets/dude.png', {
      frameWidth: 32,
      frameHeight: 48
    });
  }
  
  create() {
    this.scene.start('MenuScene');
  }
}

class MenuScene extends Phaser.Scene {
  constructor() {
    super({ key: 'MenuScene' });
  }
  
  create() {
    this.add.image(400, 300, 'sky');
    
    const title = this.add.text(400, 200, 'My Game', {
      fontSize: '64px',
      fill: '#fff'
    }).setOrigin(0.5);
    
    const startButton = this.add.text(400, 400, 'Start Game', {
      fontSize: '32px',
      fill: '#fff',
      backgroundColor: '#4CAF50',
      padding: { x: 20, y: 10 }
    }).setOrigin(0.5).setInteractive();
    
    startButton.on('pointerdown', () => {
      this.cameras.main.fadeOut(500);
      this.cameras.main.once('camerafadeoutcomplete', () => {
        this.scene.start('GameScene', { level: 1 });
      });
    });
  }
}

class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
  }
  
  init(data) {
    this.level = data.level || 1;
    this.score = 0;
  }
  
  create() {
    this.cameras.main.fadeIn(500);
    
    this.scene.launch('UIScene');
    
    this.add.image(400, 300, 'sky');
    
    this.player = this.physics.add.sprite(100, 450, 'dude');
    
    this.events.emit('scoreUpdate', this.score);
  }
  
  collectStar(player, star) {
    star.destroy();
    this.score += 10;
    this.events.emit('scoreUpdate', this.score);
  }
}

class UIScene extends Phaser.Scene {
  constructor() {
    super({ key: 'UIScene' });
  }
  
  create() {
    this.scoreText = this.add.text(16, 16, 'Score: 0', {
      fontSize: '32px',
      fill: '#fff'
    });
    
    const gameScene = this.scene.get('GameScene');
    gameScene.events.on('scoreUpdate', (score) => {
      this.scoreText.setText('Score: ' + score);
    });
  }
}

下一步 #

现在你已经掌握了场景系统,接下来学习 游戏对象,深入了解 Phaser 中各种游戏对象的使用!

最后更新:2026-03-29