运动“算法” 在客户端-服务器多人 (MMO) 游戏中?
我一直在编写一个 2D flash 多人游戏和一个套接字服务器。 我最初对客户端和服务器之间的移动算法的计划如下:
- 客户端通知服务器玩家的移动模式(向前或不移动)和玩家的转弯模式(不转弯、左转或右转)。改变。
- 服务器每隔几毫秒循环一次所有玩家,并根据时间差计算转动的角度和移动的距离。 客户端也进行同样的计算。
我当前对客户端的计算(在服务器中使用相同的数学)==>
转向
var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
var rot:uint = Math.round((newTimeStamp - turningTimeStamp) / 1000 * 90); //speed = x degrees turning every 1 second
turningTimeStamp = newTimeStamp; //update timeStamp
if (turningMode == 1) //left
{
movementAngle = fixAngle(movementAngle - rot);
}
else if (turningMode == 2) //right
{
movementAngle = fixAngle(movementAngle + rot);
}
private function fixAngle(angle:int):uint //fixes an angle in degrees (365 -> 5, -5 -> 355, etc.)
{
if (angle > 360)
{
angle -= (Math.round(angle / 360) * 360);
}
else if (angle < 0)
{
angle += (Math.round(Math.abs(angle) / 360) + 1) * 360;
}
return angle;
}
移动
var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
var distance:uint = Math.round((newTimeStamp - movementTimeStamp) / 1000 * 300); //speed = x pixels forward every 1 second
movementTimeStamp = newTimeStamp; //update old timeStamp
var diagonalChange:Array = getDiagonalChange(movementAngle, distance); //with the current angle, howmuch is dX and dY?
x += diagonalChange[0];
y += diagonalChange[1];
private function getDiagonalChange(angle:uint, distance:uint):Array
{
var rAngle:Number = angle * Math.PI/180;
return [Math.round(Math.sin(rAngle) * distance), Math.round((Math.cos(rAngle) * distance) * -1)];
}
这似乎很有效。 为了考虑到延迟,服务器会不时地通过发送此数据来更正客户端的信息。
对于该系统,用于处理移动的带宽非常少。 然而,我的服务器和客户端的坐标和角度差异太大。 我是否应该扩展我的“算法”,以考虑用户的延迟? 或者是否有更好的方法来处理具有出色性能的客户端<>服务器多人游戏中的移动?
I've been writing a 2D flash multiplayer game and a socket server. My original plan for the movement algorithm between the client and server was the following:
- The client informs the server about the player's movement mode (moving forward or not moving) and the player's turning mode (not turning, turning left or turning right) whenever these change.
- The server loops all players every few milliseconds and calculates the angle turned and distance moved, based on the difference in time. The same calculation is done by the client.
My current calculation for the client (same math is used in server) ==>
Turning
var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
var rot:uint = Math.round((newTimeStamp - turningTimeStamp) / 1000 * 90); //speed = x degrees turning every 1 second
turningTimeStamp = newTimeStamp; //update timeStamp
if (turningMode == 1) //left
{
movementAngle = fixAngle(movementAngle - rot);
}
else if (turningMode == 2) //right
{
movementAngle = fixAngle(movementAngle + rot);
}
private function fixAngle(angle:int):uint //fixes an angle in degrees (365 -> 5, -5 -> 355, etc.)
{
if (angle > 360)
{
angle -= (Math.round(angle / 360) * 360);
}
else if (angle < 0)
{
angle += (Math.round(Math.abs(angle) / 360) + 1) * 360;
}
return angle;
}
Movement
var newTimeStamp:uint = UtilLib.getTimeStamp(); //set current timeStamp
var distance:uint = Math.round((newTimeStamp - movementTimeStamp) / 1000 * 300); //speed = x pixels forward every 1 second
movementTimeStamp = newTimeStamp; //update old timeStamp
var diagonalChange:Array = getDiagonalChange(movementAngle, distance); //with the current angle, howmuch is dX and dY?
x += diagonalChange[0];
y += diagonalChange[1];
private function getDiagonalChange(angle:uint, distance:uint):Array
{
var rAngle:Number = angle * Math.PI/180;
return [Math.round(Math.sin(rAngle) * distance), Math.round((Math.cos(rAngle) * distance) * -1)];
}
This seems to work great. In order to take lag into account, the server corrects the client's info every now and then by sending this data.
With this system very little bandwidth is used to handle movement. However, the differences between my server and the client's coordinates and angles are too big. Should I maybe extend my "algorithm", to also take into account the latency a user has? Or are there better ways of handling movement in client<>server multiplayer games with great performance?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的初始设计与您的类似,但如果这不起作用,也许您可以允许客户端执行所有移动,然后让服务器进行一些范围检查。
因此,如果您最后报告的位置是 X,则下一个报告的位置必须在 X 的半径范围内,其中半径基于客户端发送的带有 x,y 数据的时间戳的差异。
大多数情况下,这只是检测作弊所需要的。
停止、战斗等需要随攻击一起发送位置,并且位置触发的操作仅在客户端发送该位置的更新后才会触发,但基于服务器。
不确定这会有多大帮助,但它可能会阻止您从初始算法中看到的颠簸重新同步。
评论回复:
不,客户端仍然会通知服务器他们的位置,但服务器不会尝试计算下一个位置。 这意味着服务器(以及所有其他客户端)将至少落后一个发送/接收周期。
我想我是说让客户端完成所有工作,找出角色在哪里并告诉服务器,但要包含足够的信息,以便服务器可以选择检查有效性以确保没有人作弊。
甚至可以关闭作弊检测以提高性能或设置为随机检查。
注意:行进范围内物体的所有碰撞/位置信息都需要发送给客户端才能正常工作。
My initial design would be similar to yours, but if that's not working, perhaps you could allow the client to do ALL the movement and just have the server do some range checking.
So if your last reported position was X, the next one must be within a radius from X where the radius is based on the difference in timestamps sent from the client with the x,y data.
Mostly this is just needed to detect cheating.
Stopping, fighting, etc would require a position be sent along with the attack, and actions triggered by positions would only be triggered after the client sent the update for that position but would be server-based.
Not sure this would help too much, but it might stop the jolting resyncs you would see from your initial algorithm.
Comment response:
No, the clients would still inform the server of their position, but the server wouldn't try to calculate the next position. This would mean that the server (and all other clients) would be at least one send/receive cycle behind in position.
I guess I'm saying just let the client do all the work, figure out where the character is and tell the server, but include enough info that the server can optionally check validity to ensure nobody's cheating.
The cheat detection could even be turned off for performance or set to randomly check.
Note: All collision/position info on objects within traveling range would need to be sent to the client for this to work.
我可以想到有两种方法来做到这一点 - 让客户端向服务器发出命令& 服务器将是最终的地图管理员。
或者,将地图保留在客户端中,& 客户端必须与他们“附近”的其他客户端建立连接才能进行移动,记录保存由服务器和服务器完成。 由一些同行(黑客警察)检查。
我感兴趣的是监视对等连接的可能性,并且延迟超过特定阈值的对等点不会出现在游戏中。
There are 2 ways I can think of doing this - have the client issue commands to the server & the server will be the ultimate map keeper.
Or, keep the maps in the clients, & the clients will have to establish connections with other clients they're "near" in order to do movement, with recordkeeping being done by the server & checked by a few peers (hacker police).
Interesting to me is the possibility to monitor peer connections, and peers that have a latency above a certain threshold just won't show up in the game.
您的服务器是否太慢以至于无法处理所有的移动? 尤其是在二维游戏中? 通常,当我制作小型 2D 游戏时,服务器会返回我的所有动作,因此客户端不需要进行任何计算。 如果服务器开始滞后,我就会冻结一点,这通常是人们所期望的(尽管这种情况几乎不会发生)。
无论如何,我肯定会在客户端不进行任何实际计算的情况下查看性能如何。 如果性能不够好,请查看服务器上玩家移动的循环是否导致延迟(并开始为每个客户端使用不同的线程)。
如果带宽确实存在真正的限制(移动本身传递的数据非常少),那么您当然需要找到该特定用户的平均延迟并将其计算到算法中。 然而,为了不断地找到平均值(为了精确),您必须继续对服务器执行 ping 操作以找到往返时间,这应该不会那么昂贵。
Is your server so slow that it cannot handle all of the movement? Especially in a 2-d game? Typically when I make little 2d games the server gives me back all of my movements, so no calculation is required on the client. If the server begins to lag, I simply freeze up a bit, which is what one would typically expect anyway (although this almost never happens).
In any case, I would definitely see how the performance is without the client making any actual calculations itself. If the performance isn't good enough, see if looping through player movements on the server is causing the delay (and start using a different thread for each client).
If there is indeed a real restriction in bandwidth (movements themselves pass very little data), then certainly you need to find the average delay of that particular user and calculate that into the algorithm. However, to continuously keep finding the average (for precision), you'll have to continue to ping the server to find the round-trip time, which shouldn't be all that costly.