简单的在线乒乓球游戏网络同步

5
我正在为两个玩家在网络上玩的简单在线乒乓球游戏编写代码。这是一个客户端-服务器应用程序,游戏逻辑在服务器端进行。我在客户端方面遇到了一些游戏同步问题,结果非常不理想。目前的工作方式如下:
1. 服务器端有一个游戏对象,存储玩家和球的位置,每个对象都有它的x、y位置和x、y速度。基于这些数据,在循环中更新对象的位置。 2. 在客户端也有一个本地对象,与服务器端的数据相同,并且在循环中也被更新。 3. 当玩家按下/释放向上或向下键时,客户端会发送一个带有一个整数的网络数据包,以便使玩家对象在服务器端的游戏对象中开始/停止移动。 4. 服务器每50毫秒发送一个同步数据包,其中包括三个对象的位置和速度。当客户端接收到此数据包时,会相应地更改游戏对象的位置。
这种方法效果不佳,因为它会在客户端上来回移动游戏对象。你有什么好的建议来改善它吗?

“不令人满意的结果”和“来回移动对象”是什么意思? - fulguroblastor
1
这篇文章是在这个问题之后出现的:http://drewblaisdell.com/writing/game-networking-techniques-explained-with-pong/ - opyate
1个回答

17

承认客户端和服务器之间有30毫秒的延迟。 客户端发送“我想把球拍向下移动”,它的球拍位于y = 100px处,速度为0.1px / ms。

30毫秒后:

  • 客户端球拍在y = 100 + 30 * 0.1 = 103px处
  • 服务器收到来自客户端的指令并开始移动球拍(当前在服务器端仍处于y = 100px位置)

20毫秒后:

  • 客户端球拍在y = 103 + 20 * 0.1 = 105px处
  • 服务器端客户端球拍在y = 100 + 20 * 0.1 = 102px处
  • 服务器向客户端发送新位置(102px)

30毫秒后:

  • 客户端球拍在y = 105 + 30 * 0.1 = 108px处
  • 客户端从服务器接收球拍的新位置:102px

此时,客户端球拍从108跳回到102px ...

如何处理网络延迟? 两种互补方法:

  • 在执行操作之前等待服务器确认
  • 预测操作结果(在客户端和服务器端)

第一种方法用于客户端与结果几乎无关且不能“回滚”的情况。例如:当客户端发射导弹时,不能接受服务器在下一个更新中删除此导弹,因为客户端实际上没有更多的导弹库存。 所以在这种情况下,客户端应用程序只会在服务器发送确认后才启动导弹。

第二种方法始终用于避免在服务器同步时出现“跳跃”。您必须监视网络延迟以预测游戏元素的移动。有两种方法:计算ping或在启动时同步服务器和客户端时间(最简单,最稳健的方式)。总体思路是:

  • 客户端发送"I wanna move my racket down at time=1265871"并开始移动

30毫秒后:

  • 客户端球拍位于y=100+30*0.1=103像素
  • 服务器接收到移动指令并计算出30毫秒的延迟(通过ping或时间同步差异),将球拍位置设为y=100+latency*0.1=100+30*0.1=103像素

非常好!它们已经同步了。

20毫秒后:

  • 服务器和客户端的球拍都在y=103+20*0.1=105像素处
  • 服务器发送新的位置和方向

30毫秒后:

  • 客户端的球拍位于y=105+30*0.1=108像素
  • 客户端接收到新的位置和方向(朝下移动105像素),计算出30毫秒的延迟时间,并将球拍位置设为y=105+latency*0.1=105*30*0.1=108像素

再次,客户端和服务器保持同步!

当第一个客户端停止移动时,其他客户端可能会发生失去同步的情况。在这种情况下,球拍会"跳"一小段。当这不是很严重时,可以尝试平滑过渡。

希望这会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接