【发布时间】: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);
}
}
编辑:我删除了客户端绘制循环。现在它很滞后,但它有效!我将审查其他人的问题并相应地编辑此问题。
【问题讨论】: