SuperAPI AI 工具集

scenes

编程与开发

查看项目

更新于 10-15 16:23

技能介绍

用途

Scenes(场景)是 Phaser 游戏的组织骨架。每个场景拥有独立的生命周期(init、preload、create、update)、独立的注入系统(this.add、this.input、this.cameras 等),并且可以启动、停止、暂停、休眠,或与其他场景并行运行。ScenePlugin(this.scene)负责所有多场景编排。

关键源码路径:src/scene/Scene.js、src/scene/Systems.js、src/scene/SceneManager.js、src/scene/ScenePlugin.js、src/scene/Settings.js、src/scene/const.js、src/scene/events/、src/scene/InjectionMap.js。

主要能力

场景生命周期

生命周期由 SceneManager.bootScene() 和 SceneManager.create() 驱动,共 10 个状态:

  1. PENDING (0):场景已注册但尚未启动。
  2. INIT (1):若定义了 scene.init(data) 则调用,数据来自 settings.data。
  3. START (2):Systems.start() 触发,发出 start 和 ready 事件。
  4. LOADING (3):若定义了 scene.preload() 则调用,加载器运行,完成后进入 create。
  5. CREATING (4):若定义了 scene.create(data) 则调用,data 与 init 相同。
  6. RUNNING (5):每帧调用 scene.update(time, delta),场景渲染。
  7. PAUSED (6):不更新,但仍渲染。
  8. SLEEPING (7):不更新也不渲染,状态保留在内存中。
  9. SHUTDOWN (8):场景关闭,系统发出 shutdown,可重启。
  10. DESTROYED (9):场景完全销毁,无法重启。

状态常量位于 Phaser.Scenes,如 Phaser.Scenes.PENDING、Phaser.Scenes.RUNNING 等。

无 preload 时的流程:init() -> create() -> update() 循环(完全跳过 preload)。 有 preload 时的流程:init() -> preload() -> 加载器运行 -> create() -> update() 循环。

场景注入属性

这些属性通过 InjectionMap(src/scene/InjectionMap.js)注入到每个场景实例。

全局管理器(所有场景共享):this.game、this.renderer、this.anims、this.cache、this.plugins、this.registry、this.scale、this.sound、this.textures。

场景专属系统(每个场景唯一):this.sys、this.events、this.cameras、this.add、this.make、this.scene、this.children、this.lights、this.data、this.input、this.load、this.time、this.tweens、this.physics、this.matter。

可通过场景配置自定义注入映射,例如将 add 重命名为 makeStuff、load 重命名为 loader。

场景管理器

SceneManager(src/scene/SceneManager.js)是游戏级系统,不应直接调用其方法,而应使用 this.scene(ScenePlugin)。它维护有序的场景数组(决定渲染/更新顺序),在每个游戏步骤开始时处理操作队列(start、stop、sleep 等)。所有 ScenePlugin 方法都是排队执行,而非立即执行(下一帧执行)。

使用方式

场景切换

  • start():关闭当前场景,启动目标场景。
  • restart():关闭并重启同一场景。
  • switch():休眠当前场景,启动/唤醒目标场景,当前场景状态保留在内存中。
  • transition():带 duration 的动画过渡,支持 moveAbove、sleep、remove、allowInput、data、onUpdate 等选项。

并行运行场景

  • launch():并行启动另一个场景(不停止当前场景)。
  • run():智能启动器,未运行则启动,已暂停则恢复,休眠则唤醒。
  • 渲染顺序控制:bringToTop、sendToBack、moveAbove、moveBelow、moveUp、moveDown、swapPosition。

场景间传递数据

  1. 通过 start/launch/restart/switch/wake/run 传数据,在 init(data) 和 create(data) 中可用。
  2. 通过 this.sys.getData() 稍后访问 settings.data。
  3. 全局 registry(所有场景共享):this.registry.set/get。
  4. 场景专属数据管理器:this.data.set/get。
  5. 直接场景引用:this.scene.get('OtherScene')。
  6. 全局 registry 上的事件:this.registry.events.on('changedata-playerHP', ...)。

暂停与恢复

  • pause():停止更新循环,仍渲染。
  • resume():恢复更新循环。
  • sleep():不更新也不渲染,但状态保留。
  • wake():从休眠恢复。
  • stop():完全关闭,清空显示列表和计时器。
  • 状态检查:isActive、isPaused、isSleeping、isVisible。
  • 独立控制可见性/活动性:setActive、setVisible。

运行时增删场景

  • add():动态添加新场景,参数为 key、sceneConfig、autoStart、data。
  • remove():完全移除场景(已销毁,无法重启)。
  • 可从同一类生成多个实例。

跨场景事件通信

一个场景发出自定义事件,另一个场景监听,发出方解耦。例如 GameScene 发出 'addScore' 事件,UIScene 通过 this.scene.get('GameScene').events.on('addScore', ...) 监听。

按场景配置插件

  • 禁用所有默认插件:super({ key: 'MinimalScene', plugins: [] })。
  • 仅包含特定插件:super({ key: 'PreloadScene', plugins: ['Loader'] })。

构造函数中的场景配置

可传入 key、physics、loader、pack 等配置。pack 在 preload() 运行前加载文件,适合进度条资源。

安全重启场景

在 init() 中重置状态,而非构造函数。构造函数只运行一次,init() 每次启动都运行。可在 create() 中通过 this.events.once('shutdown', ...) 清理,避免陈旧引用。

事件

所有事件在 this.events 上发出,通过 this.events.on('eventname', callback) 监听。

生命周期事件:'boot'、'start'、'ready'、'create'、'preupdate'、'update'、'postupdate'、'prerender'、'render'。

状态变更事件:'pause'、'resume'、'sleep'、'wake'、'shutdown'、'destroy'。

过渡事件:'transitionout'、'transitioninit'、'transitionstart'、'transitionwake'、'transitioncomplete'。

游戏对象事件:'addedtoscene'、'removedfromscene'。

适用场景

适用于使用 Phaser 4 开发游戏时需要组织多个场景(如加载场景、菜单场景、游戏场景、UI 场景、暂停菜单等)、管理场景切换与并行运行、在场景间传递数据或通信、以及控制场景暂停/休眠/唤醒等场景。

限制与注意事项

  • 操作是排队执行而非立即执行。调用 this.scene.start('X') 不会同步启动 X,而是在下一次 SceneManager 更新时发生,不要在同一帧内依赖目标场景的状态。
  • start() 会关闭调用场景。若想两者都运行,使用 launch() 或 run()。
  • switch() 休眠,start() 关闭。switch() 将当前场景保留在内存中(休眠),而 start() 触发完全关闭。休眠场景的事件和引用仍然存活。
  • 暂停的场景仍会渲染。pause() 只停止更新循环,场景仍被绘制。使用 sleep() 同时停止更新和渲染。
  • 不要覆盖 this.sys。Scene 类 JSDoc 明确警告:覆盖 this.sys 会破坏一切。
  • 不带 key 的 this.scene.start() 会重启当前场景,等同于 this.scene.restart()。
  • 传给 start()/launch() 的数据在 init(data) 和 create(data) 中都可用,存储在 settings.data 中,稍后可通过 this.sys.getData() 访问。
  • 休眠场景仍可接收其他场景的事件。若场景 A 休眠但场景 B 在全局 registry 上发出事件,场景 A 的监听器仍会触发,需注意休眠场景上的活动监听器。