ARTICLE DETAIL

资讯详情

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

melonJS 20.x 迁移完全指南:从 19.x 升级到 Application.init()、WebGL 2/WebGPU 与新渲染管线

melonJS 20.x 迁移完全指南:从 19.x 升级到 Application.init()、WebGL 2/WebGPU 与新渲染管线 游戏开发图形学【免费下载链接】melonJSa modern lightweight HTML5 game engine项目地址https://gitcode.com/gh_mirrors/me/melonJS点击查看免费下载本篇指南围绕 melonJS 20.x 相对 19.x 及更早版本的破坏性变更展开逐项说明哪些旧 API 已移除、已废弃或已改名并给出可直接落地的迁移代码。读完你将掌握 20.x 强制异步Application.init()的正确启动方式、用addPostEffect()取代renderable.shader的后处理特效新 API、video.AUTO的 WebGPU → WebGL 2 → Canvas 三级回退语义、一张完整的废弃导出对照表以及如何避开当前仓库示例中残留的旧式写法。本文所述内容以本仓库 packages/melonjs 当前版本20.8.0见 package.json为准。为什么需要这份迁移指南网上流传的大多数 melonJS 教程、博客与代码片段描述的仍是 19.x 甚至更早的 API。用这些记忆中的知识写出的代码往往看起来完全正确却在运行时静默失败——没有 canvas 被挂载、没有帧循环启动、画面一片空白。原因在于 20.0CHANGELOG.md 中的 melonJS 2 里程碑是一次底层渲染架构重构引入了 WebGPU 后端并退役了 WebGL 1 路径video.init()等旧入口被整体移除引擎启动从构造即初始化改为构造 显式await init()两步渲染相关的类Compositor系列与实体 APIEntity被新架构替代。下文按从记忆中复现代码时最可能踩中的概率排序逐条给出新旧对照。1.Application.init()是强制且异步的新旧代码对照20.0 起new Application(...)只负责构建对象不再替你初始化// ✗ pre-20.x —— 构造函数内部替你调用了 init(width, height, options) const app new Application(800, 600, { parent: screen }); app.world.addChild(sprite); // 添加了子节点但永远不会被渲染 // ✓ 20.x const app new Application(800, 600, { parent: screen }); await app.init(); // REQUIRED —— 必须调用并等待 app.world.addChild(sprite);签名也变了19.x 的init(width, height, options)在 20.x 中不接受任何参数——传入的参数会被忽略所有设置均来自构造函数。因此原本就使用new Application(...)的 19.x 代码同样需要补上await app.init()否则什么都不显示。为什么是异步的init()之所以是async是因为获取 WebGPU 设备在 Web 平台上本质上是异步操作需要协商 adapter/device。这一点在源码中有明确注释Canvas 与 WebGL 后端获取 context 时不会挂起、init()可以同步完成但 WebGPU 不行——init()未 resolve 的 Application 没有renderer。见 application.ts 的 JSDoc 与 const.ts 的说明。关键点是不存在同步替代方案也不存在替你补调用的自动回退。更隐蔽的是缺失init()不会报错——构造函数仍然构建了app.world子节点可以照常添加但没有 canvas 被追加到parent元素应用从不订阅帧循环app.renderer与app.viewport保持undefined若先构造Sprite或Text反而会在未初始化的全局game上抛出TypeError。init()调用存在额外约束application.ts重复调用init()是被警告的空操作会追加第二个 canvas 并抛弃当前 renderer因此引擎拒绝执行已销毁destroy()的实例再调用init()会抛出异常——destroy()现在是终态的重建请构造新实例若首次尝试因 WebGPU 协商失败而中途创建过 renderer重试前会自动释放该半成品后端避免泄漏。video.init(...)已不存在video.init(...)已从引擎中删除。现在的video模块只导出四个渲染器常量AUTO、CANVAS、WEBGL、WEBGPU——没有可供调用的init。任何形如me.video.init(800, 600, {...})的代码都来自已移除的 API应改为构造Application并await app.init()。video.renderer、video.createCanvas()、video.getParent()也一并移除分别改用app.renderer、app.renderer.createCanvas()与app.getParentElement()见 CHANGELOG.md 20.0.0 的 Changed (breaking)。命名空间导入仍然有效注意import * as me from melonjs依然可用me.Sprite这样的写法完全没问题。被移除的是全局引导globals bootstrap而不是命名空间导入本身。迁移时无需把me.xxx改成别的形式只需补齐启动流程。2. 后处理特效取代了shader属性弃用与替代renderable.shader ...自19.2.0起标记为废弃当前 API 是后处理特效post effect// ✗ deprecated —— 自 19.2.0 起废弃 mySprite.shader new ShaderEffect(app.renderer, glslBody); // ✓ 20.x mySprite.addPostEffect(new ShaderEffect(app.renderer, glslBody));底层实现位于 renderable.jsshader的 getter 实际上返回postEffects[0]setter 在替换前会销毁既有特效而addPostEffect(effect)只是把特效推入postEffects数组并返回该特效。配套 API 还包括getPostEffect(effectClass)——传类时返回第一个匹配的特效不传参时返回整个特效数组removePostEffect(effect)——移除指定特效clearPostEffects()——清空全部特效renderable.js。陷阱removePostEffect()会销毁特效这是迁移中最容易踩的坑removePostEffect()会调用特效的destroy()——赋值renderable.shader同样会销毁被替换掉的对象。因此移除再重新添加拿回的是一个 GPU 资源已被释放的僵尸对象。唯一例外是携带shared true的特效它在多个 renderable 间被复用销毁它会破坏其它引用方所以源码在销毁前统一判断if (typeof effect.destroy function !effect.shared)见 renderable.js。临时关闭某个特效请切换effect.enabled属性而不是移除后重新添加。3. WebGL 2 是基线WebGPU 是默认首选video.AUTO的选择顺序video.AUTO默认值现在的尝试顺序是WebGPU → WebGL 2 → CanvasWebGL 1 已彻底移除。四个常量定义于 const.ts常量值语义CANVAS0强制 Canvas。性能较低、无可编程管线但兼容一切环境含 GPU 被驱动策略屏蔽的嵌入式 webviewWEBGL1强制 WebGL 2。init()在 WebGL 2 不可用时直接 reject不会静默回退到 CanvasAUTO2默认。先尝试 WebGPU完整初始化并协商设备失败则回退 WebGL 2再失败回退 Canvasinit()总会 resolveWEBGPU3强制 WebGPU。不可用时init()同样直接 reject不降级AUTO 下的 WebGPU 尝试是一次完整的后端初始化支持与否只能通过协商 adapter/device 来证明失败时会释放半成品后端并打印AUTO: WebGPU unavailable (...) — falling back to WebGL然后落到同步探测的候选上——整个逻辑可见于 application.ts。此外运行时还可以用URI 片段强制后端#webgpu、#webgl、#canvas均被支持见 const.ts便于针对特定后端调试。对业务代码的三点影响运行在哪个后端是运行时事实。不要写假设一定在跑 WebGL的代码。自定义着色器可以一份资源同时携带 GLSL 与 WGSL。new ShaderEffect(renderer, { glsl, wgsl })让同一个特效在 WebGL 与 WebGPU 上都能运行两套代码共享 uniform 名称一个setUniform服务两个后端。依赖可编程管线的特性在 Canvas 上是惰性的——只警告一次而不是抛异常。需要 GPU 的功能Camera3d、ShaderEffect、Light2d法线贴图、GPU tilemap在 Canvas 上会静默失效因此若场景依赖它们应显式使用WEBGL或WEBGPU让失败在启动时显性化而不是运行时得到一张黑屏const.ts。值得一提的还有GLSL ES 1.00 的用户着色器在 WebGL 2 上可原样编译已有着色器代码无需改动CHANGELOG.md 20.0.0。4. 仍然存在、但不应在新代码中使用的废弃导出以下符号在当前版本中依然可以解析并运行但均已被官方替代 API 取代。废弃实现在 deprecated.js 中统一维护——每个类/函数构造或调用时都会通过warning()打印一条已废弃、请改用 xxx的控制台提示废弃符号自版本改用CanvasTexture17.1.0CanvasRenderTargetCompositor18.1.0WebGLBatcherPrimitiveCompositor18.1.0PrimitiveBatcherQuadCompositor18.1.0QuadBatcherMath大写18.0.0math小写device.requestFullscreen/exitFullscreen19.7.0app.requestFullscreen()/app.exitFullscreen()renderable.shader ...19.2.0addPostEffect()Entity18.1.0Sprite/RenderableBodyloader.onload/onProgress/onError18.2.020.3 已移除LOADER_*事件或preload(assets, onloadcb)response.overlap/overlapN/overlapV—response.depth/response.normalsetLineWidth()17.3.0lineWidth属性上表同时涵盖了已被彻底移除的项loader.onload系列以及仍在导出的项其余所有。其中两点需要特别强调。重点一Entity仍在导出但形态已过时Entity自 18.1.0 起废弃却仍然导出因此旧代码可以编译通过、运行正常同时却是 20.x 的错误形态——这正是它比直接报错更危险的地方。废弃原因记录在 entity.jsEntity在内部多包了一层——一个子Renderable通常是Sprite被塞进一个同时持有Body的父对象里导致锚点语义混乱、this.renderable.xxx的间接 API、以及一套与引擎其它部分不一致的自定义坐标渲染管线。正确做法是直接继承Sprite或Renderable并在构造函数里挂一个Bodyclass PlayerSprite extends me.Sprite { constructor(x, y, settings) { // 用图集动画帧创建 Sprite super(x, y, { ...game.texture.getAnimationSettings([ walk0001.png, walk0002.png, walk0003.png ]), anchorPoint: { x: 0.5, y: 1.0 } }); // 附加物理体优先使用 Tiled 形状或自行定义 this.body new me.Body(this, settings.shapes || new me.Rect(0, 0, settings.width, settings.height) ); this.body.collisionType me.collision.types.PLAYER_OBJECT; this.body.setMaxVelocity(3, 15); this.body.setFriction(0.4, 0); // 动画、翻转、着色全部直接调用不再经过 this.renderable this.addAnimation(walk, [walk0001.png, walk0002.png, walk0003.png]); this.setCurrentAnimation(walk); } update(dt) { if (me.input.isKeyPressed(right)) { this.body.force.x this.body.maxVel.x; this.flipX(false); } return super.update(dt); } onCollision(response, other) { return true; // solid } }完整示例含图集动画与独立 spritesheet 两种形态见 entity.js。这一写法也符合行业惯例——给 renderable 挂物理体是其它主流引擎的标准模式。重点二大写的Math会遮蔽全局Mathexport * as Math from ./../math/math.tsdeprecated.js意味着如果粗心地导入它大写Math会遮蔽全局Math对象。旧文档里的me.Math.random()解析到的正是这个废弃的再导出而不是全局Math.random()。新代码请统一使用小写math命名空间。全屏与加载回调的迁移全屏device.requestFullscreen(element)/device.exitFullscreen()自 19.7.0 废弃。它们在 deprecated.js 中的实现仍需从全局game反查父元素新入口app.requestFullscreen()/app.exitFullscreen()直接使用 Application 自己的parentElement不再依赖全局查找。加载回调loader.onload/onProgress/onError曾是 ES 模块命名空间上的let绑定——赋值loader.onProgress fn本身就会抛TypeError因此这个文档化的回调 API从来无法真正使用20.3 将其彻底移除CHANGELOG.md 20.3.0。迁移方式有二监听事件LOADER_COMPLETE/LOADER_PROGRESS/LOADER_ERROR定义于 event.ts字符串值分别为me.loader.onload/me.loader.onProgress/me.loader.onError或使用preload(assets, onloadcb)的回调参数——它同时返回可await的 Promiseloader.js。碰撞响应response.overlapN/response.overlapV是传统 2D 碰撞分离向量response.overlap是最短碰撞轴上的重叠量。响应对象 response.js 中仍保留这些字段用于兼容但更可移植的读法是response.depth最短轴重叠量与response.normal接触法线。注意 20.0 为 3D 碰撞引入了Box3d形状Z 方向以overlapNZ/overlapZ标量形式附加不把overlapV拓宽成Vector3d以免破坏所有既有 2D 消费者——平面形状之间的碰撞行为完全不变。5. 全局game不再是旧形态game仍然导出但自 20.0 起它的语义变了它指向最近一次成功初始化的Application并且在第一个init()resolve 之前是undefined。在 application.ts 中game是let绑定只在引擎初始化时通过setDefaultGame(app)赋值。因此在模块作用域读取game会得到undefined。正确做法是把Application实例作为参数传递Stage#onResetEvent(app, ...args)与Stage#onDestroyEvent(app)会直接收到 app 实例——签名定义于 stage.ts任何 renderable 都可以通过parentApp属性触达当前应用。这也呼应了第 1 节旧代码模块顶层就game.texture.xxx的写法在 20.x 会静默失败因为那时game尚未就绪。6. Node 与 SSR开箱即用零运行时依赖melonJS 在 Node 环境下可以干净地导入——这对同构isomorphic应用与构建工具链非常有用。截至 20.3引擎没有运行时依赖因此不要为globalThis、String.trimStart、String.trimEnd添加 polyfill发布产物目标为ES2022任何能解析该产物的环境本身就已内置这些能力。7. 浏览器支持ES2022 目标与转译陷阱发布产物面向ES2022并使用了私有类成员private class members。早于该标准的浏览器在加载阶段就会解析失败——不是用到某个特性时才报错而是整份文件无法 parse。若需要支持旧浏览器请自行转译。但注意一个关键陷阱转译只处理语法syntax内置方法built-in methods需要单独的 polyfill而打包器bundler的target设置永远不会替你添加它们见 CHANGELOG.md 20.3.0 的 docs 修复条目。此外构建配置默认跳过node_modules所以即使把target调得很低melonJS 也可能根本没被转译。本仓库示例中的过时内容不要照学本仓库 packages/examples 中的示例是组装 melonJS 的最佳参考但少数文件残留了过时的注释或旧式调用。以下内容不要照着学webgpu示例中有一条声称video.AUTOnever selects the WebGPU backend的注释ExampleWebGPU.tsx。这是 20.x 之前的遗留——AUTO优先尝试 WebGPU。代码本身是对的注释是错的。若干示例仍在赋值viewport.shader .../sprite.shader ...这已废弃addPostEffect()才是现行 API。有五个文件对 HUD 设置了this.z Number.POSITIVE_INFINITY——该属性根本不存在那些 HUD 能置顶仅仅是因为它们最后被添加。正确做法是让 HUD 成为最后添加的子节点或用正确的层级顺序管理。platformer/entities/player.ts读取废弃字段response.overlapV见 player.tsenemies.ts中也有同类用法见 enemies.ts。应改用response.depth/response.normal。粒子速度在 20.2 之前调好的粒子速度如今看起来不对——粒子变换修复改变了单次爆发的飞行距离发射器参数已被上调以匹配新行为。若你的粒子轨迹变短了请重新调整速度/能量参数而不是怀疑代码出错。排查清单代码应该能跑却不工作时按顺序核对以下五项能覆盖绝大多数 20.x 迁移失败场景有没有await app.init()缺失时没有任何报错只是什么都不渲染。代码是否假设一定在 WebGL 上运行实际可能是 Canvas 或 WebGPU。是否在用renderable.shader 而不是addPostEffect()是否导入了上表中的某个废弃符号尤其注意大写的Math与Entity。是否在引用全局game模块作用域读取它必得undefined请改用Stage回调参数或parentApp。延伸阅读本仓库的skills目录随包发布、随引擎版本维护提供了与本文配套的深度指南可继续深入melonjs-getting-started——20.x 正确的完整启动引导melonjs-renderables——后处理特效、指针事件与自定义绘制代码。同时可对照 CHANGELOG.md 中 20.0.0 / 20.2.0 / 20.3.0 的 breaking changes 原文以及 deprecated.js 中每个废弃符号的精确废弃版本与替代指引作为迁移时的权威依据。赞分享游戏开发图形学【免费下载链接】melonJSa modern lightweight HTML5 game engine项目地址https://gitcode.com/gh_mirrors/me/melonJS点击查看免费下载相关推荐Swagger-Client 从 2.x 升级到 3.x 迁移指南Swagger Client 从 2.x 升级到 3.x 迁移指南 前言 Swagger Client 作为处理 OpenAPI/Swagger 规范的核心工具后端终极Bacon.js迁移指南从2.x到3.x版本升级完全手册终极Bacon.js迁移指南从2.x到3.x版本升级完全手册 Bacon.js是一款功能强大的函数式响应式编程库专为TypeScript和JavaScrip前端Coupons项目H5与小程序双端开发跨平台技术深度解析Coupons项目H5与小程序双端开发跨平台技术深度解析 GitHub加速计划下的Coupons项目是一个专注于外卖红包优惠券的跨平台应用支持H5与小程序双小程序电商前端上一篇4步完成SillyTavern AI对话前端系统化迁移风险管理与技术实施指南下一篇思源宋体技术架构深度解析7种字重×5种语言变体的企业级解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表