【问题标题】:Simple online pong game network synchronization简单的在线乒乓球游戏网络同步
【发布时间】:2011-01-17 13:19:31
【问题描述】:
我正在为两个通过网络玩的玩家编写一个简单的在线乒乓球游戏。它是一个客户端-服务器应用程序,在服务器端具有游戏逻辑。我在客户端的游戏同步方面遇到了一些问题,结果很不满意。这就是它目前的工作方式:
- 在服务器端,我有一个存储球员和球位置的游戏对象,每个对象都有其 x、y 位置和 x、y 速度。基于对象的位置在循环中更新。
在客户端有相同的本地对象,具有相同的数据,并且它也在循环中更新。
- 当玩家按下/松开向上或向下时,客户端发送一个整数的网络数据包,以便玩家对象开始/停止在服务器上的游戏对象中移动。
- 服务器每 50 毫秒发送一个同步数据包,其中包含所有三个对象的位置和速度。当客户端收到此数据包时,它会相应地更改游戏对象的位置。
此方法效果不佳,因为它会在客户端来回移动游戏对象。有什么改进的方法吗?
【问题讨论】:
标签:
synchronization
network-programming
【解决方案1】:
承认您在客户端和服务器之间有 30 毫秒的延迟。
客户端发送“我想把我的球拍放下”,它的球拍在 y=100px,速度为 0.1px/ms
30ms 秒后:
- 客户端球拍在 y=100+30*0.1= 103px
- 服务器收到客户端的命令并开始移动球拍
(目前在服务器端仍为 y=100px)
20ms 秒后:
- 客户端球拍在 y=103+20*0.1 = 105px
- 服务器端客户端球拍在 y=100+20*0.1= 102px
- 服务器向客户端发送新位置(102px)
30ms 秒后:
- 客户端球拍在 y=105+30*0.1= 108px
- 客户端从服务器接收到球拍的新位置:102px
此时,客户端球拍从 108 向后“跳跃”到 102px...
如何应对网络延迟?
两种互补方式:
- 在执行操作之前等待服务器确认
- 预测操作结果(在客户端和服务器端)
当对客户端的效果与结果几乎没有联系并且不能“回滚”时,使用第一种方法。示例:当客户端发射导弹时,不可否认该导弹在下一次更新时被服务器压制,因为客户端实际上没有更多的导弹库存。所以在这种情况下,客户端应用程序只有在服务器发送确认后才会发射导弹。
第二个总是用于在服务器同步时避免这些“跳转”。您必须监控网络延迟以预测游戏元素的移动。这里有两种方法:在启动时计算 ping 或同步服务器和客户端时间(最简单和更健壮的方法)。
总体思路是:
- 客户发送“我想在 time=1265871 时将球拍向下移动”并开始移动
30 毫秒后:
- y=100+30*0.1= 103px 处的客户球拍
- 服务器接收移动并计算 30ms 延迟(通过 ping 或时间同步差异)并将球拍位置设置为 y=100+latency*0.1= 100+30*0.1= 103px
完美!它们是同步的。
20 毫秒后:
- 服务器和客户端都在 y=103+20*0.1= 105px
- 服务器发送新的位置和方向
30 毫秒后:
- y=105+30*0.1= 108px 处的客户球拍
- 客户端收到新的位置和方向(105px 向下移动),计算 30ms 延迟并将球拍位置设置为 y=105+latency*0.1= 105*30*0.1= 108px
再次,客户端和服务器同步!
当第一个客户端停止移动时,另一个客户端可能会发生不同步。在这种情况下,球员的球拍会“跳跃”一点。当这不是关键时,可以平滑过渡。
希望它会有所帮助。