ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Phaser 3.60 核心机制详解:Game、Config 与 Device 系统的新特性、更新与修复

Phaser 3.60 核心机制详解:Game、Config 与 Device 系统的新特性、更新与修复 Phaser 3.60 核心机制详解Game、Config 与 Device 系统的新特性、更新与修复【免费下载链接】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 3.60.0 版本中Game、Game Config游戏配置与Device设备检测三大核心系统。它们构成了每一个 Phaser 应用的地基Game实例负责启动、全局系统装配与主循环调度Config负责将传入的配置对象解析为最终生效的参数而Device则负责探测当前浏览器环境的能力与类型。读完本文你将掌握 3.60 新增的全局暂停/恢复 API、稳定排序开关stableSort、独立事件总线的全局数据仓库registry以及本版本对渲染器选择与浏览器检测策略的重要行为变更。原文记录于 changelog/v3/3.60/Game.md完整版本更新列表可查阅 changelog/v3/3.60/CHANGELOG-v3.60.md。一、Game、Config 与 Device 新特性New Features1.1GameConfig.stableSort与Device.features.stableSort可控的深度排序策略Phaser 内部大量场景依赖深度排序depth sorting例如 DisplayList、Container、LightsManager、ParticleEmitter 与 structs/List。排序的稳定性stable意味着当多个元素排序键相等时它们保持原有的相对顺序——这对渲染次序、粒子生命顺序至关重要。3.60 新增了GameConfig.stableSort配置项默认值-1用数值控制内部深度排序走哪条代码路径值行为0或false使用 Phaser 自带的稳定排序函数传统版本适用于旧浏览器1或true直接依赖浏览器原生 ES2019 稳定版Array.sort仅现代浏览器-1自动检测由 Phaser 根据浏览器类型与版本判断哪种方式最佳该配置在 src/core/Config.js 中被解析并将结果同步到Device.features.stableSortthis.stableSort GetValue(config, stableSort, -1); if (this.stableSort -1) { this.stableSort (Device.browser.es2019) ? 1 : 0; } Device.features.stableSort this.stableSort;Device.features.stableSort的默认声明位于 src/device/Features.js其含义是当前浏览器的Array.sort实现是否稳定。Phaser 自带的稳定排序函数Phaser.Utils.Array.StableSortsrc/utils/array/StableSort.js是**无递归的归并排序merge sort**实现基于 Two-Screen/stable 0.1.8。它的执行逻辑非常清晰先判断Device.features.stableSort为真则直接调用原生array.sort(compare)以充分利用引擎内置的高效排序否则逐轮以 1、2、4、8……递增的 chunk 尺寸执行RunPass归并并在奇数次归并后把结果拷贝回原数组。每个排序调用点都会优先走这一统一入口。1.2Device.es2019ES2019 原生能力探测Device.es2019是一个新的布尔属性用于通过浏览器类型 版本的基础检测判断当前浏览器是否原生支持 ES2019 特性典型代表就是稳定的数组排序。从 src/device/Browser.js 的实现可以看到各浏览器的判定规则Edge新版UA 含Edg/直接判定支持OperaUA 含OPR直接判定支持ChromechromeVersion 69时支持ES2019 稳定排序自 Chrome 70 起原生可用FirefoxfirefoxVersion 10时支持Mobile SafariiOS直接判定支持桌面 SafarisafariVersion 10时支持IE / Trident不支持。该属性会在stableSort为-1时被 Config 读取从而决定内部排序走原生路径还是 Phaser 自研路径。值得注意的是源码注释同时指出这种方式并非百分百可靠但偏向保守errs on side of caution即在不明确时宁可回退到自带的稳定排序实现也不冒险依赖原生排序的稳定性。1.3Game.pause、Game.resume与Game.isPaused一键冻结整个游戏3.60 为Game实例新增了三个直接可用的全局控制能力见 src/core/Game.jsGame.pause()暂停整个游戏与所有 Phaser 系统。注意它不会暂停正在进行的 Loader 请求Game.resume()恢复整个游戏使所有系统继续运行、重新开始渲染Game.isPaused布尔属性标记游戏主循环当前是否处于暂停状态也可以被直接赋值切换。// 暂停整个游戏 game.pause(); // 恢复整个游戏 game.resume(); // 直接切换暂停状态 game.isPaused true;这两个方法与页面隐藏onHidden/onVisible走的是不同路径。onHidden会真正调用this.loop.pause()停掉 TimeStep 主循环而Game.pause只把isPaused置为true主循环TimeStep / rAF仍然继续步进只是在 Game.step 与 Game.headlessStep 的开头做短路返回跳过整个更新与渲染流程。因此pause()的语义更接近冻结帧浏览器仍在收到帧回调但 Phaser 不再更新任何系统。源码中对isPaused的 JSDoc 也明确解释了这一点Is the Game currently paused? This will stop everything from updating, except theTimeStepand related RequestAnimationFrame or setTimeout. Those will continue stepping, but the core Game step will be skipped.同时pause()与resume()会分别触发Phaser.Core.Events#PAUSE与Phaser.Core.Events#RESUME事件只有状态发生实际变化时才触发避免重复广播并且只在确实发生了状态切换时发送事件避免重复广播。开发者可以在game.events上监听这两个事件来响应全局冻结/解冻game.events.on(pause, () { console.log(游戏已全局暂停); }); game.events.on(resume, () { console.log(游戏已恢复); });二、Game、Config 与 Device 更新Updates2.1 Opera 与 Edge 的浏览器 UA 检测更新3.60 更新了 Device.Browser 中 Opera 与 Edge 的检测逻辑采用这两个浏览器现代版本实际使用的 User-Agent 字符串Edge 通过/Edg\/\d/匹配现代 Edge 基于 ChromiumUA 中使用Edg/标记Opera 通过/OPR/匹配。该变更会破坏与非常老旧版本 Opera / Edge 的兼容性但换来的是对现代版本的正确识别。从源码可见这一改动同时影响了Device.es2019的判定Edge 与 Opera 在命中后均直接置es2019 true。2.2Device.safariVersion现在会被正确填充此前Device.safariVersion始终为undefined3.60 起桌面 Safari 的 UA 命中/Version\/(\d\.\d(\.\d)?) Safari/后会将主版本号解析进Browser.safariVersionsrc/device/Browser.jsBrowser.safari true; Browser.safariVersion parseInt(RegExp.$1, 10); Browser.es2019 (Browser.safariVersion 10);Device.safariVersion的 JSDoc 定义在 src/device/Browser.js。该属性现在同样参与 ES2019 能力判定并且在 Phaser 其他子系统例如 src/device/Audio.js 中基于Browser.safari Browser.safariVersion 9的音频能力分支中被引用因此填充正确值对音频等功能的特性探测同样有意义。2.3Game.registry改用独立的事件发射器Game.registry是一个DataManager实例作为全局游戏数据仓库使用初始化代码见 src/core/Game.jsthis.registry new DataManager(this, new EventEmitter());3.60 之前它复用Game自身的事件发射器这意味着如果开发者在 Registry 上广播自定义事件很容易与 Phaser 核心系统发出的事件发生命名冲突。3.60 起 Registry 拥有自己的 EventEmitter可以安全地用来发射与监听自定义事件而不再干扰Game实例自身的事件流// 全局数据仓库存取任意游戏级数据 game.registry.set(playerScore, 100); // 现在可以安全地在 registry 上使用自定义事件 game.registry.events.on(my-custom-event, handler); game.registry.events.emit(my-custom-event, payload);由于DataManager本身支持set/get/has/remove等数据操作并可通过game.registry.events广播变更事件这一改动让全局数据仓库真正成为一个可与场景数据Scene-level DataManager区分开、且事件命名空间隔离的独立设施。三、Game、Config 与 Device 的 Bug 修复Bug Fixes3.1headlessStep在PRE_RENDER前重置SceneManager.isProcessingGame.headlessStep是 HEADLESS 渲染模式专用的游戏步进方法src/core/Game.js。在 3.60 中它在触发PRE_RENDER事件之前执行了this.scene.isProcessing falsethis.scene.update(time, delta); // Render this.scene.isProcessing false; eventEmitter.emit(Events.PRE_RENDER, null, time, delta);这修复了 HEADLESS 模式下 Scene Manager 无法处理游戏启动后新添加的 Scene的问题对应 issue #5872 与 #5974。根因是若不重置isProcessing标志Scene Manager 会认为上一帧的处理流程尚未结束从而跳过新注册 Scene 的后续更新。该修复保证了 headless典型用途是自动化测试与无头服务器端模拟环境下动态添加场景同样可靠。3.2 移除从未使用的Config.domBehindCanvasConfig.domBehindCanvas属性被删除——它在内部从未被使用过issue #5749。该配置原意是控制 DOM 容器是否置于 Canvas 之后但 Phaser 内部根本没有读取它的代码路径属于长期存在的死配置。移除后开发者不应再依赖该字段DOM 容器的层级关系应由Config.dom.createContainer与Config.dom.pointerEvents默认none等有效配置控制见 src/core/Config.js。3.3 不支持 WebGL 时显式Phaser.WEBGL直接报错而非静默回退行为变更issue #5583当设备不支持 WebGL 时若renderType设置为Phaser.WEBGL创建游戏将直接抛出错误不再自动回退到 Canvas若需要自动回退能力请使用AUTO渲染类型。底层实现位于 src/core/CreateRenderer.js。AUTO模式会根据Device.features.webGL自动选择 WebGL 或 Canvas而一旦明确指定了WEBGL代码会在 WebGL 不可用时抛出Cannot create WebGL context, aborting.if (config.renderType CONST.AUTO) { config.renderType Features.webGL ? CONST.WEBGL : CONST.CANVAS; } if (config.renderType CONST.WEBGL) { if (!Features.webGL) { throw new Error(Cannot create WebGL context, aborting.); } }这一变更的意图是避免开发者以为在用 WebGL 实际却跑在 Canvas 上的隐性降级——如果你明确要求 WebGL例如依赖 WebGL 专属特效或渲染管线静默回退反而会导致功能不可用且难以排查。需要兼容旧设备时应显式使用AUTO。另外若customEnvironment为true或提供了自定义canvas则必须显式指定renderType不能使用AUTO否则同样会抛错。3.4 配置中的render对象不再覆盖顶层配置此前只要 Game Config 中包含了render对象就会整体擦除顶层已有的渲染配置。3.60 起issue 修复见 src/core/Config.jsrender对象中的设置优先于顶层游戏配置但两者会同时生效——render中未覆盖的顶层设置依然保留。从 Config 源码可以看到所有渲染相关属性都采用双重取值策略先读render对象再回退到顶层配置例如this.antialias GetValue(renderConfig, antialias, true, config); this.roundPixels GetValue(renderConfig, roundPixels, false, config); this.transparent GetValue(renderConfig, transparent, false, config); this.clearBeforeRender GetValue(renderConfig, clearBeforeRender, true, config);GetValue(renderConfig, key, default, config)的最后一个参数是兜底源——render中没有该项时会继续从顶层config取值。这样顶层配置与render子对象可以按细粒度覆盖的方式合并。3.5 空render: {}不再把已设置的属性重置为默认值配套修复issue #6097此前如果配置中出现空对象如render: {}会导致已设置的顶层属性被默认值覆盖。3.60 修正了取值逻辑空对象不会触发覆盖保证传了但不填与完全不传行为一致。3.6PluginManager.installScenePlugin的插件索引恢复PluginManager.installScenePlugin方法现在会检查插件是否缺失于本地keys数组中若缺失则将其添加回去见 src/plugins/PluginManager.js。这修复了某些流程如重复安装或插件列表被外部改动下插件键丢失、导致场景插件无法按名称访问的问题。四、综合实战示例将 3.60 的核心新特性组合起来可以得到一个完整的实战骨架——显式指定渲染类型、自动稳定排序、全局暂停控制与独立事件总线的全局数据仓库var config { type: Phaser.AUTO, // 需要兼容回退时使用 AUTO显式 WEBGL 不支持时会直接报错 width: 800, height: 600, stableSort: -1, // -1 自动检测 / 1 用原生 ES2019 / 0 用 Phaser 自带稳定排序 parent: game-container, scene: { create: function () { // 在 registry 上使用独立的事件总线 this.registry.events.on(score-changed, function (score) { console.log(新分数, score); }); }, update: function () { if (this.input.keyboard.addKey(P).isDown) { this.game.isPaused !this.game.isPaused; // 直接切换全局暂停 } } } }; var game new Phaser.Game(config); // 全局事件响应暂停与恢复 game.events.on(pause, function () { console.log(已暂停); }); game.events.on(resume, function () { console.log(已恢复); });其中stableSort的三种取值策略建议如下面向现代浏览器Chrome 70、Firefox 70、Safari 11、新版 Edge/Opera的新项目保持默认-1即可Phaser 会自动探测需要完全可预测、跨环境一致的排序行为显式设置1遇到旧浏览器内核IE/Trident 等且需要稳定排序设置0强制走 Phaser 自带的无递归归并排序。总结Phaser 3.60 对Game、Config、Device三个地基模块的打磨非常务实Game.pause / resume / isPaused补齐了不依赖页面可见性、由开发者主动控制的全局冻结能力stableSortDevice.es2019让深度排序既能吃到现代引擎的原生性能、又能安全兼容旧内核Game.registry独立事件总线消除了全局数据仓库与游戏事件命名空间互相污染的风险而渲染器不静默回退与render配置合并规则的修正则让开发者的配置意图真正如实生效。这些变化共同提升了 Phaser 3.60 在真实多端环境下的可控性与可诊断性是升级到 3.60 时值得优先了解的核心改动。如需查阅本版本全部更新可继续阅读 changelog/v3/3.60/CHANGELOG-v3.60.md以及同一版本的 Scene.md、Timestep.md、ScaleManager.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),仅供参考
返回列表