ARTICLE DETAIL

资讯详情

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

Superpowers实操:浏览器+TypeScript的开源协作式游戏开发

Superpowers实操:浏览器+TypeScript的开源协作式游戏开发 Superpowers 这名字我第一次见还以为是什么个人成长类的付费课程。查了一圈才发现它其实是一套开源的协作式实时开发环境专门用来做游戏和互动网页应用而且整个编辑器都跑在浏览器里。更直接一点说你不需要在自己电脑上装什么庞大的引擎客户端只要有浏览器打开一个地址就能开始搭场景、写脚本、做交互。最让我觉得有意思的是它默认支持多人同时编辑同一个项目就像团队一起开一个共享的文档来做游戏。如果你正在找轻量级的游戏开发方案或者想用 TypeScript 练手又不想碰复杂的工程化配置那这篇文章里的安装记录和实操笔记应该能帮你少走不少弯路。1. 先搞清楚 Superpowers 到底是什么它不是一个游戏引擎至少不是我们熟悉的 Unity、Godot、Cocos 那种需要下载几十 GB 编辑器的软件。Superpowers 把自己定义成“协作式实时开发环境”核心玩法是一台电脑作为 Host 运行服务所有人用浏览器访问同一个地址然后在这个 Web 页面里共同创建和编辑项目。项目里的所有资产包括图片、声音、3D 模型、脚本代码都存放在 Host 机器的项目目录中。编辑器本身是网页应用游戏运行时的渲染和逻辑也基于 Web 技术。这样做的好处非常明显团队成员不用为了某个依赖是否安装、某个版本是否匹配而纠缠只要网络能连上服务打开浏览器就能进项目。我实际用下来的感受是它特别适合三种场景。第一种是教学生做游戏老师只需要在一台机器上启动 Host学生各自用浏览器打开地址即可不需要每个人都配一套开发环境。第二种是小团队远程做 Game Jam大家分散在不同城市却可以同时画地图、调参数、写脚本实时看到彼此的改动。第三种是快速原型验证比如我想测一个小玩法是否有趣不需要先建完整的 Unity 工程直接在 Superpowers 里拖几个实体、写几行脚本就能跑起来看效果。还有一个很实际的卖点是Superpowers 的脚本语言直接使用 TypeScript。这意味着你在写游戏逻辑的同时其实也在练 TypeScript 的语法、类型系统、模块化思想。对于 Web 开发者转游戏开发或者游戏开发者想接触前端技术的人来说这个学习曲线是被平滑掉的。它不是“又一个要学的语言”而是“你已经会的东西换了个跑法”。当然它也有自己的短板。这些年它的社区活跃度不算高插件和教程都比较有限和主流商业引擎的生态完全不能比。但如果你只是想低成本地做点小项目或者想体验“多人共建实时编辑”这种开发模式它绝对值得一试。真正动手之前我建议先读一下官网的文档至少把项目定位和基本术语过一遍后面安装和使用时会顺畅得多。2. 安装与运行全流程实操记录2.1 装之前需要准备什么Superpowers 的运行环境要求非常简单核心就三样东西Node.js、一个现代浏览器、稳定的本地网络。Node.js 是必须的因为 Host 服务本身就是跑在 Node 上的。版本方面官方文档推荐使用 LTS 版本这一点我特别想强调我踩过坑刚开始我装了当时最新的 Node 大版本结果 npm 安装依赖时频繁报错后来换成 LTS 版本才稳定下来。如果你不想折腾直接装官网标注的 LTS 版本不要追新。浏览器建议用 Chromium 系的一线浏览器Chrome 或者 Edge 都可以。因为编辑器界面和游戏渲染大量依赖现代 Web 特性Firefox 我试过也能跑但个别面板的显示效果不如 Chrome 系那么自然。就别考虑老旧的浏览器了Web 实时协作需要的 WebSocket、WebGL 等特性在旧版本上支持得很糟糕。网络方面如果是单机使用什么都不用配置。如果要让其他同事或同学一起编辑那台 Host 机器的网络需要允许局域网访问防火墙记得放行对应端口。我习惯先用单机模式把流程跑通再开局域网协作这样出了问题容易排查。2.2 全局安装还是用 npx安装方式有两种我建议直接全局安装npm install -g superpowers全局安装的好处是后续启动服务、管理插件都方便命令直接可用。如果不想往全局环境里装东西也可以试试npx superpowers免安装直接跑但每次调用都要经过 npx 的解析多多少少会慢一点而且后续升级插件的时候还是要落到本地目录里去操作。安装过程其实很短npm 会拉取一堆依赖耐心等一等就行。国内网络环境下如果下载超时可以把 npm 源切到国内镜像这个就不展开说了属于 Node 生态的基础操作。安装完成后直接在命令行输入superpowers正常情况下终端会输出服务启动信息并显示一个访问地址一般是http://localhost:4237。看到这个地址说明 Host 进程已经起来了。保持这个终端窗口开着然后打开浏览器访问那个地址。2.3 首次启动要做的配置第一次打开管理界面时系统会让你设置项目存储目录和管理员账号。项目存储目录就是后续所有游戏项目文件存放的地方。我建议专门建一个干净的空目录比如SuperpowersProjects不要随手放在桌面或者下载文件夹里否则后面项目多了会乱。管理员账号要记好但不用太紧张它不是登录平台那种强绑定只是用来管理 Host 服务、创建项目和分配权限的。设置完成后你会看到一个类似控制台的界面可以从这里创建新项目。有一个细节容易被忽略如果你打算让局域网里的其他人一起开发需要先在管理界面里把 Host 模式配置成允许外部连接。默认的配置可能只允许本机访问这个选项不在显眼的位置我第一次找了好一会儿。简单说就是找到服务设置或者网络设置相关的菜单把监听地址从回环地址改成全网卡地址然后给局域网客户端设置一个访问密钥。这个密钥一定要告诉协作者不然他们即使知道地址也进不来。2.4 项目文件到底放在哪这里特别值得提前搞清楚。你在浏览器里做的所有东西——地图、图片、脚本、场景配置——最终都会以文件夹的形式保存在 Host 机器上那个项目存储目录里。这个设计意味着备份项目就是直接拷贝目录不需要任何导出操作。我也会定期把整个目录打包存到网盘或者 NAS比依赖平台自身的快照功能更踏实。如果是团队协作最好约定好由 Host 机器负责人来定期备份否则一旦 Host 机器的磁盘坏了项目就真的没了。3. 核心概念一切都是一张地图3.1 为什么用“地图”来组织项目我第一次打开 Superpowers 的时候习惯性地找“场景”或者“关卡”的概念结果先看到的是 Maps也就是地图。其实这只是命名习惯的问题Superpowers 把空间结构当成项目的骨架一个项目由多张地图组成每张地图就是一个独立的 3D 空间或者 2D 平面场景。这样做的好处是拆解起来非常直观。比如做一个小游戏主菜单可以是一张地图关卡一是一张地图设置界面又是一张地图。你可以任意切换当前运行的地图来改变游戏状态。这种组织方式的另一个好处是不同地图之间的资源可以共享但具体的摆放和逻辑互不干扰多人协作时不容易出现两个人同时改一张图导致崩溃的情况。地图本身可以设置大小、背景颜色、雾效、重力等基础参数。如果你做的是 2D 游戏可以把地图模式设为 2D并设定像素尺寸如果是 3D 游戏就按三维空间来配置。这里我推荐一个做法动手做内容之前先把地图的尺寸和单位想清楚。不要小看这一步后面摆放实体、调整碰撞效果、设置相机全部要依赖这套坐标尺。3.2 实体与组件把能力装进对象Superpowers 里的场景对象叫 Entity翻译成中文一般是“实体”。一个实体本身没有任何表现能力它只是一个有位置、旋转、缩放信息的空壳。真正让实体看起来像一棵树、一堵墙、一个会移动的小人全靠挂在上面的组件。这种架构和 Unity 很像我甚至觉得它就是受了 Unity 的启发。每个组件负责一个维度的能力显示模型、渲染图片、播放声音、执行脚本、接收键盘输入、模拟物理碰撞。你往一个实体上挂几个组件它才具备对应的功能。比如我做一个小球需要先创建一个空实体然后给它添加一个球体模型组件让它有形状再添加一个材质组件调整颜色最后挂一个脚本组件让它在每帧更新时向前滚动。整个过程就像拼积木不同组件相互叠加能力越来越完整。理解“实体 组件”这个模式基本就理解了一半的 Superpowers 用法。不需要把所有代码都写在一个巨大脚本里把每一块能力拆成独立的组件挂在对应的实体上逻辑就清晰了。尤其是多人协作的时候每个人负责一个实体的组件逻辑代码冲突的概率会大大降低。3.3 脚本组件与 TypeScript 编写体验脚本组件是 Superpowers 里最有技术含量的部分。新建一个脚本资产后你可以用内置的代码编辑器打开它这时懂 TypeScript 的人会感到很舒心有类型提示有自动补全和现代前端开发体验很接近。一个脚本组件的基础结构长这样我摘一段我自己项目里的示意代码class Rotator extends Sup.Behavior { private angle 0; update(dt: number) { this.angle dt * 60; this.actor.setEulerAngles(0, 0, this.angle); } }这段代码的意思是让当前实体绕 Z 轴持续旋转。Sup.Behavior是脚本组件的基类update(dt)是每一帧都会执行的方法dt是距离上一帧过去的时间单位是秒。把速度乘以dt是为了避免不同刷新率屏幕导致旋转速度不一致。this.actor指向脚本组件所在的实体也就是说脚本可以反过来控制和它绑定的实体。这是组件化开发里很重要的一环通过脚本来驱动实体运动、响应输入、触发事件。我第一次写的时候犯过一个低级错误直接把角度增量写死在update里没有乘dt。在 60Hz 屏幕上看着还行换到 120Hz 的屏幕物体转得明显快一倍。后来老老实实按帧间隔来算问题就消失了。这类坑几乎每个用实时渲染环境的人都会碰到所以我把这个细节放在这里提醒一下。4. 实操一个互动小场景旋转方块加键盘移动4.1 创建项目和第一步搭场景启动服务并登录管理界面之后创建一个新的空白项目记住项目名和存储位置。创建好项目你会看到编辑器的初始界面里面左侧是资产列表中间是地图视图右侧是属性面板。我先建议你在资产面板里新建一张地图然后把地图属性设置为 3D 模式。接着在菜单里添加一个基础立方体实体把它放在世界原点附近。此时场景里应该出现一个灰白色的方块但它是静态的没有任何行为。我们需要给它两样东西一个可以运动的脚本和一个能接收输入的触发机制。为了让场景更丰富我再添加一个定向光和一个相机。相机的位置调到稍微高处俯视方块这样运行游戏后你就能从正面看到方块的运动状态。不要小看相机的设置我第一次做的时候忘记调相机角度运行后盯着屏幕看了半天才意识到镜头正对着地面什么也看不见。4.2 写一个键盘控制脚本接下来是关键部分。创建一个新的 TypeScript 脚本起名叫PlayerController然后把它挂到方块实体上。这个脚本实现的功能很简单用方向键控制方块在水平面上前后左右移动用 A/D 键让方块旋转。代码示意大致是这样class PlayerController extends Sup.Behavior { private speed: number 4; update(dt: number) { let horizontal 0; let vertical 0; if (Sup.Keyboard.isKeyDown(Left)) { horizontal - 1; } if (Sup.Keyboard.isKeyDown(Right)) { horizontal 1; } if (Sup.Keyboard.isKeyDown(Up)) { vertical 1; } if (Sup.Keyboard.isKeyDown(Down)) { vertical - 1; } this.actor.move(horizontal * this.speed * dt, 0, vertical * this.speed * dt); } }Sup.Keyboard.isKeyDown是 Superpowers 提供的键盘查询接口参数可以直接写成 Left、Right 这样的语义化名称。move方法让实体沿 X 和 Z 轴平移传入的是距离所以我们把方向值、移动速度和帧间隔乘在一起。保存脚本后回到编辑器点击运行按钮用方向键应该就能推动方块了。这里面最值得说的是dt的作用。很多新手会把移动速度直接写成每帧移动固定距离结果游戏在不同机器上速度完全不一样。正确做法一定是乘上帧间隔让运动距离和时间挂钩而不是和帧率挂钩。这是做实时交互的基本功养成习惯以后写任何引擎都适用。4.3 把行为拆成独立组件的好处做到这里你可能会想如果要做一个会同时移动和旋转的物体是不是要把所有逻辑都写进一个脚本不是的更合理的做法是拆成两个组件一个Rotator负责自转一个PlayerController负责移动两个都挂到同一个实体上。它们互相独立各干各的互不干扰。麻烦的是如果之后想复用某段能力直接把这个组件挂到新实体上就行了。这种拆分的做法在多人协作时好处更加明显。两个人可以同时改同一个实体上的不同组件不需要排队等一个人改完再让另一个人改。只要组件之间没有强依赖代码冲突的概率就很低。4.4 常用属性参数速查我给刚开始接触的朋友整理了一个小表格方便快速理解最常用的几个组件参数参数作用备注Position实体在场景中的位置修改后影响所有子实体Rotation实体的旋转欧拉角用度数表示Scale实体的缩放比例设为负数可能导致渲染异常Camera FOV相机视野角度数值越大看到的范围越广Script Actor脚本绑定的实体引用在脚本里用 this.actor 访问Behavior Enabled是否启用该行为组件关闭后 update 不再执行这些参数看几遍不如动手设置一遍。我建议你新建一个实体每个参数都改一改观察场景里的变化比看十篇教程都有效。5. 多人协作是怎么实现的5.1 Host 和 Client 的明确分工Superpowers 的协作机制可以简单理解为一台机器跑 Host 服务其他机器通过浏览器连接成为客户端。Host 负责保存项目文件、广播变更、处理权限客户端通过 WebSocket 与 Host 实时通信。我用了一个类比来帮助朋友理解这件事Host 就像共享文档的所有者别人通过链接打开文档后大家写的字会同步到所有屏幕但文档真正存在谁的电脑里谁就有最终保存权。在 Superpowers 里Host 机器的权限天然最大客户端如果失去连接还能不能编辑、怎么处理冲突都由 Host 端配置决定。实际操作时Host 机器不需要额外安装任何客户端软件它本身就是 Node 服务在跑。唯一要注意的是Host 机器最好用有线网络连接WiFi 下长时间多人编辑偶尔会有延迟抖动毕竟所有变更都要经过它。5.2 同时编辑同一张图的真实体验我自己试过和另一位朋友一起编辑同一个项目。我们同时拖拽同一个实体一个改位置一个改缩放界面上能看到两边操作都在实时生效这个过程很神奇就像两个人分别握着同一个木偶的左右手。如果两个人同时修改同一个属性后提交的一方会覆盖先提交的结果这个和共享文档的冲突处理逻辑非常接近不是禁止你改而是以最后操作为准。这种模式最让我喜欢的一点是沟通成本极低。以前远程协作做游戏要不停截图发群、开会说明自己改了哪块。在 Superpowers 里我直接看着对方的操作就能理解他的意图。某个人往场景里多加了一面墙其他人立刻就能看到。这种即时性带来的协作体验是传统开发流程很难给的。5.3 适合哪些协作场景我最推荐的是远程教学和结对编程。老师或组长作为 Host新手们作为客户端边讲解边改代码学生能实时看到老师的每一步操作。反过来学生操作时老师也能在一旁观察及时指出问题。比屏幕共享更自然因为双方都能动手而不是一个人操作另一个人干看。推广到远程 Game Jam 也特别好用。一个团队三五个人不需要每个人都搭环境只要一个人开好 Host其余人打开链接就能开工。美术可以一边传素材一边摆位置程序可以一边写脚本一边调参数策划可以在旁边直接改实体属性做平衡性测试整个节奏快很多。也可以当作个人多设备开发的工具上班的电脑跑 Host回家用自己的笔记本开浏览器继续干项目文件还在公司那台机器上远程网络连过去就能继续。不过这种情况对网络稳定性和延迟要求比较高如果两张网络之间跳数太多实时编辑反而会卡建议只做查看和简单操作密集操作还是在 Host 本机上方方便。6. 导出与部署做完的项目怎么带走6.1 导出 HTML5 产物当你把一个项目做到可以玩的阶段下一步就是产出一个能给别人打开的东西。Superpowers 支持直接把项目构建成 HTML5 应用导出的产物就是一份静态网页目录。找到项目设置或构建菜单选择目标平台然后执行构建系统会在指定目录生成一堆文件其中有一个index.html是入口。这件事对做小游戏的体验改善很大。以前用其他引擎导出还要自己配一堆构建工具Superpowers 把这一步做得很轻。导出的文件里图片、音频、脚本逻辑、引擎运行时都被打包到一起理论上扔到任何一个静态目录都能跑。6.2 部署到静态服务器导出的目录不需要任何后端服务直接扔给静态服务器托管就行。我常用两种方式本地开发测试时在导出目录跑一个简单的静态文件服务比如npx serve然后浏览器访问终端提示的地址就能玩上项目了。正式分享给其他人时可以部署到云服务器的 Nginx 或者对象存储静态站点上。只要支持静态文件访问基本都能用。有一点要注意导出的项目如果包含了比较多的音频素材首屏加载会慢有条件的话尽量做一下素材体积控制。6.3 定期备份才是最重要的“存档”前面提过项目文件保存在 Host 机器的存储目录里。我真见过有人辛苦做了两星期的项目因为 Host 机器重装系统全部丢了。这里必须强调备份每天工作结束后把项目目录打包一份放到网盘、NAS、Git 仓库都可以。如果你会用 Git把项目目录扔进 Git 仓库是可行的。但要注意如果多人同时通过 Host 编辑直接拿项目目录做 Git 操作可能会和实时同步机制打架。最安全的做法是先暂时停止 Host 服务再做 Git 提交和推送重新启动后再继续工作。毕竟实时编辑时内存里还有没写盘的变更。7. 我踩过的坑和排查速查7.1 端口占用导致服务起不来默认端口 4237 是一个不太常见的端口但还是可能被其他进程占用。启动后如果浏览器访问不了先看终端有没有报端口错误。在命令行执行netstat -ano | findstr 4237找到占用进程后要么关掉它要么在配置里换成其他可用端口。我遇到过某次开发工具悄悄占用了这个端口排查了十分钟才反应过来。7.2 Node 版本导致安装或依赖异常前面已经说过Node 版本太新有时候会有兼容问题。如果你在安装依赖或者启动服务时报错先看看是不是 Node 版本的问题。建议直接切换到 LTS 版本。如果你装了 nvm版本切换是很快的nvm install --lts nvm use --lts切换后重新安装依赖大部分莫名其妙的报错都能解决。这个坑属于典型的“不是你不会用而是环境版本太超前”。7.3 多人连接不上 Host局域网协作时客户端经常遇到连不上或者连接后闪退的情况。排查顺序是这样的先确认客户端和 Host 在同一个局域网然后检查 Host 的监听地址是否已经从回环地址改成了全网卡地址最后看防火墙是否放行了 4237 端口。如果客户端能连上但画面卡顿优先检查是不是 WiFi 不稳定实在不行就换网线。7.4 保存后脚本不生效脚本写好了也保存了但运行时没有反应。这种问题多半是脚本没有挂到任何实体上或者挂在实体上但组件没有启用。打开实体的组件列表确认脚本组件存在且处于启用状态。另一个常见原因脚本类名写错了或者没有继承Sup.Behavior。检查一下类名是否和脚本文件名一致有时候复制代码片段时会丢失这些看似不重要的细节。7.5 资产文件不同步多人协作时偶尔会出现某人上传了新图片其他人资产面板里看不到的情况。这种问题多数是连接不稳定导致同步消息丢失。最简单的做法是让出问题的那个人刷新浏览器页面重新连接一次一般就能恢复。如果还不行就让 Host 端重启一下服务再让所有人重新进入项目。我还整理了一个快速排查表方便实际操作时对着看现象可能原因处理方法服务启动失败端口被占用找占用进程关掉或换端口npm 安装报错Node 版本不兼容切换 LTS 版本局域网无法连接监听地址/防火墙改为全网卡地址并放行端口脚本运行无效果脚本未挂载或未启用检查实体组件列表多人不同步网络波动或消息丢失刷新页面或重启 Host8. 最后分享一点个人判断Superpowers 不是一款力图取代 Unity 或 Godot 的引擎它的独特之处在于把人、浏览器、实时协作这三样东西组合到了一起。如果你玩过的引擎已经很多再回头用它可能会觉得功能不够厚重但我仍然认为它有存在的价值它把“做游戏”这个过程拉回到了最简单直观的交互方式里。我在实际使用中最大的感触是它能不能发挥出效果不取决于功能列表有多长而取决于你是否愿意接受“浏览器即编辑器”这种轻量开发模式。把它当成快速原型工具、当成 TypeScript 教学环境、当成团队共创的沙盒你都会觉得它很顺滑。如果一开始就用它和完整商业引擎比资源数量、比插件生态那大概率会失望。最后再分享一个小技巧导出项目以后如果你只是想在手机上有事没事测试一下手感可以给静态服务器加上局域网访问然后手机用浏览器打开那个地址。它支持桌面端和移动端交互省去了一次次扫码打包安装的功夫这个体验在快速迭代时特别舒服。
返回列表