前言
随着互联网技术的不断发展,多人在线游戏正在成为越来越流行的游戏类型。在前端领域,使用 socket.io 实现多人游戏已经成为一种较为常见的实现方式。本文就来分享一些关于使用 socket.io 实现多人游戏的实战经验。
socket.io 简介
首先,让我们来了解一下 socket.io。它是一款实现了 WebSocket 协议的 JavaScript 库,可以在客户端和服务器之间建立实时、双向、基于事件的通信,实现实时的多人游戏功能。
实现思路
基于 WebSocket 协议,socket.io 在实现多人游戏时需要考虑以下几个方面:
- Client-Server 之间的实时通信
- 多个 Client 之间的交互
- 数据的同步性
- 应用逻辑的实现
在实现过程中,我们可以基于这些方面,一步步对应实现。
功能分析与设计
对于多人游戏,功能分析与设计是至关重要的。本文以 “五子棋” 游戏为例,简述多人游戏的设计思路。
“五子棋” 游戏是一种比较典型的多人游戏,其游戏规则大致如下:
- 两个玩家轮流在棋盘上下“黑子”或“白子”。
- 任意一方在棋盘上形成了相邻的五枚子,即胜利。
基于此规则,我们需要考虑以下功能实现:
- 玩家发出下子请求并同步到服务器端
- 服务器端将下子请求广播给所有 client
- Client 对下子请求进行处理并同步到其他 client
- 检测游戏是否结束
系统架构
基于以上分析,本文设计实现的多人游戏系统架构如下图所示:
具体实现
在实现多人游戏时,我们需要分别在 Client 和 Server 端实现对应的逻辑。以下为具体实现细节。
Server 实现
Step 1:Server 运行及监听
// javascriptcn.com 代码示例 // 引入 express、socket.io 库 const express = require('express'); const http = require('http'); const socketIo = require('socket.io'); const app = express(); const server = http.createServer(app); const io = socketIo(server); // 监听端口 const port = 3000; server.listen(port, () => console.log('server running on port ' + port));
Step 2:Server 监听连接请求
io.on('connection', (socket) => { console.log('a user connected'); // 进入房间操作 socket.on('enterRoom', (roomId) => { socket.join(roomId); }); ... });
Step 3:Server 支持下棋请求
// javascriptcn.com 代码示例 // 存放房间数组 let rooms = {}; io.on('connection', (socket) => { ... // 下棋请求 socket.on('addChess', (data) => { // 当前房间 Id const roomId = data.roomId; // 对应房间对象 let room = rooms[roomId]; // 棋盘 let { board } = room; // 棋盘对应坐标位置 let { x, y } = data; // 棋子种类 let { chess } = data; // 检查落子位置是否正确 if (!checkPosition(board, x, y)) { return; } // 处理落子 board[x][y] = chess; // 检查游戏是否结束 if (checkWin(board, x, y, chess)) { room.lastChess = chess; io.emit('game-win', { roomId, winner: chess }); return; } // 广播当前落子情况 io.to(roomId).emit('addChessAck', { x, y, chess }); }); });
Step 4:Server 检查游戏是否结束
function checkWin(board, x, y, chess) { // everyWin = [ [ [ x, y ], [ x + 1, y ], ... ], [] ] return everyWin.some((v, i) => { return v.every(([ mx, my ]) => { return board[mx][my] === chess; }); }); }
Step 5:Server 维护当前房间状态
// javascriptcn.com 代码示例 io.on('connection', (socket) => { ... // 初始化房间状态 if (!rooms[roomId]) { rooms[roomId] = { board: [], lastChess: '', players: [], }; } // 将当前客户端加入到房间中 room.players.push(socket.id); socket.join(roomId); // 离开房间事件 socket.on('disconnecting', () => { deletePlayer(socket, roomId); }); function deletePlayer(socket, roomId) { let room = rooms[roomId]; let players = room.players; let index = players.indexOf(socket.id); players.splice(index, 1); // 检测房间是否为空 if (players.length === 0) { delete rooms[roomId]; } } });
Client 实现
Step 1:Client 加入房间
// 进入房间对应的事件 socket.emit('enterRoom', roomId); socket.on('addChessAck', (data) => { ... });
Step 2:Client 请求下棋
// javascriptcn.com 代码示例 // Client 端监听棋盘点击事件 cv 是 canvas 对象 canvas.addEventListener('click', function (event) { // 获得当前落子坐标 x, y let { x, y } = getCursorPosition(event); if (chess === 'black' && turn === 'black' || chess === 'white' && turn === 'white') { // 向服务器端发送下棋请求 socket.emit('addChess', { roomId, x, y, chess }); ... } });
Step 3:Client 处理落子请求
// 接收服务器端的 addChessAck 事件 socket.on('addChessAck', (data) => { let { x, y, chess } = data; // 画出当前落子 drawChess(cv, x, y, chess); updateBoard(boardData, { x, y, chess }); });
Step 4:Client 更新游戏状态
// javascriptcn.com 代码示例 socket.on('game-win', (data) => { const { winner } = data; let msg; if (winner === chess) { msg = '你赢了!'; } else { msg = '你输了!'; } alert(msg); });
总结
通过以上实现,我们成功地利用了 socket.io 实现了多人游戏。其中的步骤不仅适用于“五子棋”游戏,同样适用于其他形式的多人游戏。希望读者可以通过本文的介绍,更好地掌握使用 socket.io 实现多人游戏的方法,同时也能够构思并开发出更加优秀的多人游戏!
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6528be727d4982a6ebb4c86a