2009-06-30 60 views
8

我一直在写一个2D闪存多人游戏和一个套接字服务器。我原来的客户端和服务器之间的运动算法如下:客户端 - 服务器多人(MMO)游戏中的运动“算法”?

  • 客户端通知服务器关于播放器的移动模式或者右转),只要这些改变。
    • 服务器每隔几毫秒循环播放所有播放器,并根据时间差异计算转角和距离移动的角度。客户端完成相同的计算。

我的电流计算为客户端(相同的数学在服务器中使用)==>

车削

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)]; 
     } 

这似乎很好。为了考虑滞后,服务器通过发送这些数据来纠正客户端的信息。

这个系统使用很少的带宽来处理移动。但是,我的服务器和客户端的坐标和角度之间的差异太大。我是否应该扩展我的“算法”,同时考虑到用户的延迟?还是有更好的方式来处理客户端运行效果很好的服务器多人游戏?

回答

6

我的初始设计与您的初始设计相似,但如果这样做不起作用,或许您可以让客户端做所有的动作,并让服务器进行一些范围检查。

因此,如果您上次报告的位置是X,则下一个位置必须位于X的半径内,其中半径基于客户端发送的时间戳与x,y数据的差异。

大部分情况下,这只是检测作弊。

停车,打架,等需要的位置与攻击一同发送,客户端发送的更新后的那个位置,但将基于服务器的位置由触发的动作只会被触发。

不知道这会帮助太多,但它可能会停止颠簸重新同步,你会从你最初的算法见。

评论回应:

没有,客户仍然会告知其位置的服务器,但是服务器不会尝试计算下一个位置。这意味着服务器(和所有其他客户端)至少会有一个发送/接收周期滞后。

我猜我说的只是让客户端完成所有的工作,找出其中的字符,并告诉服务器,但包含足够的信息,该服务器可以选择性地检查的有效性,以确保任何人的作弊。

作弊检测甚至可以关闭性能或设置为随机检查。

注:上行驶范围内的所有物体碰撞/位置信息需要被发送到客户端这个工作。

+0

如果所有客户都必须通知所有其他客户他们当前的位置,服务器是否不得不继续接收并重新发送大量消息? – Tom 2009-06-30 22:28:22

0

您的服务器速度太慢,无法处理所有动作?特别是在二维游戏?通常,当我制作小型2D游戏时,服务器会将我的所有动作都给予我,因此客户端无需进行任何计算。如果服务器开始滞后,我只是简单地冻结一下,这正是人们通常所期望的(尽管这几乎从不发生)。

无论如何,我肯定会看到如果客户没有做出任何实际的计算,性能如何。如果性能不够好,请查看循环播放器在服务器上的移动是否导致延迟(并开始为每个客户端使用不同的线程)。如果确实存在对带宽的实际限制(运动本身传递很少的数据),那么当然你需要找到该特定用户的平均延迟并将其计算到算法中。但是,要持续查找平均值(精确度),您必须继续ping服务器以查找往返时间,这不应该花费太多的代价。

+0

这不是一个小小的2D游戏。它应该同时处理数百名玩家。我需要最优化的系统。 – Tom 2009-06-30 21:32:34

+0

嗯,在这种情况下调整服务器,以便发送数据足够小的间隔将不得不做。当然,所有服务器都需要某种类型的玩家上限,但至少会在客户端移动方面增加10-20毫秒的延迟。这几乎不明显,应该在大多数情况下与球员的实际位置相对应。 – AlbertoPL 2009-06-30 21:41:43

1

有2种方法我能想到这样做的 - 在客户端发出命令到服务器&的服务器将是最终的地图门将。

或者,保持客户端的地图,&客户将不得不建立他们为了做运动,有记录保存“近”由几个同行检查服务器&正在做其他客户端的连接(黑客警察)。

让我感兴趣的是监控等连接​​的可能性,并有超过一定阈值的延迟同行就不会在游戏中出现。

相关问题