WebSocket 是 HTML5 中的一个新协议,它实现了浏览器与服务器全双工通信,可以实时地传输数据。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,可以帮助我们快速地构建高性能的网络应用程序。本文将介绍如何使用 Node.js 实现一个基于 WebSocket 的游戏,希望能够帮助大家学习和掌握 WebSocket 技术。
WebSocket 简介
WebSocket 是一种网络通信协议,它能够在浏览器和服务器之间建立一个可持续的连接,实现双向实时通信。WebSocket 协议是在 TCP 协议之上实现的,它的优点是:
- 可以在一个连接上发送任意数据,不像 HTTP 只能发送请求和响应。
- 可以实现实时通信,不需要轮询服务器。
- 与 HTTP 协议兼容,可以通过 HTTP 端口进行通信。
WebSocket 协议是一个标准化协议,目前已经被广泛应用于各种实时通信场景,例如在线游戏、即时聊天等。
Node.js 实现 WebSocket
Node.js 提供了一个 ws
模块,可以轻松地实现 WebSocket 服务器和客户端。下面是一个简单的示例代码:
// javascriptcn.com 代码示例 // 引入 ws 模块 const WebSocket = require('ws'); // 创建 WebSocket 服务器 const wss = new WebSocket.Server({ port: 8080 }); // 监听连接事件 wss.on('connection', (ws) => { console.log('client connected'); // 监听消息事件 ws.on('message', (message) => { console.log(`received: ${message}`); // 发送消息给客户端 ws.send(`you said: ${message}`); }); // 监听关闭事件 ws.on('close', () => { console.log('client disconnected'); }); });
上面的代码创建了一个 WebSocket 服务器,监听 8080 端口。当客户端连接到服务器时,会触发 connection
事件。在连接建立后,服务器会监听客户端发送的消息,并将消息原样发送回去。当客户端关闭连接时,会触发 close
事件。
WebSocket 游戏实现
下面我们将使用 Node.js 和 WebSocket 实现一个简单的游戏,游戏规则是:两个玩家分别控制一个小球,互相碰撞后游戏结束。我们将使用 p5.js
来绘制游戏画面,socket.io
来实现 WebSocket 通信。
客户端实现
首先,我们需要创建一个 HTML 页面,引入 p5.js
和 socket.io
库:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>WebSocket Game</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script> <script src="/socket.io/socket.io.js"></script> </head> <body> <script src="sketch.js"></script> </body> </html>
然后,我们需要编写 sketch.js
文件,使用 p5.js
绘制游戏画面,并使用 socket.io
实现 WebSocket 通信:
// javascriptcn.com 代码示例 // 创建 WebSocket 连接 const socket = io(); // 定义玩家 ID 和位置 let playerId = null; let playerX = 0; let playerY = 0; // 定义对手 ID 和位置 let opponentId = null; let opponentX = 0; let opponentY = 0; function setup() { createCanvas(400, 400); background(255); // 监听连接事件 socket.on('connect', () => { console.log('connected'); // 发送加入游戏请求 socket.emit('join'); }); // 监听加入游戏响应 socket.on('join', (data) => { console.log('join', data); // 保存玩家 ID 和位置 playerId = data.id; playerX = data.x; playerY = data.y; }); // 监听对手进入游戏事件 socket.on('opponent', (data) => { console.log('opponent', data); // 保存对手 ID 和位置 opponentId = data.id; opponentX = data.x; opponentY = data.y; }); // 监听对手移动事件 socket.on('move', (data) => { console.log('move', data); // 更新对手位置 opponentX = data.x; opponentY = data.y; }); // 监听游戏结束事件 socket.on('end', (data) => { console.log('end', data); // 显示游戏结束提示 alert('Game over!'); }); } function draw() { background(255); // 绘制玩家和对手 fill(255, 0, 0); ellipse(playerX, playerY, 20, 20); fill(0, 0, 255); ellipse(opponentX, opponentY, 20, 20); // 判断是否碰撞 if (dist(playerX, playerY, opponentX, opponentY) < 20) { // 发送游戏结束请求 socket.emit('end'); } } function keyPressed() { // 移动玩家 if (keyCode === LEFT_ARROW) { playerX -= 5; } else if (keyCode === RIGHT_ARROW) { playerX += 5; } else if (keyCode === UP_ARROW) { playerY -= 5; } else if (keyCode === DOWN_ARROW) { playerY += 5; } // 发送移动请求 socket.emit('move', { x: playerX, y: playerY }); }
上面的代码实现了以下功能:
- 创建 WebSocket 连接。
- 监听连接事件,发送加入游戏请求。
- 监听加入游戏响应,保存玩家 ID 和位置。
- 监听对手进入游戏事件,保存对手 ID 和位置。
- 监听对手移动事件,更新对手位置。
- 监听游戏结束事件,显示游戏结束提示。
- 在
draw()
函数中绘制玩家和对手。 - 在
keyPressed()
函数中移动玩家,发送移动请求。
服务器实现
接下来,我们需要编写服务器端代码,使用 ws
模块实现 WebSocket 服务器。服务器需要实现以下功能:
- 监听客户端连接事件,为每个客户端分配一个 ID。
- 监听客户端发送的加入游戏请求,将玩家加入游戏并通知对手。
- 监听客户端发送的移动请求,更新玩家位置并通知对手。
- 监听客户端发送的游戏结束请求,结束游戏并通知对手。
下面是服务器端的示例代码:
// javascriptcn.com 代码示例 // 引入 ws 模块 const WebSocket = require('ws'); // 创建 WebSocket 服务器 const wss = new WebSocket.Server({ port: 8080 }); // 定义玩家列表和对手列表 const players = {}; const opponents = {}; // 定义玩家 ID 计数器 let playerIdCounter = 0; // 监听连接事件 wss.on('connection', (ws) => { console.log('client connected'); // 为客户端分配 ID const playerId = playerIdCounter++; players[playerId] = { x: Math.random() * 360 + 20, y: Math.random() * 360 + 20 }; // 监听消息事件 ws.on('message', (message) => { console.log(`received: ${message}`); // 解析消息 const data = JSON.parse(message); // 处理加入游戏请求 if (data.type === 'join') { console.log('join', data); // 将玩家加入游戏 players[playerId] = { x: Math.random() * 360 + 20, y: Math.random() * 360 + 20 }; ws.send(JSON.stringify({ type: 'join', id: playerId, x: players[playerId].x, y: players[playerId].y })); // 查找对手 for (const opponentId in opponents) { // 发送对手进入游戏事件 opponents[opponentId].ws.send(JSON.stringify({ type: 'opponent', id: playerId, x: players[playerId].x, y: players[playerId].y })); ws.send(JSON.stringify({ type: 'opponent', id: opponentId, x: players[opponentId].x, y: players[opponentId].y })); } // 将玩家加入对手列表 opponents[playerId] = { ws: ws }; } // 处理移动请求 if (data.type === 'move') { console.log('move', data); // 更新玩家位置 players[playerId].x = data.x; players[playerId].y = data.y; // 发送对手移动事件 for (const opponentId in opponents) { if (opponentId !== playerId.toString()) { opponents[opponentId].ws.send(JSON.stringify({ type: 'move', id: playerId, x: data.x, y: data.y })); } } } // 处理游戏结束请求 if (data.type === 'end') { console.log('end', data); // 发送游戏结束事件 for (const opponentId in opponents) { if (opponentId !== playerId.toString()) { opponents[opponentId].ws.send(JSON.stringify({ type: 'end', id: playerId })); } } // 将玩家从对手列表中移除 delete opponents[playerId]; } }); // 监听关闭事件 ws.on('close', () => { console.log('client disconnected'); // 将玩家从玩家列表中移除 delete players[playerId]; // 发送对手离开游戏事件 for (const opponentId in opponents) { if (opponentId !== playerId.toString()) { opponents[opponentId].ws.send(JSON.stringify({ type: 'leave', id: playerId })); } } // 将玩家从对手列表中移除 delete opponents[playerId]; }); });
上面的代码实现了以下功能:
- 定义玩家列表和对手列表。
- 定义玩家 ID 计数器。
- 监听连接事件,为每个客户端分配一个 ID。
- 监听消息事件,处理加入游戏请求、移动请求和游戏结束请求。
- 监听关闭事件,将玩家从玩家列表和对手列表中移除,并通知对手。
总结
本文介绍了如何使用 Node.js 和 WebSocket 实现一个简单的游戏,通过这个例子,我们可以学习和掌握 WebSocket 技术的基本原理和实现方法。WebSocket 技术在实时通信场景中有着广泛的应用,例如在线游戏、即时聊天等。希望本文能够帮助大家更深入地了解 WebSocket 技术。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/657eba76d2f5e1655d994455