用PeerJS驯服WebRTC:制作一个简单的P2P网络游戏

本文概述

WebRTC是一种启用Web浏览器之间实时通信的技术。它相对较新, 并且API定义仍被视为草稿。再加上所有主要的网络浏览器尚未支持WebRTC(并且其中一些浏览器不支持该技术的所有功能), 这使得将WebRTC用于任何关键任务应用程序相对比较困难。 。否则, 你会认为!

使用PeerJS在WebRTC上连接四人:看,没有服务器!

使用PeerJS在WebRTC上连接四人:看, 没有服务器!

鸣叫

自Google于2011年5月首次推出以来, WebRTC已在许多现代Web应用程序中使用。作为许多现代Web浏览器的核心功能, Web应用程序可以无缝地利用此技术, 以多种方式提供改善的用户体验。视频流或会议应用程序不需要庞大的浏览器插件, 并且可以利用对等(P2P)网络(而不会通过服务器传输所有数据)只是所有令人惊奇的事情的一部分可以使用WebRTC实现。

在本文中, 我们将研究如何使用WebRTC制作一个简单的Connect Four P2P网络游戏。为了解决WebRTC的各种粗糙之处和实现差异, 我们将使用一个令人惊叹的JavaScript库:PeerJS。

WebRTC上的数据

在开始之前, 重要的是要了解WebRTC不仅涉及传输音频和视频流。它还提供对P2P数据通道的支持。这些渠道有两种变化:可靠和不可靠。就像人们可能猜到的那样, 可靠的数据通道可确保传递消息并按顺序传递消息, 而不可靠的通道则不提供此类保证。

WebRTC基础结构-缩略语的海洋

WebRTC基础结构-缩略语的海洋

鸣叫

此外, 除了典型的WebRTC对等连接所需要的之外, WebRTC数据通道不需要特殊的基础结构设置:用于协调对等体之间连接的信令服务器, 用于确定对等体公共身份的STUN服务器以及可选的TURN服务器如果无法在对等体之间建立直接连接(例如, 当两个对等体都位于NAT之后), 则在对等体之间路由消息。如果这些首字母缩写听起来很熟悉, 那是因为WebRTC尽可能地重新利用了现有技术。

这为WebRTC的更多使用案例打开了大门, 包括但不限于多人游戏, 内容交付和文件共享。同样, 所有这些都不需要任何中间服务器, 因此延迟更短。

在我们简单的网络游戏中, 我们将使用两个网络浏览器之间的数据通道来交流玩家的来回移动。

认识PeerJS

PeerJS在你的浏览器中实现WebRTC的实现, 并在其周围包装了一个简单, 一致且优雅的API。它填补了早期浏览器的WebRTC实施中的各种漏洞。例如, 在Chrome 30或更旧的版本中, 只有不可靠的数据通道可用。如果将PeerJS配置为使用可靠的数据通道, 则将对那些较旧的浏览器使用填充程序。尽管这不像可靠渠道的本机实施那样出色, 但仍然可以使用。

使用PeerJS, 识别对等节点甚至更加简单。仅使用ID来标识每个对等方。对等方可以自行选择或由服务器生成的字符串。尽管WebRTC承诺了对等通信, 但无论如何你仍然需要服务器充当连接代理并处理信令。如果你不想使用它们的云托管版本(目前是免费的, 并且有一些限制), PeerJS提供了此连接代理服务器PeerJS Server(用Node.js编写)的开源实现。

连接四通P2P

现在我们有了使用WebRTC的信心, 即PeerJS, 让我们从创建一个简单的Node.js / Express应用程序开始。

npm init
npm install express --save
npm install jade --save
npm install peer --save

我们将仅使用它来托管PeerJS Server, 并提供页面和前端资产。我们只需要提供一个页面, 该页面将包含两个部分:一个简单的主菜单和一个7×6的”连接四个”网格。

PeerJS服务器

托管我们自己的PeerJS Server非常容易。 GitHub上的官方存储库甚至具有一键式按钮, 可将PeerJS Server实例部署到Heroku。

在我们的例子中, 我们只想在Node.js应用程序中创建ExpressPeerServer的实例, 并将其提供给” / peerjs”:

var express = require('express')
var app = express()
// … Configure Express, and register necessary route handlers
srv = app.listen(process.env.PORT)
app.use('/peerjs', require('peer').ExpressPeerServer(srv, {
	debug: true
}))

PeerJS客户端

随着PeerJS Server的启动和运行, 我们进入了客户端。如前所述, PeerJS标识具有唯一ID的对等体。这些ID可以由PeerServer为每个对等体自动生成, 或者我们可以在实例化Peer对象时为每个对等体选择一个ID。

var peer = new Peer(id, options)

在这里, 如果我们希望服务器为我们生成一个ID, 则可以完全省略id。就我们而言, 这就是我们要做的。 PeerServer将确保其给出的ID是唯一的。第二个参数, options, 通常是一个包含密钥的对象(API密钥, 如果你使用的是云托管的PeerServer, 或者如果你自己托管PeerServer, 则为主机, 端口, 路径等)。

var peer = new Peer({
	host: location.hostname, port: location.port || (location.protocol === 'https:' ? 443 : 80), path: '/peerjs'
})

为了在两个PeerJS对等体之间建立连接, 其中一个对等体必须知道另一个对等体的ID。为了简单起见, 在我们通过WebRTC实现四人连线时, 我们将要求开始游戏的玩家与对手分享其对等ID。有了目标对等方ID后, 我们只需要简单地调用peer.connect(destId):

var conn = peer.connect(destId)

peer.connect(destId)返回的Peer对象和DataConnection对象都发出一些非常有用的事件, 值得监听。在本教程中, 我们对DataConnection对象的”数据”事件和两个对象的”错误”事件特别感兴趣。

为了将数据发送到连接的另一端, 只需调用conn.send(data):

conn.send('hello')

尽管对我们这里的需求有些过分, 但PeerJS在对等体以BinaryPack格式编码后在对等体之间传输数据。这使同级可以交流字符串, 数字, 数组, 对象甚至blob。

要接收传入的数据, 只需在conn上监听” data”事件:

conn.on(‘data’, function(data) {
	// data === 'hello'
})

这几乎就是我们所需要的!

游戏逻辑

显示第一个开始游戏的玩家的对等ID(由PeerJS生成), 他们可以与对手共享。一旦对手使用第一个玩家的对等ID加入游戏, 则允许第一个玩家移动。

Connect Four是一种简单的规则和机制游戏, 只有一种移动方式:每个玩家都必须选择一列并将光盘放入其中。这意味着对等方需要通信的是当前播放器选择放入其光盘的列号。我们将以包含两个元素的数组的形式传输此信息:字符串” move”和数字-0-左列的索引。

玩家每次单击列时:

if(!turn) {
	// it is not the current player’s turn
	return
}

var i
// i = chosen column index
if(grid[i].length == 6) {
	// the column doesn’t have any more space available
	return
}

// track player’s move locally
grid[i].push(peerId)

// end current player’s turn
turn = false

conn.send(['move', i])

将移动数据发送给对手后, 我们会在本地更新游戏状态。这包括确定当前玩家是否赢了, 或者游戏是否以平局结束。

在此移动数据的接收端:

if(turn) {
	// ignore incoming move data when it is the current player's turn
	return
}

var i = data[1]
if(grid[i].length == 6) {
	// ignore incoming move data when it is invalid
	return
}

// track opponent’s move locally
grid[i].push(opponent.peerId)

// activate current player’s turn
turn = true

当然, 在此之后, 我们将在本地更新游戏状态, 确定对手是否获胜或游戏是否以平局结束。

注意我们需要如何对传入的数据执行完整性检查。这很重要, 因为在基于WebRTC的游戏中, 我们没有验证移动数据的中间服务器和基于服务器的游戏逻辑。

为了简化代码片段, 省略了更新UI的代码行。你可以在此处找到客户端JavaScript的完整源代码。

全部连接

为了将所有内容组合在一起, 我们创建了一个包含两个部分的简单页面。在页面加载时, 将显示包含主菜单的部分, 而包含游戏网格的部分将保持隐藏状态。

section#menu
	div.animated.bounceIn
		div
			h1 Connect Four
			br
			div.no-support(style='display: none;')
				div.alert.alert-warning
					p Unfortunately, your web browser does not <a href="http://iswebrtcreadyyet.com">support WebRTC</a>
			div
				a.btn.btn-primary.btn-lg(href='#start') Start
				| &nbsp;
				a.btn.btn-default.btn-lg(href='#join') Join

section#game(style='display: none;')
	div
		div
			h1 Connect Four
			br
			table.table.grid
				tbody
					for i in [0, 1, 2, 3, 4, 5]
						tr
							for j in [0, 1, 2, 3, 4, 5, 6]
								td
									div.slot
			br
			div.alert.alert-info
				p 

使这些DOM元素看起来更漂亮超出了本教程的范围。因此, 我们将求助于我们值得信赖的同伴Bootstrap并对其进行一些样式化。

当第一个玩家点击”开始”按钮时, 游戏网格以及玩家的对等ID就会显示出来。然后, 玩家可以与对手共享该对等ID。

开始一个新游戏,并分享你的PeerJS生成的对等ID

第二位玩家可以单击, 然后单击”加入”按钮, 输入第一位玩家的对等ID, 然后开始游戏。

使用对手的同龄人ID参加游戏

尝试一下

你可以在https://arteegee.herokuapp.com上试用此示例应用程序。

或者, 你可以从GitHub克隆存储库, 安装NPM依赖项, 然后在本地尝试:

git clone https://github.com/hjr265/arteegee.git 
cd arteegee
npm install
PORT=5000 npm start

服务器运行后, 你可以使用对等ID将Web浏览器指向http:// localhost:5000, 从一个选项卡开始游戏, 然后从另一个选项卡(甚至是其他具有WebRTC功能的Web浏览器)加入游戏。

你可以打开网络浏览器的控制台以查看一些调试信息, 因为在此示例应用程序中, PeerJS客户端已配置为执行详细日志记录。

但这对我不起作用!

该游戏可能无法在你的计算机上运行的主要原因有两个。

你使用的网络浏览器可能不支持必需的WebRTC API。如果是这样, 你可能需要尝试使用其他浏览器-支持WebRTC和数据通道的浏览器。

如果你使用的是支持WebRTC的现代Web浏览器, 则可能存在WebRTC无法渗透的某些网络基础架构。理想情况下, 可以使用TURN服务器轻松解决此问题, 但是由于示例应用程序未使用该服务器, 因此当你和你的对手都位于NAT之后时, 该应用程序将无法工作。

总结

WebRTC是一项新技术, 其实现还远远不成熟。这些通常会给开发人员带来一些独特的挑战。但是, 随着像PeerJS这样的库的出现, 它们可以很好地抽象出粗糙的原始API, 该技术已经变得可以访问。

我希望这个有关构建基于PeerJS的游戏的简短教程将帮助你入门WebRTC并构建一些惊人的实时对等Web应用程序。

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?