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

时间:2011-01-17 13:19:31

标签: synchronization network-programming

我正在为在网络上玩的两个玩家编写一个简单的在线乒乓球游戏。它是一个客户端 - 服务器应用程序,在服务器端具有游戏逻辑。我在客户端有一些游戏同步问题,结果非常不满意。这就是它目前的工作方式:

  1. 在服务器端,我有一个存储球员位置和球的游戏对象,每个对象都有x,y位置和x,y速度。基于对象的位置在循环中更新。 在客户端,有相同的本地对象具有相同的数据,并且它也在循环中更新。
  2. 当玩家按下/释放向上或向下时,客户端会发送一个包含一个整数的网络数据包,以便玩家对象开始/停止在服务器上的游戏对象中移动。
  3. 服务器每隔50毫秒发送一个同步数据包,其中包含所有三个对象的位置和速度。当客户端收到此数据包时,它会相应地更改游戏对象的位置。
  4. 这种方法不能很好地工作,因为它在客户端来回移动游戏对象。任何想法如何改进它?

1 个答案:

答案 0 :(得分:17)

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

30ms后:

  • 客户端球拍位于y = 100 + 30 * 0.1 = 103px
  • 服务器从客户端接收订单并开始移动球拍 (目前仍在服务器端y = 100px)
<秒> 20秒后:

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

30ms后:

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

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

如何应对网络延迟? 两种互补方式:

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

当客户端上的效果几乎与结果无关并且无法“回滚”时,将使用第一个aproach。例如:当一个客户射击导弹时,它不能说明这个导弹在下一次更新时被服务器压制,因为客户实际上没有更多的导弹库存。因此,在这种情况下,客户端应用程序将仅在服务器发送确认后启动导弹。

第二个用于在服务器同步时避免这些“跳转”。您必须监视网络延迟以预测游戏元素的移动。这里有两种方法:在启动时计算ping或同步服务器和客户端时间(最简单,更健壮的方式)。 一般的想法是:

  • 客户端发送“我想在时间= 1265871时移动我的球拍”并开始移动

30ms后:

  • 客户端球拍在y = 100 + 30 * 0.1 = 103px
  • 服务器接收移动并计算30ms延迟(通过ping或时间同步差异)并将球拍位置设置为y = 100 +延迟* 0.1 = 100 + 30 * 0.1 = 103px

完美!它们是同步的。

20ms后:

  • 服务器和客户端在y = 103 + 20 * 0.1 = 105px
  • 时拍摄
  • 服务器发送新的位置和方向

30ms后:

  • 客户端球拍在y = 105 + 30 * 0.1 = 108px
  • 客户端接收新位置和方向(105px向下移动),计算30ms延迟并将球拍位置设置为y = 105 +延迟* 0.1 = 105 * 30 * 0.1 = 108px

同样,客户端和服务器同步!

当第一个客户端停止移动时,可以在另一个客户端上发生Desync。在这种情况下,球员球拍将“跳跃”一点点。如果这不重要,可以平滑这种转变。

希望它会有所帮助。