首先,我想为我糟糕的英语道歉:)昨天,我用Winsock和Allegro5完成了我在C++中的第一个多人游戏(Pong)的编写。游戏由一个服务器组成,用于所有玩家和客户端。
每帧(FPS=60)客户端将其mouse_y坐标发送到服务器,服务器将其分别传递给对手的客户端。当我在连接到其中一台服务器的两台电脑上玩游戏时,通过本地网络,它运行得很好,对手的球拍移动得很顺利。但当我通过外部IP地址进行同样的连接时,对手的球拍会滞后,这会破坏比赛,因为是客户端检查球是否击中了对手的球拍。因此,同步被破坏了,每当我移动一个球拍在另一台电脑上反弹球时,它就会滞后,无法及时到达,从而为对手得分。。。但这并不是游戏的滞后。我的球拍和球移动得很顺利。问题只出在对手的球拍上。
我是网络编程的新手,因为我只读过Beej的网络编程指南。我使用TCP套接字发送()和接收()桨板的坐标,并使用select()函数轮询套接字中的数据。
我不知道是什么原因造成的。
TL;DR:当我通过外部IP连接时,对手的球拍会滞后,但当我通过本地IP连接时不会。
扩展托马斯的话。我会给你一个更实际的答案。
- 使用UDP进行游戏
如果您坚持使用TCP,那么请执行以下操作。
-
降低TCPAckFrequency的值。
-
禁用nagle的算法,因为您的请求大小较小。请将TCPNoDelay设置为1。
-
减缓两点之间的移动。
-
在打包其余数据的同时发送更少的数据。
-
将接收到的数据包强制转换为结构。
-
不要使用
select
。大约50次连接后,您会注意到huge
性能下降。对于Windows/Linux,分别使用epoll
或IOCP
。
好吧,这是完全预期的行为,是由光速强加的。通过互联网发送的数据包只需要一段时间就可以到达:
$ ping stackoverflow.com
PING stackoverflow.com (198.252.206.16) 56(84) bytes of data.
64 bytes from stackoverflow.com (198.252.206.16): icmp_req=1 ttl=53 time=85.1 ms
这告诉我,从我的机器到stackoverflow.com的RTT(往返时间)是85毫秒,这对网站来说很好,但足以导致实时游戏的明显滞后。
这是个坏消息。更坏的消息是,这是一个很难解决的问题。
职业实时多人游戏使用了几种技巧来减少滞后。例如,他们跟踪每个客户端的延迟,并试图"预测"玩家在当前时间点的位置,即使这些数据包还没有到达。但当然,如果数据包到达,而预测结果是错误的,这将导致玩家突然"跳"到正确的地方。为了解决这个问题,他们在预测的位置和最后一个已知的位置之间进行了一些平滑处理。如果做得好,就会产生实时运动的错觉。
另一个问题是,你不能只在客户端上进行游戏逻辑,因为每个客户端对世界的看法都略有不同。让客户端进行预测是可以的,但服务器应该对球拍是否击球拥有最终发言权。