2009-06-30 101 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種方法我能想到這樣做的 - 在客戶端發出命令到服務器&的服務器將是最終的地圖門將。

或者,保持客戶端的地圖,&客戶將不得不建立他們爲了做運動,有記錄保存「近」由幾個同行檢查服務器&正在做其他客戶端的連接(黑客警察)。

讓我感興趣的是監控等連接​​的可能性,並有超過一定閾值的延遲同行就不會在遊戲中出現。

相關問題