ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Phaser Scenes 场景系统参考指南:ScenePlugin 与 Systems 全 API 速查表及源码映射

Phaser Scenes 场景系统参考指南:ScenePlugin 与 Systems 全 API 速查表及源码映射 Phaser Scenes 场景系统参考指南ScenePlugin 与 Systems 全 API 速查表及源码映射【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser本文是 Phaser 仓库中skills/scenes技能的配套参考文档围绕 skills/scenes/references/REFERENCE.md 展开系统梳理this.sceneScenePlugin与this.sysSystems两个场景控制入口的全部方法签名、场景生命周期状态常量PENDING 0 到 DESTROYED 9、以及src/scene/目录下各源码文件的职责映射。读完本文你将能熟练使用队列式场景操作 API 完成场景切换、并行启动、暂停/休眠、数据传递与渲染层级控制并能依据源码地图快速定位场景系统的底层实现。一、场景控制的两个入口ScenePlugin 与 Systems在 Phaser 的场景系统中对场景的外部操作切换、并行、暂停等和对场景的自身状态查询、生命周期分别由两个对象承担它们通过 src/scene/InjectionMap.js 被注入到每个 Scene 实例上this.scene—— 即Phaser.Scenes.ScenePlugin是用户面向的场景管理 API所有操作都会被排队queued在下一个 Scene Manager 更新周期执行this.sys—— 即Phaser.Scenes.Systems是每个 Scene 的系统中枢负责生命周期管理、状态查询以及 pause/resume/sleep/wake 等底层状态切换。从 src/scene/InjectionMap.js 可以看到注入映射将 Systems 的scenePlugin键映射为场景属性scene将displayList映射为children这正是this.scene与this.children名称的来源。需要特别注意的是不要覆盖this.syssrc/scene/Scene.js 的 JSDoc 明确警告覆盖它会破坏一切场景机制。二、ScenePlugin 方法速查表this.scene以下是 skills/scenes/references/REFERENCE.md 中给出的完整方法表。所有方法均排队执行——例如调用this.scene.launch(SceneB)会在游戏步进开始时由 Scene Manager 处理而不是同步生效。这一点在 src/scene/ScenePlugin.js 的类文档中有明确说明nearly all methods in this class are run on a queue-basis and not immediately。方法签名说明start(key?, data?) this停止当前场景启动目标场景不传 key 则重启自身restart(data?) this停止并重启当前场景launch(key, data?) this并行启动另一个场景不停止当前场景run(key, data?) this智能启动器未运行则启动、已暂停则恢复、休眠中则唤醒pause(key?, data?) this暂停场景不传 key 表示暂停当前场景resume(key?, data?) this恢复已暂停的场景sleep(key?, data?) this让场景休眠不更新、不渲染wake(key?, data?) this唤醒休眠中的场景switch(key, data?) this当前场景进入休眠同时启动/唤醒目标场景stop(key?, data?) this关闭场景不传 key 表示关闭当前场景transition(config) boolean带动画过渡到目标场景get(key) Scene按 key 获取场景引用getStatus(key) number获取场景状态常量getIndex(key?) number获取场景在 scenes 数组中的位置add(key, sceneConfig, autoStart?, data?) Scene?向 Scene Manager 动态添加新场景remove(key?) this移除并销毁场景无法再重启setActive(value, key?, data?) this设置激活状态true恢复false暂停setVisible(value, key?) this设置可见状态isActive(key?) boolean检查场景是否在运行isPaused(key?) boolean检查场景是否已暂停isSleeping(key?) boolean检查场景是否休眠中isVisible(key?) boolean检查场景是否可见bringToTop(key?) this渲染到所有场景之上sendToBack(key?) this渲染到所有场景之下moveUp(key?) this在渲染顺序中上移一位moveDown(key?) this在渲染顺序中下移一位moveAbove(keyA, keyB?) this将 keyB 移动到 keyA 之上moveBelow(keyA, keyB?) this将 keyB 移动到 keyA 之下swapPosition(keyA, keyB?) this交换两个场景的位置队列机制的源码印证在 src/scene/ScenePlugin.js 中start与restart的实现非常直观地展示了排队机制start: function (key, data) { if (key undefined) { key this.key; } this.manager.queueOp(stop, this.key); this.manager.queueOp(start, key, data); return this; }, restart: function (data) { var key this.key; this.manager.queueOp(stop, key); this.manager.queueOp(start, key, data); return this; }可以看到start()无参调用时等价于restart()——它会先排队一个stop操作再排队一个start操作见 src/scene/ScenePlugin.js。而launch()、run()、pause()、sleep()、wake()、switch()等也都通过queueOp排队见 src/scene/ScenePlugin.js所有操作按调用顺序在下一帧的 Scene Manager 更新中执行。渲染顺序与层级控制bringToTop、sendToBack、moveAbove等方法最终委托给 Scene Manager 操作场景数组见 src/scene/SceneManager.js。场景在数组中的位置同时决定更新与渲染顺序数组靠后的场景渲染在上层。此外 src/scene/SceneManager.js 的getIndex直接通过scenes.indexOf(scene)计算位置。当 Scene Manager 正在处理场景isProcessing为 true时这些层级操作也会被排入队列见 src/scene/SceneManager.js。三、Systems 方法速查表this.systhis.sys是每个场景的系统中枢直接操作场景自身的设置settings与状态方法同步生效。完整方法表如下方法返回说明getData()any获取传给此场景的数据getStatus()number当前状态常量isActive()boolean是否 RUNNINGisPaused()boolean是否 PAUSEDisSleeping()boolean是否 SLEEPINGisVisible()boolean是否可见isTransitioning()boolean是否正在过渡进入或离开isTransitionOut()boolean是否正在过渡离开isTransitionIn()boolean是否正在过渡进入canInput()boolean能否接收输入状态处于 PENDING 与 RUNNING 之间setActive(value, data?)Systems恢复true或暂停falsesetVisible(value)Systems设置渲染可见性pause(data?)Systems暂停此场景resume(data?)Systems恢复此场景sleep(data?)Systems使其休眠wake(data?)Systems从休眠中唤醒关键实现的源码解读状态查询isActive()、isPaused()、isSleeping()分别比较settings.status与CONST.RUNNING、CONST.PAUSED、CONST.SLEEPING见 src/scene/Systems.jsgetData()直接返回settings.datasrc/scene/Systems.jsgetStatus()返回settings.statussrc/scene/Systems.js。输入判定canInput()的实现是status PENDING status RUNNING见 src/scene/Systems.js意味着从 INIT 到 RUNNING 之间的场景都可以接收输入。setActive本质是派发setActive(value, data)在 value 为 true 时调用resume(data)为 false 时调用pause(data)见 src/scene/Systems.js。非法操作警告pause()与sleep()在场景不是 CREATING/RUNNING 状态时会打印console.warn提示见 src/scene/Systems.js 与 src/scene/Systems.js。每帧步进step(time, delta)依次发出PRE_UPDATE、UPDATE、POST_UPDATE事件并调用场景的update方法见 src/scene/Systems.js这就是update()每帧执行的来源。四、场景状态常量0 到 9场景的十种状态定义在 src/scene/const.js通过Phaser.Scenes.PENDING、Phaser.Scenes.RUNNING等常量访问常量值含义PENDING0已注册到 Scene Manager但尚未启动或初始化INIT1正在初始化init方法被调用START2启动中create尚未调用LOADING3正在通过 Loader 加载资源加载完成后进入 createCREATING4正在执行create方法RUNNING5完全运行中每帧执行 update 与 renderPAUSED6已暂停不执行 update但仍渲染SLEEPING7休眠不更新不渲染状态保留在内存SHUTDOWN8正在关闭游戏对象与插件被销毁可重启DESTROYED9已彻底销毁无法再启动这十种状态对应场景的完整生命周期PENDING → INIT → START → LOADING → CREATING → RUNNING是主流程RUNNING 可转向 PAUSED仅停更新或 SLEEPING停更新与渲染关闭时进入 SHUTDOWN可重启彻底移除则进入 DESTROYED。生命周期驱动过程生命周期由SceneManager.bootScene()与SceneManager.create()驱动见 src/scene/SceneManager.js关键流程如下init(data)—— 若有定义则调用data 来自settings.dataSystems.start()触发start与ready事件preload()—— 若有定义则调用并执行加载没有 preload 时直接跳过加载流程即init() → create() → update()循环create(data)—— 与 init 收到同一个 data 对象update(time, delta)—— 每帧执行time 为当前毫秒时间delta 为距上一帧的毫秒数平滑处理。五、源码文件映射表以下是 skills/scenes/references/REFERENCE.md 提供的场景系统源码地图按此可快速定位各模块文件职责src/scene/Scene.js基础 Scene 类声明所有注入属性src/scene/Systems.js场景系统生命周期管理、pause/resume/sleep/wakesrc/scene/SceneManager.js游戏级管理器启动场景、驱动生命周期、处理操作队列src/scene/ScenePlugin.jsthis.scene插件面向用户的场景操作 APIsrc/scene/Settings.js根据配置创建场景设置对象src/scene/const.js场景状态常量PENDING0 到 DESTROYED9src/scene/InjectionMap.js将 Systems 属性映射为 Scene 属性src/scene/events/index.js事件名称导出src/scene/events/*_EVENT.js各事件定义文件含 JSDoc 签名src/scene/GetPhysicsPlugins.js解析场景的物理插件src/scene/GetScenePlugins.js解析场景插件六、深入场景注入属性与自定义映射全局管理器所有场景共享通过 src/scene/InjectionMap.js 注入左侧为 Systems 键右侧为场景属性名场景属性类型说明this.gamePhaser.GameGame 实例this.rendererCanvasRenderer \| WebGLRenderer当前渲染器this.animsPhaser.Animations.AnimationManager全局动画管理器this.cachePhaser.Cache.CacheManager非图像资产全局缓存this.pluginsPhaser.Plugins.PluginManager全局插件管理器this.registryPhaser.Data.DataManager全局数据管理器场景间共享this.scalePhaser.Scale.ScaleManager全局缩放管理器this.soundNoAudio \| HTML5Audio \| WebAudioSoundManager声音管理器this.texturesPhaser.Textures.TextureManager全局纹理管理器场景专属系统每个场景独立场景属性类型说明this.sysPhaser.Scenes.Systems场景系统切勿覆盖this.eventsPhaser.Events.EventEmitter场景专属事件发射器this.camerasPhaser.Cameras.Scene2D.CameraManager场景相机管理器this.addPhaser.GameObjects.GameObjectFactory工厂创建并加入显示列表this.makePhaser.GameObjects.GameObjectCreator创建器创建但不加入显示列表this.scenePhaser.Scenes.ScenePlugin场景管理插件start/stop/launchthis.childrenPhaser.GameObjects.DisplayList场景显示列表this.lightsPhaser.GameObjects.LightsManager场景灯光插件this.dataPhaser.Data.DataManager场景专属数据管理器this.inputPhaser.Input.InputPlugin场景输入管理器插件this.loadPhaser.Loader.LoaderPlugin场景加载器插件this.timePhaser.Time.Clock场景时钟插件this.tweensPhaser.Tweens.TweenManager场景补间管理器插件this.physicsPhaser.Physics.Arcade.ArcadePhysicsArcade 物理需配置this.matterPhaser.Physics.Matter.MatterPhysicsMatter 物理需配置自定义注入映射在场景构造函数中通过map配置可以重命名注入属性该机制在 src/scene/InjectionMap.js 的注释中有示例const config { key: MyScene, map: { add: makeStuff, // this.makeStuff 取代 this.add load: loader // this.loader 取代 this.load } };七、常见实战模式7.1 场景切换start / restart / switch / transition// start()关闭当前场景并启动目标当前场景收到 SHUTDOWN目标走完整生命周期 this.scene.start(LevelTwo, { score: 100 }); // restart()关闭并重启当前场景 this.scene.restart({ score: 0 }); // switch()当前场景进入休眠状态保留在内存启动/唤醒目标场景 this.scene.switch(PauseMenu, { fromScene: GameScene }); // transition()带动画过渡默认时长 1000ms this.scene.transition({ target: LevelTwo, duration: 1000, moveAbove: true, // 目标渲染在当前场景之上 sleep: false, // false过渡后停止当前场景默认true休眠它 remove: false, // true过渡后从 Scene Manager 移除当前场景 allowInput: false, // 过渡期间是否允许当前场景接收输入 data: { score: 100 }, onUpdate: function (progress) { // progress 在 duration 内从 0 变化到 1 } });关于transition()的实现细节可查看 src/scene/ScenePlugin.js它通过_elapsed / _duration计算进度并经Clamp限制在 01见 src/scene/ScenePlugin.js过渡结束后根据_willRemove、_willSleep决定移除、休眠或停止当前场景src/scene/ScenePlugin.js。同时注意transition()返回boolean当目标场景不存在、已激活或正在过渡时会返回falsecheckValidTransitionsrc/scene/ScenePlugin.js。7.2 并行场景与渲染层级// launch()并行启动不停止当前场景 this.scene.launch(UIScene, { lives: 3 }); // run()智能启动——未运行则启动、已暂停则恢复、休眠中则唤醒 this.scene.run(UIScene, { lives: 3 }); // 控制并行场景的渲染顺序数组靠后者渲染在上 this.scene.bringToTop(UIScene); // 渲染在最上层 this.scene.sendToBack(Background); // 渲染在最底层 this.scene.moveAbove(GameScene, UIScene); // UIScene 渲染在 GameScene 之上 this.scene.moveBelow(GameScene, Background); this.scene.moveUp(UIScene); // 上移一位 this.scene.moveDown(UIScene); // 下移一位 this.scene.swapPosition(SceneA, SceneB);7.3 场景间数据传递六种方式// 方式 1通过 start/launch/restart/switch/wake/run 传数据 this.scene.start(LevelScene, { level: 5, score: 1200 }); // 在 LevelScene 中 // init(data) { data.level 5 } // create(data) { data.score 1200 } // 方式 2之后任意时刻通过 sys.getData() 取回等价于 settings.data const data this.sys.getData(); // 方式 3全局 registry所有场景共享 this.registry.set(playerHP, 100); // 场景 A const hp this.registry.get(playerHP); // 场景 B // 方式 4场景专属 data 管理器 this.data.set(localValue, 42); this.data.get(localValue); // 42 // 方式 5直接获取场景引用访问公开属性 const otherScene this.scene.get(OtherScene); otherScene.somePublicProperty; // 方式 6监听全局 registry 事件 // 场景 A 中 this.registry.events.on(changedata-playerHP, (parent, value, previousValue) { // 响应变化 }); // 场景 B 中触发 this.registry.set(playerHP, 50);7.4 暂停、恢复与休眠// 暂停停止 update 循环但仍在渲染 this.scene.pause(); // 暂停当前场景 this.scene.pause(OtherScene); // 暂停其他场景 // 恢复重启 update 循环 this.scene.resume(); this.scene.resume(OtherScene, { message: welcome back }); // 休眠不更新也不渲染但状态保留 this.scene.sleep(); this.scene.sleep(OtherScene); // 唤醒 this.scene.wake(); this.scene.wake(OtherScene, { data: here }); // 停止完全关闭清空显示列表与定时器 this.scene.stop(); this.scene.stop(OtherScene); // 状态查询 this.scene.isActive(OtherScene); // boolean this.scene.isPaused(OtherScene); // boolean this.scene.isSleeping(OtherScene); // boolean this.scene.isVisible(OtherScene); // boolean // 独立控制激活/可见性 this.scene.setActive(false); // 暂停 this.scene.setActive(true); // 恢复 this.scene.setVisible(false); // 隐藏但仍更新 this.scene.setVisible(true); // 显示7.5 运行时添加与移除场景// 动态添加参数key、sceneConfig、autoStart、data this.scene.add(BonusLevel, BonusLevelScene, false, { someData: true }); // 移除彻底销毁无法重启 this.scene.remove(BonusLevel); // 用一个类派生多个实例 for (let i 0; i 5; i) { this.scene.add(Level i, new LevelScene(Level i), false); }7.6 跨场景事件通信发射场景与监听场景解耦事件通过目标场景的this.events传播class GameScene extends Phaser.Scene { collectCoin(coin) { coin.destroy(); this.events.emit(addScore, 10); } } // UIScene 与 GameScene 并行运行构造时 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); const gameScene this.scene.get(GameScene); gameScene.events.on(addScore, (points) { this.score points; this.scoreText.setText(Score: this.score); }); } }7.7 场景级配置构造函数super()class Level1 extends Phaser.Scene { constructor() { super({ key: Level1, physics: { arcade: { debug: true, gravity: { y: 200 } } }, loader: { path: assets/levels/1/ }, // pack 在 preload() 之前加载文件——适合进度条等资源 pack: { files: [ { type: image, key: bar, url: loaderBar.png } ] } }); } }按需裁剪插件// 禁用全部默认插件仅保留核心 super({ key: MinimalScene, plugins: [] }); // 此时 this.load、this.tweens、this.time、this.input、this.data、this.lights 均不存在 // 只启用指定插件 super({ key: PreloadScene, plugins: [Loader] }); // 只有 this.load 可用this.tweens、this.time 等为 undefined7.8 安全重启状态重置放 init构造函数只执行一次而init()在每次场景启动/重启时都会执行因此状态重置必须放在init()中class GameScene extends Phaser.Scene { constructor() { super(GameScene); // 错误示范this.gameOver false; —— 只在首次实例化时执行 } init() { // 正确示范每次场景启动都重置状态 this.gameOver false; this.score 0; } create() { // 在 shutdown 时清理避免残留引用 this.events.once(shutdown, () { this.enemies []; }); } }八、场景事件参考所有事件均在this.events场景专属 EventEmitter上发出字符串值即监听名称通过this.events.on(eventname, callback)监听。事件常量定义在 src/scene/events/index.js单个事件文件位于 src/scene/events如PAUSE_EVENT.js、TRANSITION_OUT_EVENT.js等每个文件内含 JSDoc 签名。生命周期事件事件字符串常量回调签名触发时机bootPhaser.Scenes.Events.BOOT(sys)场景首次实例化时供插件使用startPhaser.Scenes.Events.START(sys)场景系统启动供插件使用readyPhaser.Scenes.Events.READY(sys, data)start 之后供用户代码使用createPhaser.Scenes.Events.CREATE(scene)create()方法运行后场景进入 RUNNINGpreupdatePhaser.Scenes.Events.PRE_UPDATE(time, delta)每帧 update 之前updatePhaser.Scenes.Events.UPDATE(time, delta)每帧 update 期间postupdatePhaser.Scenes.Events.POST_UPDATE(time, delta)每帧 update 之后prerenderPhaser.Scenes.Events.PRE_RENDER(renderer)场景渲染之前renderPhaser.Scenes.Events.RENDER(renderer)场景渲染之后状态变更事件事件字符串常量回调签名触发时机pausePhaser.Scenes.Events.PAUSE(sys, data)场景被暂停resumePhaser.Scenes.Events.RESUME(sys, data)场景被恢复sleepPhaser.Scenes.Events.SLEEP(sys, data)场景进入休眠wakePhaser.Scenes.Events.WAKE(sys, data)场景被唤醒shutdownPhaser.Scenes.Events.SHUTDOWN(sys, data)场景正在关闭destroyPhaser.Scenes.Events.DESTROY(sys)场景正被销毁过渡事件事件字符串常量回调签名发出方transitionoutTRANSITION_OUT(targetScene, duration)源场景transitioninitTRANSITION_INIT(fromScene, duration)目标场景init 期间transitionstartTRANSITION_START(fromScene, duration)目标场景create 之后transitionwakeTRANSITION_WAKE(fromScene, duration)目标场景若从休眠唤醒transitioncompleteTRANSITION_COMPLETE(scene)目标场景过渡完成时游戏对象事件事件字符串常量回调签名addedtosceneADDED_TO_SCENE(gameObject, scene)removedfromsceneREMOVED_FROM_SCENE(gameObject, scene)九、常见误区与避坑清单操作是排队而非立即生效调用this.scene.start(X)不会同步启动 X而是在下一次 Scene Manager 更新时执行。不要在当帧内依赖目标场景的状态。start()会关闭调用它的场景this.scene.start(X)停止当前场景并启动 X。若想两者同时运行用launch()或run()。switch()休眠、start()关闭switch()将当前场景保留在内存休眠start()触发完全关闭。休眠场景的事件与引用仍然存活。暂停的场景仍会渲染pause()只停止 update 循环场景仍然绘制。需要同时停止更新与渲染时使用sleep()。不要覆盖this.sysScene 类的 JSDoc 明确警告覆盖它会破坏一切。this.scene.start()无参调用会重启当前场景等价于this.scene.restart()。传给start()/launch()的数据同时出现在init(data)与create(data)存储在settings.data之后可通过this.sys.getData()获取。休眠场景仍能收到其他场景的事件若场景 A 休眠而场景 B 在全局 registry 上发事件A 的监听器依然会触发注意休眠场景上的活跃监听器。渲染顺序 数组顺序数组靠后的场景渲染在上。用bringToTop()、sendToBack()、moveAbove()、moveBelow()控制层级。shutdown 与 destroy 的区别shutdown 是休眠可重启destroy 是永久移除。监听shutdown释放需要在重启时重建的资源监听destroy做最终清理。this.physics与this.matter仅在配置了物理系统时存在否则为 undefined。create事件在create()方法返回之后、状态变为 RUNNING 之后才触发需要做 post-create 设置时可监听该事件。在init()而非构造函数中重置状态构造函数只在首次实例化时运行init()每次启动/重启都运行。在shutdown上清理以避免残留引用监听this.events.once(shutdown, ...)清空持有游戏对象的数组、移除外部事件监听器等。对已销毁游戏对象的残留引用会在重启时引发错误。switch()会重启一个暂停的场景而不是恢复它需要恢复行为时改用run()。场景逆序更新、正序渲染最上层的场景先更新获得输入优先级但最后渲染显示在最上。请在游戏配置的 scene 数组中预先确定渲染顺序。十、相关资源场景技能总览含快速上手示例、生命周期与实战模式skills/scenes/SKILL.md场景系统源码根目录src/scene场景单元测试tests/scene相邻技能游戏初始化配置 skills/game-setup-and-config/SKILL.md、资源加载 skills/loading-assets/SKILL.md、事件系统 skills/events-system/SKILL.md【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表