6

我正在开发一个基于 Javascript 的多人游戏。到目前为止,我已经准备好基本的服务器、客户端和网络。

我确实遇到了一个问题,即我的播放器在 120Hz 屏幕上比在 60Hz 屏幕上移动得更快。我通过将玩家的移动速度乘以“requestAnimationFrame”的增量时间来解决这个问题。

然而; 将动画与逻辑分开会是更好的解决方案吗?

如:

//Game loop; Do each 1/60th of a second
setInterval(gameTick, 1000/60);
function gameTick(){
  player.handleKeys();
  enemies.foreach( (enemy) => {
    enemy.update();
  });
}

//Draw loop; match to player screen refresh rate
window.requestAnimationFrame(gameLoop);
function gameLoop() {
    player.draw();
    enemies.foreach( (enemy) => {
    enemy.draw();
  });
  window.requestAnimationFrame(gameLoop);
}

虽然差异可能是“可以忽略的”,但我想避免使用 240Hz 的玩家向服务器“发送垃圾邮件”,并且比其他玩家更有优势。

另一方面,对于 240Hz 显示器;您的键盘输入仅会处理 4 帧中的 1 帧,所以感觉可能不那么流畅?

我要问的这个原因是这将是一场竞争性的游戏,因此应该保持平衡。但是我已经检查了各种来源,共识似乎是使用 requestAnimationFrame (即使是逻辑;不仅仅是绘图),尽管我对此表示怀疑并想知道哪个是正确的(和/或用于专业竞技游戏)。

4

1 回答 1

3

requestAnimationFrame(rAF) 只会以 60fps 的最大速率发射。(例外一些更旧版本的某些浏览器有关闭 VSync 的标志,这确实影响了 rAF)

笔记

  • rAfsetTimeout或者setInterval不可靠并且可能由于多种原因而丢帧。

  • 如果选项卡或窗口被隐藏或(选项卡)未聚焦,rAF 将停止触发。

  • setInterval如果选项卡或窗口被隐藏或(选项卡)未聚焦,setTimeout则会受到限制。

  • rAF 时间参数不代表(下一个显示的)帧的时间,而是调用 rAF 回调的时间。

    这意味着...

    • 如果从 rAF 时间参数计算的帧之间的时间将浮动并且不能可靠地用作增量时间。
    • time 参数表示调用的时间,而不是呈现给显示器的帧时间,并且可以比呈现的内容呈现给显示硬件的时间早 < 1/60 秒。

本地网络

对于多人游戏,服务器应该提供时间,以便所有玩家在一个通用且可靠的时间戳上运行。如果网络延迟数据包,客户端可以从最后一个时间戳向前投影时间以避免冻结,但应在收到时恢复为同步(服务器时间)时间。

大型网络

通信取决于距离,即使在完美的点对点网络上,如果客户端在世界的另一端,由于传输时间短,可能的最佳 ping 为 130 毫秒(接近 8 帧 @60Hz)。这不包括数据包交换和实际路由长度。通常,到地球上最远​​点的 ping 时间约为 300 毫秒。

职业游戏必须考虑这种延迟,这也是为什么许多多人游戏提供本地服务器,如果远离某些服务器则限制玩家进入的原因。300ms 为距离较近的玩家提供了显着优势。

使用浏览器 API 托管客户端的实时多人游戏充其量是有问题的,因为浏览器是一个不可靠且不一致的客户端主机,主要是由于客户端运行的设备范围很大。

顺便提一句

window是默认值this( globalThis),因此不是必需的。例如window.requestAnimationFrame等同于requestAnimationFrame

于 2019-09-22T12:56:40.917 回答