2011-05-09 52 views
10

嗨我已經寫了一個Java遊戲,我想知道我需要學習什麼和/或什麼我應該使用遊戲可通過網絡或多臺計算機在互聯網上播放。對於從哪裏開始,我真的很無助,所以任何建議都會有幫助,謝謝。製作可通過網絡或互聯網播放的多人遊戲

+0

遊戲如何支持當前狀態下的多人遊戲功能?它是否使用套接字與同一臺計算機上的多個實例進行通信? – 2011-05-09 14:52:08

+0

不,它只是基於輪流,但我想這是我需要做的事情之後,我可以把它通過網絡播放? – 2011-05-09 14:53:41

+0

多人遊戲意味着多個用戶玩同一個遊戲,並且遊戲中的玩家之間有一些互動。你說你的遊戲「基於輪流」。它是多人遊戲嗎? – 2011-05-09 14:56:20

回答

1

如果您想通過網絡添加多人遊戲功能,請查看Netty project以構建通信基礎結構,這可能會對您有所幫助。

但是在你做到這一點之前,你需要確保你的遊戲擁有正確的「架構」。您需要使用大型模塊:客戶端和服務器。

服務器負責所有的遊戲邏輯。從某種意義上說,它是遊戲引擎。客戶端負責向服務器查詢遊戲狀態,將其顯示給玩家,獲取玩家輸入並向服務器發送命令。

一種解耦我們的客戶端和服務器代碼的方法,不需要學習網絡編程的麻煩,就是有兩個不同的程序可以從CLI運行。執行的順序可以是這樣的:

  1. 服務器運行初始化遊戲狀態,遊戲狀態保存在文件中。
  2. 客戶端正在運行,它讀取遊戲狀態,以某種方式顯示它並從玩家處獲得一些輸入。它將輸入保存到文件中。
  3. 服務器運行時,它從客戶端讀取命令,更改遊戲狀態並更新狀態文件。

沖洗和重複。這基本上是PBEM服務器所做的。

爲了幫助脫鉤的客戶端和服務器,是有意義的定義「語言」來表示在遊戲中的狀態變化,並命令由服務器執行。它有助於客戶端緩存狀態並應用從服務器發送的更改。

一旦你的客戶端和服務器的代碼完全解耦,並在「語言」是完全定義,你就可以改變被基於文件的,以作爲插座爲基礎的通信機制。

1

一種可能的架構方法是讓遊戲的一個實例充當主機(例如,第一個啓動的實例)。它會協調遊戲併發送遊戲狀態信息並轉向其他每個玩家。

當玩家走棋,它會發送移動信息給主機,這將更新遊戲的狀態(並檢查移動的有效性等)。然後,它會將新的遊戲狀態發送給每個玩家,並且還可以(可能作爲單獨的通信)向下一個轉發通知適當的客戶端並等待其響應。

在某種意義上,主機充當這種情況下,遊戲服務器,但可能是簡單的使用/起到不存在必須以玩遊戲上運行一個單獨的進程。

40

那些其他的答案都是相當高的水平,這是好的,但你不希望高層次,你想低層次的,如「我怎麼讓它實際發送的數據和什麼意思以及我發送了什麼等等。「這裏是你做什麼:

首先,TCP或UDP?如果你不知道這些東西是什麼,請閱讀它們,因爲我沒有空間在這裏給出一個很好的概要,但爲了你的選擇知道以下內容:

  1. TCP很好對於基於回合的遊戲或高延遲通常可用的遊戲,由於TCP確保數據包傳輸,因此可能需要一段時間才能重新傳輸丟棄的數據包。這對國際象棋或其他任何輪流的事物都很有好處。
  2. UDP適用於那些不一定關心消息可靠性的遊戲,並且寧願數據只是繼續發送,如果你錯過了某些東西,哦。這對於基於實時動作的遊戲(如HALO:Reach或Call of Duty)非常有用。在那些場合,如果你發送一個對象的位置,並且對象永遠不會到達那裏,那麼發送一個新位置比重新發送一箇舊位置更好(現在更舊),所以保證可靠性並不重要。也就是說,你必須有某些東西是100%可靠的,所以你仍然需要某些東西來保證交付,比如對象創建和對象銷燬。這意味着您需要在UDP之上實現您自己的半可靠,基於優先級的協議。這是困難的。

因此,問問自己什麼是重要的,瞭解TCP和UDP如何工作,然後做出明智的選擇。

也就是說,現在你必須在整個網絡上同步對象狀態。這意味着您的對象需要序列化爲可以用字節流表示並寫入套接字的內容。寫入套接字很容易;如果你可以寫入一個文件,你可以寫入一個套接字,這真的不難。重要的是確保你能夠將一個對象表示爲一個緩衝區,所以如果你的對象有引用/指向其他對象的指針,你將不能發送這些指針,因爲它們在其他客戶端上不同,所以你必須將它們轉換爲所有主機共有的東西。這意味着ID,儘管對象的ID在所有主機中必須是唯一的,所以必須有一種方法來在主機之間進行協調,以便兩臺主機不會創建具有相同ID的不同對象。有辦法處理這樣做的主機,但我們不會擔心在這裏(提示:使用主機的ID和網絡ID之間的某種映射。更大的提示:不要這樣做,如果你不需要)。

所以,現在你可以發送數據,很好,現在呢?每次遊戲狀態發生變化時,都必須以某種方式向其他機器發送更新。這就是客戶端 - 服務器體系結構進來的地方,或者如果你願意,也可以是點對點的。客戶端 - 服務器更容易實現。另外,作爲服務器的一臺主機仍然是客戶端服務器,任何不同的人都是錯誤的。

所以,服務器的責任是「擁有」所有的遊戲狀態。只有服務器可以明確地說出一個對象的狀態。如果你想移動一個對象,你告訴服務器你想移動,但是服務器然後告訴你應該移動對象,你不只是做到這一點(雖然某種客戶端預測通常很有用)。服務器將更新的對象狀態發送給所有其他主機。

所以,你提到了一個回合制遊戲,對吧?非常簡單:

  1. 你打算解決一個完全打開客戶端的問題。一旦該客戶端做了他們想做的事情,將該輪次的結果發送到服務器。然後,服務器驗證客戶端的動作(不要僅僅信任客戶端,以這種方式發生作弊)並將其應用於其對象狀態。
  2. 服務器一旦達到最新狀態,就會將消息發送給具有新狀態的每個其他客戶端,並且這些客戶端將應用這些更新。這包括剛剛輪到的客戶;客戶端應該只在服務器告訴它時更新它的世界狀態,因爲你想確保與其他主機的一致性,並且你想防止主機作弊。
  3. 服務器然後發出一條消息,指出它是哪個人。您可以在上一步中的世界狀態更新的同時發送此信息,那很好。只要注意客戶試圖停止秩序。這就是爲什麼服務器擁有全世界的權威。如果一個客戶試圖欺騙,服務器可以把它們打倒。

這就是所有你需要做的回合制遊戲。提示:使用TCP 更大的提示:TCP實現了一種叫做「Nagle's Algorithm」的東西,它將把你的消息組合成一個包。這意味着如果您發送兩個單獨的消息併發送兩個單獨的「發送」消息,其他主機可能會在一次調用「接收」時只接收一個數據包,但該數據包將包含「發送」的兩個內容已發送的數據包。因此,如果您發送兩個100字節的數據包併發送兩個呼叫,則您可能會在一次呼叫中收到一個200字節的數據包以進行接收。這很正常,所以你需要能夠以某種方式處理這個問題。一個技巧是讓每一個數據包的大小相同,然後在每次檢查輸入時從套接字讀取許多字節。請記住,你也可以得到部分消息。例如,如果您發送兩個100字節的消息,則它們可以組合成一個200字節的消息。接下來,如果您從另一端的套接字讀取數據,但您使用150字節的緩衝區大小讀取,則會有150字節,其中包含第一個數據包和第二個數據包的一部分。您必須撥打第二個電話才能收到第二條消息的剩餘部分,因此請保持跟蹤您收到的數據量,以便在某處不會丟失數據包的一部分。這就是爲什麼保持你的數據包相同的大小是有用的。

還有一些其他有用的技巧可以減少消息的大小和頻率,並且可以跟蹤不是基於回合的遊戲並且能夠實時行動,但是如果您有回合制遊戲,那麼正確的做法可能是使用TCP,而不用擔心任何其他的東西。這裏有一些鏈接有用的網站和文章,這將使你在遊戲網絡編程是怎麼做的更多信息:

  • Glenn Fiedler's site,這裏的一些偉大的信息。
  • 1500 archers,關於如何實現一種稱爲確定性鎖步的技術的一篇很好的論文,對許多類型的遊戲都很有用。

讓我知道你是否想了解這些東西的更多細節,或者如果你有更具體的問題。