You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Socket.IO中为房间绑定矩阵数据?双人游戏方案咨询

给Socket.IO房间绑定自定义矩阵数据的可行方案

Socket.IO 本身并没有内置的「给房间附加自定义数据」的功能,但我们完全可以自己在服务器端实现这个逻辑——不管是把矩阵绑定到房间,还是关联到两个 Socket 连接,都是可行的,具体选哪种取决于你的游戏需求和后续扩展计划。

方案一:把矩阵绑定到房间

这种方案是在服务器端维护一个全局的「房间-数据」映射对象,把矩阵和房间ID关联起来。逻辑上更清晰,也方便后续扩展成多人游戏。

实现示例

// 服务器端(Express + Socket.IO)
const roomData = {}; // 键:房间ID,值:包含矩阵的房间数据

io.on('connection', (socket) => {
  // 处理用户加入房间的请求
  socket.on('join-game-room', (roomId) => {
    socket.join(roomId);
    
    // 如果房间还没有初始化矩阵,就创建一个新的
    if (!roomData[roomId]) {
      roomData[roomId] = {
        matrix: Array(5).fill().map(() => Array(5).fill(0)) // 示例:5x5的空矩阵
      };
    }
    
    // 把当前房间的矩阵发给新加入的玩家
    socket.emit('init-game-matrix', roomData[roomId].matrix);
  });

  // 处理玩家修改矩阵的请求
  socket.on('update-matrix', (roomId, updatedMatrix) => {
    if (roomData[roomId]) {
      // 更新服务器端的矩阵数据
      roomData[roomId].matrix = updatedMatrix;
      // 把更新后的矩阵广播给房间里的所有玩家
      io.to(roomId).emit('matrix-updated', updatedMatrix);
    }
  });

  // 清理空房间的数据,避免内存泄漏
  socket.on('disconnecting', () => {
    // 获取当前socket所在的所有房间(排除socket自身的ID房间)
    const rooms = Object.keys(socket.rooms).filter(id => id !== socket.id);
    rooms.forEach(roomId => {
      // 检查房间里还有没有其他玩家
      io.in(roomId).allSockets().then(socketsInRoom => {
        if (socketsInRoom.size === 0) {
          delete roomData[roomId];
        }
      });
    });
  });
});

优缺点

  • 优点:数据和房间强关联,逻辑清晰;天然支持多人游戏,后续扩展成本低;所有玩家共享同一份数据,同步逻辑简单。
  • 缺点:需要自己管理房间数据的生命周期(比如空房间要及时清理),否则可能导致内存泄漏。

方案二:把矩阵绑定到两个Socket连接

如果你的游戏确定是固定双人模式,也可以直接把矩阵关联到配对的两个Socket实例上,逻辑更轻量化。

实现示例

// 服务器端(Express + Socket.IO)
const playerPairs = {}; // 存储配对的玩家和对应的矩阵

io.on('connection', (socket) => {
  // 处理玩家寻找匹配的请求
  socket.on('find-opponent', () => {
    // 找一个正在等待的玩家
    const waitingPlayer = Object.values(playerPairs).find(pair => !pair.player2);
    
    if (waitingPlayer) {
      // 配对成功,绑定第二个玩家和初始化矩阵
      waitingPlayer.player2 = socket;
      const gameMatrix = Array(5).fill().map(() => Array(5).fill(0));
      waitingPlayer.matrix = gameMatrix;
      
      // 通知两个玩家匹配成功并发送初始矩阵
      waitingPlayer.player1.emit('match-success', gameMatrix);
      socket.emit('match-success', gameMatrix);
    } else {
      // 没有等待的玩家,加入等待队列
      playerPairs[socket.id] = { player1: socket, player2: null };
    }
  });

  // 处理玩家修改矩阵的请求
  socket.on('update-matrix', (updatedMatrix) => {
    // 找到当前玩家所属的配对
    const currentPair = Object.values(playerPairs).find(
      pair => pair.player1 === socket || pair.player2 === socket
    );
    
    if (currentPair) {
      currentPair.matrix = updatedMatrix;
      // 把更新后的矩阵发给对手
      const opponent = currentPair.player1 === socket ? currentPair.player2 : currentPair.player1;
      opponent.emit('matrix-updated', updatedMatrix);
    }
  });

  // 玩家断开连接时清理配对数据
  socket.on('disconnect', () => {
    const currentPair = Object.values(playerPairs).find(
      pair => pair.player1 === socket || pair.player2 === socket
    );
    
    if (currentPair) {
      // 通知对手断开连接
      const opponent = currentPair.player1 === socket ? currentPair.player2 : currentPair.player1;
      if (opponent) opponent.emit('opponent-left');
      
      // 从配对列表中删除
      const pairKey = Object.keys(playerPairs).find(key => playerPairs[key] === currentPair);
      delete playerPairs[pairKey];
    }
  });
});

优缺点

  • 优点:逻辑更简单,针对双人场景做了简化,不需要处理多房间的复杂逻辑。
  • 缺点:扩展性差,如果以后想改成多人游戏,需要大幅重构代码。

总结

如果你的游戏有后续扩展成多人的可能,方案一(绑定房间) 是更好的选择;如果确定只做双人模式,方案二(绑定Socket对) 更轻便。核心记住:Socket.IO的房间只是一个「分组广播」的机制,没有内置数据存储能力,所有自定义数据都需要我们在服务器端自己维护。

内容的提问来源于stack exchange,提问作者user5999835

火山引擎 最新活动