【问题标题】:Real-Time multiplayer: EDIT: How to smooth out animation frames on Canvas实时多人游戏:编辑:如何平滑画布上的动画帧
【发布时间】:2019-11-11 18:36:48
【问题描述】:

我正在尝试构建一个实时多人游戏应用程序。为此,我使用了 React、Node.js 和 Socket.io。将其部署到 Heroku 后,我发现了我的问题。如果我从笔记本电脑访问它,我开发它就像一个魅力。一切都根据两者的输入显示 我和我的对手。然而,在其他设备上,画布上绘制的所有对象都会发疯。设备是否在同一个网络中没有区别。

用户应该进入 socket.io 房间。首先,他们在聊天中相遇,点击就绪后,他们立即被发送到 GameRoom,游戏随即开始。

我非常感谢任何形式的输入或提示!如果您没有准备好答案,但对如何改进我的问题以帮助人们理解我的问题有意见,请随时发表评论。

首先我改变了 socket.io 通过socket.volatile.to(room).emit() 将当前游戏状态发送到房间的方式。我认为它会优化服务器消息的处理。这没有帮助。

然后我调整了游戏在客户端的绘制方式。客户端的绘制逻辑现在类似于服务器端的绘制逻辑,但这也无济于事。

这就是为什么我认为我绘制游戏的方式不是问题所在。

我是训练营的一员,我所有的同学都使用和我一样的 MacBook。如果我想和他们比赛,他们的比赛显示不正确,但我的比赛显示正常。因此,我得出结论,这不是硬件。

我删除了所有 .env 变量。因此这也不应该是问题。我没有想法。

这是我的套接字客户端代码:

import io from "socket.io-client";

export default function Main({ setSettings, settings }) {
  const [connectedTo, setConnectionTo] = React.useState({});

  React.useEffect(() => {
    const socket = io();
    socket.emit("setname", getItem("nickname"));
    setConnectionTo({ connected: true, socket, player: false });
    return () => {
      socket.close();
      setConnectionTo(false);
    };
  }, [connectedTo.room]);

这是客户端绘制循环。它在另一个组件中,并通过 props 获取套接字:

  React.useEffect(() => {
    let currentFrame;
    let canvas = canvasRef.current;
    let ctx = canvas.getContext("2d");
    const drawLoop = () => {
      const now = Date.now();
      const timeSinceLastDraw = game.global.lastDraw
        ? now - game.global.lastDraw
        : 0;
      game.global.lastDraw = now;

      const newGameState = calculateNewGameStateClient(game, 
      timeSinceLastDraw);
      const { ball, player1, player2, global } = newGameState;

      drawGameState(ctx, global, ball, player1, player2);

      if (game.global.play) {
        currentFrame = requestAnimationFrame(() => drawLoop());
      }
    };
    if (game && game.global.play !== "ended") {
      drawLoop();
    }
    return () => cancelAnimationFrame(currentFrame);
  }, [game]);

这是服务器端的套接字:

const express = require("express");
const path = require("path");

const PORT = 5000;

const app = express();

app.use(express.static(path.join(__dirname, "client/build")));
app.get("*", function(req, res) {
  res.sendFile(path.join(__dirname, "client/build", "index.html"));
});

const server = app.listen(PORT, () => console.log(`Listening on ${PORT}`));

initSocket(server);

这是服务器端的绘制循环:

    function drawLoop(game) {
      const now = Date.now();
      const timeSinceLastDraw = game.global.lastDraw
        ? now - game.global.lastDraw
        : 0;
      game.global.lastDraw = now;
      const newGameState = calculateNewGameStateServer(
        game,
        io,
        room,
        timeSinceLastDraw
      );
      if (game.global.play) {
        updateTime += timeSinceLastDraw;
        if (updateTime > 100) {
          io.to(room).emit("new frame", newGameState);
          updateTime = 0;
        }
        setTimeout(() => drawLoop(newGameState), 0);
      } else {
        const player1Won = game.player2.lifes === 0;
        game.global.winner = player1Won ? "1" : "2";
        game.global.lastDraw = 0;
        socket.emit("game ended", game);
      }
    }

编辑:我删除了客户端绘制循环。现在它很滞后,但它有效!我将审查其他人的问题并相应地编辑此问题。

【问题讨论】:

    标签: node.js reactjs socket.io


    【解决方案1】:

    我无法弄清楚为什么它在一台特定的机器上工作。一位朋友告诉我尝试隐身模式,因为它可能会忽略缓存。但是,主要问题似乎是客户端循环。由于这是一个完全不同的问题,这里有很多答案,我认为这个问题可以被视为“已回答”。

    例如:Smooth Canvas Animation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-17
      • 2016-08-13
      • 2013-07-02
      • 2012-08-02
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多