
Phaser 3.4.0 Miyako 版本解析Container 容器、Matter 物理时间步进与动画事件化重构实战指南【免费下载链接】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 官方仓库中 CHANGELOG-v3.4.md 的完整记录深入解析 Phaser 3.4.0代号 Miyako发布于 2018 年 4 月 12 日这一关键版本的核心技术变化。你将掌握三类高价值能力一是理解并安全使用 beta 阶段的 Container 容器游戏对象二是通过getDelta、autoUpdate、step等新 API 精确控制 Matter 物理引擎的更新频率与时间步长三是掌握动画系统从全局回调到游戏对象事件的重大重构并顺带了解当时引入的数组工具函数与音频链式 API 的实用写法。文中所有结论均以当前仓库源码为佐证可直接对照查阅。版本总览3.4.0 Miyako3.4.0 是 Phaser 3 早期快速迭代中的一次功能密集型发布。从 CHANGELOG-v3.4.md 可以看到本次版本的核心主线有四条Container 游戏对象以 beta 形式首次登场Matter 物理补齐了时间步进timestep的精细化控制能力动画系统完成了一次面向一致性的事件化重构废弃了大量回调Utils.Array工具族大规模扩展并反哺List内部实现。此外还包含大量 Bug 修复与内部重构下文逐一展开。Container 游戏对象beta 引入的父子变换容器设计动机与 beta 状态说明3.4.0 首次以 beta 状态引入 Container 游戏对象。官方在更新日志中明确说明在含有多相机multiple cameras或非规则相机视口irregular camera viewports的场景中使用 Container 存在已知问题其余场景下运行正常。使用 Container 时会打印一条控制台警告提醒开发者该警告会在其离开 beta 后移除。核心行为模型从 Container.js 的类注释可以提炼出 Container 的完整行为语义一个 Container 可以包含其他类型的游戏对象加入后由 Container 负责其渲染子对象会从 Display List 移除并转入 Container 的内部列表子对象的位置自动变为相对 Container 的局部坐标Container 的变换原点固定为 0x0局部空间因此应把 0x0 当作 Container 的中心围绕它正负方向摆放子对象修改Container.x、Container.rotation等变换属性会自动影响全部子对象且支持 Container 嵌套以构造深层变换树Container 可以设置遮罩mask也可作为遮罩使用Canvas 渲染下仅应用 Container 自身的遮罩Container 可启用输入但由于没有纹理必须为其提供一个形状作为命中区域子对象也可独立于 Container 启用输入——但注意若子对象同时设置了origin和负的缩放因子输入区域会发生错位Container 可挂载 Arcade / Impact / Matter 物理刚体但子对象若启用物理当 Container 或其祖先不在 0x0 时可能出现刚体偏移因为子对象物理计算不考虑 Container 变换官方建议在布局上规避。官方还给出了重要的性能提示Container 会为每一个子对象增加额外处理开销嵌套越深代价越高输入事件尤其明显且子对象的显示深度depth设置不如非 Container 场景灵活。因此其结论是不要为用而用每个 Container 的创建都有成本。创建与使用示例// 通过工厂方法创建 Container 并添加到场景 var container this.add.container(400, 300); // 添加子对象子对象坐标将相对 Container 原点 0x0 计算 var sprite this.add.sprite(0, 0, player); container.add(sprite); // 移动、旋转 Container 会连带影响所有子对象 container.x 10; container.rotation 0.05;子对象的顺序调整可使用MoveUp、MoveDown、SendToBack等 Container 内置方法见 Container.js 中对渲染顺序的描述。从源码注释的since 3.4.0标记Container.js可以确认Container 正是从这个版本开始进入 Phaser 3 的生命周期。Matter 物理精细化的时间步进控制3.4.0 对 Matter 物理的时间驱动模型做了一次系统性增强全部体现在 World.js 中并在 MatterWorldConfig.js 的配置类型定义中得到印证。其核心目标是将物理模拟的更新频率与游戏渲染步进解耦允许开发者完全自定义模拟步长。correction时间修正因子新增World.correction属性作为可选的 time correction factor 传入Engine.update。根据 World.js 的说明其定义为delta / lastDelta即 delta 相对上一帧的百分比变化在 delta 恒定或无需修正时恒为 1这也是默认值。它参考了 Time Corrected Verlet 论文思路在 delta 抖动时可提升模拟精度。getDelta自定义 delta 计算函数新的配置/运行时属性getDelta允许你指定自己的函数来计算每帧传给 Matter Engine 的 delta 值。从源码看World.js其默认值为this.update60Hz// World.js 中内置的两个固定步长函数 update60Hz: function () { return 1000 / 60; }, update30Hz: function () { return 1000 / 30; },即默认以 60Hz16.67ms固定步长推进物理。你可以在 Scene 的 Matter 配置中覆盖它// 自定义 delta 计算例如把物理步长固定为 20ms this.matter.world.getDelta function () { return 20; };set60Hz与set30Hz一键固定步长新增set60Hz()与set30Hz()两个方法分别将 Engine 更新率固定为 60Hz 与 30Hz其中60Hz 为默认。需要注意调用二者会把autoUpdate重置为true见 World.js 的注释。autoUpdate解绑物理与游戏步进新增配置与运行时属性autoUpdate默认true即 Matter Engine 与游戏步进由 RequestAnimationFrame 驱动同步更新delta 值由getDelta函数提供。当设为false时物理模拟不再随游戏帧自动推进转而由你显式控制更新时机配合下面的step。step手动推进模拟新增step(delta, correction)方法手动将物理模拟推进一个迭代delta 与 correction 由调用方传入。根据 World.js 的说明step直接绕过enabled与autoUpdate检查也会忽略自定义getDelta因为 delta 由你直接传入若不传参数则使用 Matter 默认的 60Hz 与无修正。典型用法——实现物理固定步长、渲染随帧率的经典架构// Scene 配置中关闭自动更新 var config { physics: { matter: { autoUpdate: false, getDelta: function () { return 1000 / 60; } } } }; // 在场景 update 中手动步进例如每帧累计时间后固定步进多次 update: function (time, delta) { if (this.timeAccumulator 1000 / 60) { this.matter.world.step(1000 / 60, 1); this.timeAccumulator - 1000 / 60; } this.timeAccumulator delta; }新增的 Matter 调试属性debugShowJoint与debugJointColor两个新调试属性可在开启 debug 绘制时postUpdate 调试阶段显示刚体间的关节joint连线。配置类型对照完整的 Matter 世界配置项可参考 MatterWorldConfig.js其中与本次更新直接相关的包括配置项默认值说明correction1Engine.update 的时间修正因子getDeltaupdate60Hz1000/60自定义 delta 计算函数autoUpdatetrue是否随游戏步进自动调用 Engine.updateenabledtrue世界是否启用positionIterations/velocityIterations/constraintIterations6/4/2每次更新的求解迭代次数越高模拟质量越好但性能开销越大从 World.js 的update方法实现可以看出Phaser 后来还引入了 runner 机制帧 delta 平滑、时间缓冲与性能预算来保证模拟稳定但enabled/autoUpdate双开关仍是进入更新的第一道门。动画系统重构从全局回调到游戏对象事件3.4.0 对 Animation API 做了一次使其与 Phaser 3 其余部分保持一致的重构涉及 AnimationState.js 与Animation组件核心变化如下。时间单位统一为毫秒动画的duration、delay、repeatDelay全部从秒改为毫秒与 Tween、Sound 等单位对齐frameRate仍可用来以帧/秒设定动画速度。回调全部移除改为事件驱动onStart、onRepeat、onUpdate、onComplete回调及onStartParams、callbackScope等全部移除。原因正如更新日志所述回调定义在全局动画上100 个 Sprite 共享同一动画时无法只为其中一个 Sprite 触发回调。取而代之的是在播放动画的游戏对象上派发事件animationstartanimationrepeatanimationupdateanimationcomplete更新日志原文中的animtionrepeat为拼写笔误实际事件名为animationrepeat见 ANIMATION_REPEAT_EVENT.js。// 旧写法全局回调3.4.0 起移除 // this.anims.create({ key: walk, frames: ..., onComplete: fn }); // 新写法监听游戏对象事件3.4.0 起 sprite.on(animationstart, function (animation, frame, gameObject, frameKey) { // 只在当前 Sprite 上触发 }); sprite.on(animationcomplete, function (animation, frame, gameObject) { sprite.destroy(); });以 ANIMATION_START_EVENT.js 为例其 JSDoc 明确描述了完整的事件流ANIMATION_START→ANIMATION_UPDATE按帧重复→ANIMATION_REPEAT若设置了重复→ANIMATION_COMPLETE有限或零重复次数时→ANIMATION_COMPLETE_KEY若动画被直接停止则派发ANIMATION_STOP而非ANIMATION_COMPLETE若在播放中被重启则派发ANIMATION_RESTART。事件全部从承载动画的 Game Object 派发而不是从动画本身派发这赋予了按对象粒度控制的能力。AnimationFrame.onUpdate回调也被移除改用游戏对象上的animationupdate事件其第 2 个参数即当前动画帧。方法集重构get/set 化 返回游戏对象组件方法做了大规模重命名核心规则是play/pause/resume/restart/stop/load/delayedPlay等动作类方法改为返回父级 Game Object支持链式调用而所有取值方法统一为getXxx、设值方法统一为setXxx新增stopAfterDelay(ms)、stopOnRepeat()、stopOnFrame(frame)、setDelay、getDelay、setProgress、getProgress、setRepeat、getRepeat、setRepeatDelay、getRepeatDelay、setTimeScale、getTimeScale、setYoyo、getYoyo、isPaused移除delay、paused、progress、repeat、repeatDelay、timeScale、totalFrames、totalProgres该方法是笔误且无实际功能、yoyo等旧方法。此外updateFrame现在会调用setSizeToFrame使游戏对象的宽高自动适配当前帧修复 #3473并支持带自定义 pivot 的动画帧注入到对象 originAnimation.getFrameByProgress(progress)返回最接近给定进度值的帧5 帧动画传 0.5 返回中间帧destroy全面清理事件与内部数组。变更日志还特别指出旧版本中修改组件上的yoyo属性无效因为只读取全局属性现在会正确读取局部值支持按游戏对象指定 yoyo。音频 APIWebAudio 与 HTML5 音频的链式方法为统一两个音频后端的调用体验3.4.0 为WebAudioSound与HTML5AudioSound补齐了链式chainableAPI// 链式调用 sound.setVolume(0.5).setMute(false).setLoop(true).setSeek(5000);四个方法为setMute、setVolume、setSeek、setLoop对应实现见 HTML5AudioSound.js 等文件。同时3.3.0 中放置在BaseSound上的setRate/setDetune被下移到WebAudioSound与HTML5AudioSound两个具体类中——因为两种后端对 rate/detune 的处理方式不同。更新日志还修复了BaseSoundManager.rate与BaseSoundManager.detune错误调用setRate的问题现在正确调用calculateRate见 BaseSoundManager.js 与 BaseSound.js。BaseSound的rate/detune属性被移除总是在子类中设置并新增destroy事件派发。Utils.Array工具族与 List 回调机制3.4.0 引入了一批通用的数组操作函数全部位于 src/utils/array 目录并在 index.js 中汇总导出增删Add、AddAt、Remove、RemoveAt、RemoveBetween、Replace顺序调整BringToTop、SendToBack、MoveUp、MoveDown、MoveTo、Swap遍历与统计Each、EachInRange、CountAllMatching、GetAll、GetFirst取值GetRandom由GetRandomElement更名而来这些函数普遍支持可选的属性/值匹配与回调参数。List内部随后全面改用这些函数实现并新增了两个可选回调List.addCallback每次有新子对象加入 List如 Display List时触发List.removeCallback每次有子对象被移除时触发。// 利用 addCallback 在子对象加入显示列表时自动处理 this.children.addCallback function (child) { console.log(added:, child); };同时List的多个方法add、addAt、addMultiple、remove、removeAt、removeBetween、removeAll新增了skipCallback可选参数List.add现在接受数组并转交addMultiple。旧的getByKey、sortIndexHandler被移除改用getFirstsort签名简化addMultiple并入add。另外Group.destroy新增可选参数destroyChildren为true时自动销毁全部子对象默认false不破坏既有 API对应实现见 Group.js。其余值得关注的新特性BitmapText.letterSpacing可设置正/负数值来增加/减少字符间距Graphics.slice轻松绘制吃豆人或扇形切片形状ScenePlugin.restart()语义更清晰的重启当前场景等价于无参startScene 配置新增mapAdd用于扩展而非覆盖场景的默认注入映射实现见 Settings.js——Merge(InjectionMap, GetValue(config, mapAdd, {}))配置类型见 SettingsConfig.jsGetBounds的四个角点方法getTopLeft/getTopRight/getBottomLeft/getBottomRight新增includeParent可选参数可将所有祖先变换计入返回点TransformMatrix新增a/b/c/d/tx/ty的 getter/setter以及scaleX/scaleY/rotation只读 getter并新增destroy()清空内部数组Tilemap.addTileset现在支持传入 Sprite Sheet 或 Canvas 作为纹理 key 并在 WebGL 下正常工作此前会显示损坏的 tilemapUtils.Array.FindClosestInSorted新增可选key参数可扫描排序数组中对象某个顶层属性的最近匹配。值得留意的 Bug 修复更新日志中的 Bug 修复部分同样包含大量可复用的经验精选如下RenderTexture修复 WebGL 下 tint 恒为 0xffffff 导致 alpha 被忽略的问题#3385改用 ComputedSize 组件使getBounds可用#3451destroy不再抛错#3475PathFollowerPathFollower.start更名为startFollow修复setPath仍调用旧名的问题键盘Keyboard.JustDown/JustUp过早重置导致在update循环中失效#3490TileSpriteWebGL批次中调节tilePosition避免长时间滚动后 UV 数据溢出导致的贴图损坏#3402Arcade 物理静态刚体补上了缺失的setOffset方法#3465Scene 数据传递以data参数启动新 Scene 时若 Scene 尚未完全 boot数据现在会正确传入init/create并存入 Scene Settings 的data属性#3363MatterSetBody 组件不再对没有 origin 组件的对象如 Graphics、Container调用setOriginMatter Image/Sprite 补上destroy方法#3516GamepadAxis 的getValue正确应用阈值阈值从 0.05 提高至 0.1并将低于阈值的值归零CanvasPool.first此前永远返回null现已修复#3520CSP 合规内部 RTree 库rbush原先在运行时以 eval 方式动态创建函数违反 CSP 策略现已改为 generator 定义#3441。内部重构与接口调整摘要InteractiveObject.js更名为CreateInteractiveObject.js与职责相符并避免文档类型错误Camera Controls 模块导出从Fixed/Smoothed更名为FixedKeyControl/SmoothedKeyControlGamepadManager 改为直接继承 EventEmitter与 KeyboardManager 一致Scene 配置的extend属性现在会阻止覆盖sys属性且若extend中定义了对象类型的data会将其填充到场景 Data ManagerSceneManager._processing更名为公开只读布尔属性isProcessing新增只读isBootedMatter World 关闭时会调用MatterEvents.off清除全部事件并移除本地监听器Rectangle.Union内部缓存变量允许输入矩形兼作输出矩形而不被污染。结语与查阅建议3.4.0 虽然只是 Phaser 3 早期的一个增量版本却奠定了若干沿用至今的核心机制Container 成为后续容器/图层体系的基石Matter 的固定步长控制模式沿用至今相关实现仍可对照 World.js动画的事件化模型则直接决定了现代 Phaser 动画的编程范式事件常量定义见 src/animations/events 目录。建议读者将本变更日志与 Container.js、AnimationState.js、World.js 的源码注释配合阅读即可获得变更原因 → 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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考