从小我就对电子游戏非常着迷。从 Atari 和 Colecovision 到 NES 和 Super NES,我花费了无数个小时玩各种各样的游戏。虽然我自己的电子游戏玩的时间减少了,但我仍然对游戏领域的问题和进步感兴趣。我见证了网络游戏的近来爆火,并且坚信这将开启一个新的游戏时代,为广大受众提供海量的游戏。然而,在探索蓬勃发展的网络游戏场景时,我注意到了一件事——许多游戏如果能用游戏手柄玩会更有趣!我着手通过为 Firefox 实现一些功能来解决这个问题,于是游戏手柄 API 诞生了。
启用 API
从 Firefox 24 开始,游戏手柄 API 在一个首选项后面可用。您可以通过加载 about:config
并将 dom.gamepad.enabled
首选项设置为 true 来启用它。Firefox 的 Nightly 和 Aurora 版本默认启用了该 API。我们预计将在 Firefox 28 中以类似的方式启用发布版本。
使用 API
游戏手柄 API 的设计非常简单。规范有意地只尝试描述一个用于处理传统游戏手柄的接口——一组按钮和轴。我们认为这涵盖了大多数现有的游戏控制器,同时避免了尝试指定一个涵盖所有内容的 API 的复杂性。该 API 包含一个函数调用、一些 DOM 事件和一个要使用的对象类型。
获取游戏手柄
在实现中,除非用户在页面可见时与游戏手柄交互,否则游戏手柄不会公开给网页。这是出于隐私原因,主要是为了防止它们被用于指纹识别用户的系统。如果用户在页面可见时与(按下按钮、移动摇杆)控制器交互,则 <a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#the-gamepadconnected-event">gamepadconnected</a>
事件将被发送到页面。
<a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#gamepadevent-interface">GamepadEvent</a>
对象有一个 <a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#widl-GamepadEvent-gamepad">gamepad</a>
属性,该属性描述了相关设备。在 Firefox 中,一旦一个游戏手柄已公开给页面,将任何其他游戏手柄连接到系统(通过插入 USB 游戏手柄或关联蓝牙游戏手柄)将立即将该设备公开给页面并发送 gamepadconnected
事件。
游戏手柄 API 还提供了一个函数——<a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#methods">navigator.getGamepads()</a>
——它返回当前对网页可见的所有设备的列表。每个对页面可见的游戏手柄都以其 index
属性指定的列表中的位置返回。
注意:此代码片段将在 Firefox 28 nightly 版本中有效,但在较旧的版本中无效,因为最近修复的一个错误。
如果游戏手柄断开连接——例如,拔掉插头——则 <a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#the-gamepaddisconnected-event">gamepaddisconnected</a>
事件将触发到页面。对 Gamepad
对象的所有剩余引用都将将其 connected
属性设置为 false
。
Gamepad 对象
Gamepad 对象
表示游戏控制器的状态。它有一些属性来描述控制器
- id
- 包含有关控制器的某些信息的字符串。这不是严格指定的,但在 Firefox 中,它将包含由连字符 (
-
) 分隔的三部分信息:两个 4 位十六进制字符串,包含控制器的 USB 供应商和产品 ID,以及驱动程序提供的控制器名称。此信息旨在允许您查找设备上控件的映射,以及向用户显示有用的反馈。 - index
- 一个整数,对于当前连接到系统的每个设备都是唯一的。这可以用来区分多个控制器。
- connected
- 布尔值:如果控制器仍然连接,则为
true
;如果控制器已断开连接,则为false
。 - mapping
- 一个字符串,指示浏览器是否已将设备上的控件重新映射到已知的布局。目前只支持一种已知的布局——“标准游戏手柄”。如果浏览器能够将设备上的控件映射到该布局,则
mapping
属性将设置为字符串standard
。 - axes
- 一个浮点值数组,包含设备上每个轴的状态。通常这些表示模拟摇杆,其中一对轴给出摇杆在其 X 和 Y 轴上的位置。每个轴都归一化为 -1.0..1.0 的范围,其中 -1.0 表示轴的最上或最左位置,1.0 表示轴的最下或最右位置。
- buttons
- 一个
GamepadButton 对象
数组,包含设备上每个按钮的状态。每个GamepadButton
都有一个<a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#widl-GamepadButton-pressed">pressed</a>
和一个<a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#widl-GamepadButton-value">value</a>
属性。pressed
属性是一个布尔值,指示按钮当前是否按下 (true
) 或未按下 (false
)。value
属性是一个浮点值,用于启用表示模拟按钮,例如许多现代游戏手柄上的触发器。这些值归一化为 0.0..1.0 的范围,其中 0.0 表示未按下的按钮,1.0 表示完全按下的按钮。
跨浏览器兼容性
游戏手柄 API 规范
在 Firefox 和 Chrome 中都实现了,但兼容性程度不同。目前,Firefox 实现了 编辑器草案
的全部内容,除了 Gamepad
对象上的 <a href="https://dvcs.w3.org/hg/gamepad/raw-file/default/gamepad.html#widl-Gamepad-timestamp">timestamp</a>
属性。
在撰写本文时,Chrome 尚未实现 ongamepadconnected
或 ongamepaddisconnected
事件。您必须使用 navigator.webkitGetGamepads()
函数(注意前缀)来访问游戏手柄。
另一个需要注意的区别是,在 Chrome 中,Gamepad
对象是快照,而在 Firefox 中,它们始终反映控制器的最新状态。这意味着对于 Chrome,您需要在每一帧中使用 navigator.webkitGetGamepads()
轮询游戏手柄集,而在 Firefox 中,您可以将对 Gamepad
对象的引用保存在变量中,并在以后引用它以检查当前状态。
最后,最近的规范更改意味着 Chrome 和 Firefox 的发布版本与 Firefox 28 有所不同——Gamepad
对象的 buttons
属性最初被指定为双精度数数组,而不是 GamepadButton
对象数组。这可以通过简单的类型检查安全地处理,如下面的代码示例所示。
一个简单的演示
我将为您提供一个简单的演示,它将这里的所有部分组合在一起,并展示了您如何在当今以跨浏览器的方式使用 API。它只是查找连接或断开连接的游戏手柄,并显示所有已知控制器的按钮和轴的当前状态。此演示应该在 Firefox 24 及更高版本以及 Chrome 21 及更高版本中运行。您可以在Github 上找到演示的源代码。
我希望这篇博文能激励您重新思考在网络游戏领域可能实现的目标。让我们一起制作一些游戏吧!
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直从事 Web 前端开发工作——在瑞典和纽约市。他还定期在http://robertnyman.com 上发表博文,并且喜欢旅行和结识新朋友。
17 条评论