Я хотел бы создать простую многопользовательскую игру с Node.js и socket.io. Моя текущая настройка времени не оптимальна, так как рендеринг не плавный. Пока что игроки просто кружатся по холсту.
Я пытаюсь примерно объяснить эту настройку, добавляя несколько фрагментов кода, пожалуйста, дайте мне знать, когда потребуется дополнительный код.
Каждый раз, когда клиент подключается к серверу, новый игрок создается и добавляется в список игроков. Кроме того, мы добавляем слушателей для ключевых вводов клиентов (которые в основном меняют направление).
io.on("connection", (socket) => {
const p = playerList.add(socket.id);
socket.on("keydown", (key) => p.addControlKeyDown(key));
socket.on("keyup", (key) => p.addControlKeyUp(key));
}
Также на стороне сервера, у нас есть обновление l oop. Так как в Node.js нет requestAnimationFrame
, я пробовал использовать setInterval
. После каждого обновления мы отправляем то, что важно для рисования (это то, для чего предназначена p.extract ()) всем клиентам.
function updateLoop() {
for (p of playerList.players) {
p.update();
}
const currentPlayers = playerList.players.map((p) => p.extract());
io.emit("playerUpdate", currentPlayers);
}
const interval = setInterval(updateLoop, 30);
Я уже пробовал здесь 30 миллисекунд, но это не так. Не решает проблему.
На клиенте мы слушаем обновления:
let players = [];
socket.on("playerUpdate", (currentPlayers) => {
players = currentPlayers;
});
На клиенте у нас также есть отрисовка l oop с использованием requestAnimationFrame
:
function drawLoop() {
clearCanvas();
players.forEach(drawPlayer);
requestAnimationFrame(drawLoop);
}
Связь между сервером и клиентом работает, но, как вы можете видеть, время не совсем оптимальное.
Как это можно улучшить?
Моя первая идея заключалась в том, чтобы избежать l oop на стороне клиента, поскольку мы уже есть на сервере, и напрямую оттуда отправлять запрос на отрисовку клиентам, но это оказывается еще хуже.
Я знаю, что для сложных многопользовательских игр нужно приложить гораздо больше усилий для синхронизации , и этот также делает снимки игрового мира и фактически отображает «прошлое» для клиентов. Надеюсь, что в этом простом примере такие сложные методы не нужны.