Introducing PROXX

一款受扫雷启发的邻近游戏。

Mariko Kosaka

为您带来 squoosh.app 的团队又回来了!这次,我们构建了一款名为 PROXX (proxx.app) 的基于 web 的游戏。PROXX 是一款受传奇游戏扫雷启发的邻近游戏。游戏背景设定在太空,您的工作是找出黑洞的位置。它适用于各种设备,从桌面设备到功能手机。用户可以使用鼠标、键盘、方向键,甚至屏幕阅读器来玩这款游戏。

功能手机上的 PROXX。

我们的基准

在构建这款游戏之前,我们为应用程序设定了以下目标和预算

  • 相同的核心体验:所有设备的功能必须相同
  • 无障碍:鼠标、键盘、触摸、方向键、屏幕阅读器
  • 高性能:
    • 初始有效负载小于 25kb
    • 在慢速 3G 网络上,TTI(可交互时间)小于 5 秒
    • 一致的 60fps 动画
A pixelbook running PROXX
Pixelbook 上的 PROXX。

Web Workers

该游戏由 4 个主要实体组成:核心游戏逻辑、UI 服务、状态服务和动画图形。由于我们从一开始就知道我们必须在主线程上运行大量动画图形,因此我们将游戏逻辑和状态服务移至 Web Worker,以尽可能保持主线程空闲。

构建时预渲染

我们的 UI 是使用 Preact 构建的,因为它使我们能够实现初始有效负载小于 25kb 的积极目标。为了提供良好的初始加载体验,我们决定预渲染我们的第一个视图。我们在构建时使用 Puppeteer 访问顶层页面,并让 Preact 填充 DOM。然后将生成的 DOM 序列化为 HTML 并另存为 index.html

用于动画的 Canvas,用于无障碍功能的(不可见)DOM

我们使用 WebGL 在 canvas 中渲染游戏图形。一个 canvas 负责背景动画,另一个 canvas 负责顶部的游戏网格。我们还有一个 HTML 表格,其中包含用于无障碍功能的按钮,该表格位于这两个 canvas 的顶部,但设置为不可见(opacity: 0)。即使您看到的是游戏状态的 canvas 渲染,玩家也在与不可见的 DOM 表格交互,这使我们能够附加事件侦听器并依赖浏览器的焦点管理。

通过将 DOM 元素保留在 canvas 中,我们能够利用浏览器内置的无障碍功能。例如:通过在我们的游戏表格上设置 role="grid",屏幕阅读器可以播报焦点单元格的行和列,而无需我们实现该功能。

用于捆绑和代码拆分的 Rollup

该应用程序的总大小压缩后为 100KB。其中,20KB 用于初始有效负载 (index.html)。我们在此项目中使用 Rollup.js。我们在主线程和 Web Worker 之间共享依赖项,Rollup 可以将这些共享依赖项放在一个单独的块中,该块只需加载一次。其他捆绑器(如 webpack)会复制共享依赖项,从而导致重复加载。

支持功能手机

智能功能手机(如 KaiOS 手机)正迅速普及。这些设备的资源非常受限,但我们尽可能使用 Web Worker 的方法使我们在这些手机上的体验也具有高度响应性。由于功能手机配备不同的输入界面(方向键和数字键,没有触摸屏),我们还实现了基于按键的界面。

A man playing PROXX on a yellow feature phone
功能手机上的 PROXX。

下一步

为了赶上 2019 年 Google I/O 大会,我们非常忙碌地构建了这款游戏,因此我们将抽出一些当之无愧的时间休息一下,但计划回来就游戏的每个领域提供更深入的文档。

在那之前,请观看 Mariko 在 I/O 大会上就此项目所做的演讲。

您可以在 proxx GitHub 存储库 中浏览代码。

干杯!Surma、Jake、Mariko