淺談網路遊戲的設計——伺服器端程式設計
本遊戲伺服器端作業系統採用UNIX,因為UNIX是標準的伺服器作業系統,可保證網路遊戲的穩定性。因此,以下所有的程式設計都將針對UNIX進行。 伺服器端的整體構架如下:通訊模組,訊息傳遞模組,遊戲規則模組,執行緒管理模組,遊戲世界管理模組。 通訊模組: 通訊模組主要實現與客戶端的通訊功能,實際上,通訊模組就是對套結字Socket的封裝。Socket是UNIX下的網路通訊基礎,對於一個Socket我們可以對其進行讀寫操作,讀入的資料來自客戶端,寫入的資料可供客戶端讀取。 Socket主要有阻塞套接字和無阻塞套接字兩種,對於無阻塞套結字,每次讀寫後,不管讀寫的位元組數是否達到要求,都立即返回;而對於阻塞套結字,若讀寫位元組數不夠,函式將被阻塞,直到所有待處理的資料都處理完畢才返回。可以看出,若採用無阻塞套結字,則將使網路傳輸變得很不穩定,在網路環境不好時很難控制傳輸。因此,對於我們的系統,將採用阻塞模式。 我們下一個面臨的問題是怎麼知道何時讀入,如果在不合適的時候從阻塞套接字讀入資料,那執行緒很可能將被阻塞,這裡採用了select——多路複用技術,原理是對我們的socket進行監視,如果socket上有讀事件發生,將呼叫訊息模組傳送訊息給socket的攜帶物件,對其進行讀寫。 以下是對Socket的簡單封裝: class SSocket { fd_set *SockSet; //fd_set,也就是我們的select監聽集合 char IsListenSocket; //是否是監聽套接字 int ServerPort; //監聽套接字的監聽埠號 struct sockaddr_in addr; //地址資訊 public: SSocket(); ~SSocket(); int Socket; //socket int CreateListenSocket(fd_set *sset, int Port, char* addr); //初始//化一個監聽socket int AcceptSocket(int listen_fd, fd_set *sset); //初始化一個非監聽socket int CloseSocket(); //關閉 socket int SendBuf(void *buf, int size); //傳送資料 int RecvBuf(void *buf, int size); //接收資料 int SetSocketFd(); //將socket加入到監聽集合中 int ClrSocketFd(); //將socket從監聽集合中清除 }; 通過對socket的封裝,我們完成了通訊模組的基本任務。下一步要做的是傳輸網路上的訊息,此時需要對SSocket繼續封裝,首先定義一個訊息結構體,然後就是讀寫訊息,訊息結構根據各個遊戲不同,在此就不再深入探討了。 執行緒管理模組: 由於我們用了阻塞模式,這就意味著必須要為各個socket建立單獨的執行緒,否則很可能會引起伺服器端停止工作。因此我們需要封裝執行緒,封裝內容主要包括:執行緒函式地址,執行緒開始時間,執行緒上次阻塞時間,執行緒最大阻塞時間,執行緒start方法,執行緒stop方法。執行緒stop方法可以通過傳送訊號給執行緒來達到殺死執行緒的目的。 執行緒類封裝完成後,我們就可以開始編寫管理模組程式碼了。管理模組其實也是一個執行緒,其第一功能就是監視各個執行緒是否阻塞超時,通過察看執行緒上次阻塞時間和最大阻塞時間來完成。一旦發現當前時間超過執行緒最大阻塞時間加上執行緒上次阻塞時間,既可斷定執行緒阻塞超時,此時就需要kill該執行緒。另外,其他一些根執行緒有關的管理方法都有此模組負責。 訊息傳遞模組: 物件、模組之間怎樣傳遞訊息,這也是伺服器端設計的重點。舉一個簡化的例子說明如下:若某一玩家對另一玩家發了一條資訊,先通過通訊模組接收資料,然後用訊息傳遞模組通知另一玩家,再由另一玩家的執行緒呼叫通訊模組把訊息發回客戶端,這就是訊息傳遞模組的作用。 要怎樣封裝訊息模組呢?第一步就是做一個MessageBox類,它是一個堆疊,用來裝訊息,主要由pop和push方法,當然這裡不能忘了必須實現一個儲存訊息資料結構。第二步封裝就是HandleMessage類,這就是我們的訊息模組的主要實現。其中有一個WaitMessage方法,呼叫此方法後,執行緒將被阻塞,直到有訊息到達。在此可通過無名訊號量來實現,也就是UNIX下的sem,它可以增加或減少訊號量來實現互斥。然而,有人一定會問,為什麼我們要有WaitMesssage呢,這不是將造成執行緒阻塞嗎?其實,伺服器端是一個被動驅動的模型,就像沒有踩油門汽車就不會走一樣,如果沒有訊息來驅動,伺服器端就不會執行下去。 實現以上封裝後,在兩個物件之間發訊息就變得很簡單,我們直接用SendMessage方法就可以,SendMessage的實現也很簡單,就是呼叫MessageBox裡Push方法向裡邊放訊息,之後把sem加一,這樣接受這就可以收到訊息了。 其他: 剩下的兩個模組,都是與遊戲相關的,事實上他們是兩個更為複雜的模組,根據要編寫的遊戲的不同,這兩個模組實現也不同。但是,他們究竟是做什麼的,下面通過一個例子來說明: 假設我們現在開發的是一個RPG遊戲,我們的玩家在螢幕上讓遊戲人物向前走了一步,此時傳送移動請求給伺服器端,伺服器端的通訊模組收到後,便通知遊戲世界管理模組,遊戲世界管理模組呼叫遊戲規則模組,判斷玩家請求是否符合規則(是否合法),若可以移動,再由遊戲管理模組將其座標改變,最後再通知其相關玩家。也就是說,規則模組實際上是專門處理遊戲業務邏輯的,管理模組實際上是專門處理遊戲物件的。 小結 網路遊戲的開發入門是挺難的,實際上,本文只能起到拋磚引玉的作用,僅告訴大家一個入門的方法而已,剩下的,還有那煩人的一行一行實現程式碼。
首先,再次強調一下,網路遊戲開發極為困難,技術含量相當的高,其程式設計知識涉及網路程式設計,作業系統程序、執行緒程式設計,圖形影象程式設計(DirectX / OpenGL),WIN32 API程式設計(Windows下開發),以及各種演算法和資料結構,同時對設計人員策劃能力要求也頗高,如不能構思出一個吸引玩家的遊戲世界,也必將導致開發失敗。 目前,國內的網路遊戲市場被韓國遊戲霸佔,情形讓人心寒。在國內網路遊戲程式設計資源奇缺的環境下,我希望把自己的一些經驗和想法說出來,供大家參考,起一個拋磚引玉的作用。 對於我在淺(1)中提出的架構,如果大家有更好的修改建議,歡迎大家共同探討修改,把我國的網路遊戲開發水品提高到世界級標準。最起碼,也要在國內市場是立足! 好了,費話就不多說了,正文開始。 在淺(1)中,關於遊戲世界管理模組和通訊模組我沒有詳細說明,本篇中將補充介紹。 遊戲世界管理模組: 本模組專門管理遊戲世界裡的資料模型,也就意味著,所有遊戲裡的物件基本上都由他來管理所以,此模組極為複雜,甚至在大型系統裡,也可以把它再劃分成很多子模組來協同工作。 這個模組該怎麼封裝呢?首先,自然是需要一個訊息處理類,因為遊戲世界管理模組同樣是需要訊息驅動的,此模組每收到一個訊息後,就察看訊息型別,看是轉發型別還是管理型別的訊息,如果是轉發型別,就將訊息轉發給訊息目的地模組,如果是管理型別的訊息,就察看管理的目標以及管理的方法,然後執行管理方法。因此,我們還需要的就是一個辨別訊息的方法,以及一些資料及操作資料的方法。 遊戲規則模組 本模組按照遊戲策劃者制定的規則來進行業務邏輯處理。同樣,首先需要封裝的也是訊息處理類。然後就是辨別訊息,按照訊息提示進行規則處理,隨後就是將處理結果封裝成訊息,發給管理模組,基本上與遊戲世界管理模組模式相同。 以上談了兩個模組的封裝思想,但是,實際上,這兩個模組是不可能像上面寫得那樣運用的,很多朋友也談到這個構架並不適合作大型網路遊戲,那麼,真正的大型網路究竟是怎樣的架構呢? 就像我們的OSI模型和TCP/IP模型一樣,只有後者能真正運用在工業標準中,前者固然是好的,但是他封裝得太細了,太過於複雜了,不適合現在的情況使用。在真正的網路遊戲中,以上的兩個模組是合在一起的!我把它們統稱為遊戲世界模組。請大家注意看下面這個模型(發了幾次圖片都失敗了,所以用文字弄了一個,請諒解) 客 戶 端 通訊模組 遊戲世界模組 | | | | 傳送internet訊息 | | | ---------------------a | | | |──┐ | | | | 解包 | | |<─┘ | | | 傳送訊息 | | | --------------------- > | | | (通過訊息模組) | | | |──┐ | | | | 規則判定 | | |<─┘ | | | | | | ──┐ | | | | 修改遊戲世界 | | 傳送訊息 | <─┘ | | <---------------------- | | 傳送internet訊息 | (通過訊息模組) | | <------------------------- | | | | | |
補充日期: 2004-02-01 18:28:34
續,沒發好 首先,再次強調一下,網路遊戲開發極為困難,技術含量相當的高,其程式設計知識涉及網路程式設計,作業系統程序、執行緒程式設計,圖形影象程式設計(DirectX / OpenGL),WIN32 API程式設計(Windows下開發),以及各種演算法和資料結構,同時對設計人員策劃能力要求也頗高,如不能構思出一個吸引玩家的遊戲世界,也必將導致開發失敗。 |
補充日期: 2004-02-01 18:31:10
本系列文章始終以淺談二字開頭,所以內容簡單,不夠深入,希望大家諒解。 但是,正如人類的學習過程一樣,是一個由淺入深的過程。市面上很多昂貴的圖書都喜歡用深入XXXX,或者XXXX內幕揭祕之類的題目,其實大家看了以後,感覺他們又何嘗不是淺談呢。為什麼會有這樣的感覺,因為人類的思維是發散的,特別是科技含量較高的領域。我們的知識,都是在前人的基礎上繼承過來的。就像我們的面向物件程式設計一樣,如果我們照搬,那就不是繼承了,直接例項化就行了,只有在交作業的時候,我們才會把書上的東西照抄。要繼承,就得自己編寫一些新的方法,甚至有時候需要覆蓋一些方法,這才是開發研究的真正涵義。 所以,我的文章只是一個基類,給大家拋磚引玉,讓大家自由繼承,甚至很多東西也只是一個虛擬函式,好的架構,好的實現,靠大家自己。希望各位開發出經典遊戲以後,別忘了免費給我幾個月的點卡玩玩。 這次先不談技術問題,先談談怎麼策劃網路遊戲(離伺服器端程式設計越來越遠了,呵呵)。 網路的遊戲構思 遊戲寫得好,絕對不是因為技術用得好,舉個簡單的例子,假設我們現在策劃了一款非常不錯的網路遊戲,就算因為技術問題能支援的同時線上使用者很少,也同樣能夠贏得市場,只要加上幾臺伺服器就行了;但反過來,策劃不好的遊戲沒人玩,那就一定沒市場,此時,我們具備高超程式設計水平的技術人員就白辛苦了。當然,我這樣說的目的並不是要大家忽視技術,只是想讓大家重視遊戲策劃而已,因為我發現有時候我們的很多程式設計高手太過於注重技術細節,反而忽視了市場這個我們賴以生存的重要因素,忽視構思、策劃,就等於忽視市場,後果可想而知。 構思哪裡來?創意怎麼找?最簡單的辦法,多找幾個玩家聊聊,最好就是身邊的好朋友。只要你要善於捕捉他們的思想閃光點,就一定會有重要發現。 什麼樣的創意才是好創意?我問了很多人它們的創意是什麼,大部分都是一來就說:應該做一個完全模擬現實世界的真實的遊戲世界!何其偉大創意構思啊,可惜,用不了。股市裡有一名言:“和別人一樣的話是很難賺到錢的”,意思是說大家都這樣操作,你也這麼操作的話就別想賺錢了。因為市場是殘酷的,歷來只有少數人會勝出,既然這個想法大家都能想到,那遊戲公司的策劃高手又怎麼會不知道呢,程式高手又怎麼會寫不出來呢?這個構思的失敗的原因很簡單,就因為它沒有吸引玩家玩下去的地方。 一個網路遊戲是否能夠成功,就看它是否能引入一種遊戲規則,讓玩家一上手就覺得自己不得不不停的做一件在他認為是很有意義的事。上面這句話是有點拗口,不過我想不到更好的表達方式了,大家多讀幾遍一定能讀懂的。這個規則有很多辦法實現。最常用的辦法就是引入一個競爭系統,因為只有競爭,才能激起人的奮鬥慾望,才能讓人把money和time大量的花在上面。這個系統的競爭規則,應該是相對一致的,就是說不同的玩家之間競爭的東西應該是一樣的,比如,目前的網路遊戲大多引入的競爭基本上是等級競爭,裝備競爭,為了更高的級別,為了更好的裝備,玩家可以不停的作一些枯燥的事。而我們上面那個虛擬現實世界想法失敗的根本原因,就是因為它的競爭系統不明確。玩家的人數是有限的,但是相對於這樣的遊戲人數來說,那麼大的一個系統,競爭的目標卻是無限的,玩家可以選擇的目標太多了,以至於玩家之間沒有了比較的方法,我不知道我玩了一天和他玩了一年到底是誰厲害,因為我們的屬性根本不一樣,假設遊戲裡有教師和學生兩種職業,到底是教得好,還是學得好,在教師與學生之間根本比不出來。我們只能在教師與教師,學生與學生之間比。如果是要模擬現實世界的話,必然出現成千上萬的競爭機制,為了能分出個高下,大家最終將會自然而然的集中到少數幾個競爭機制上來,那就意味著,其他的競爭機制白做了,還不如把遊戲簡化,專門做這幾種競爭機制,那樣會更好。那麼,競爭機制越少越好嗎?那也不一定,競爭機制太少的話,遊戲有時候也會缺乏樂趣,這個,就是體現策劃功底的地方了。 下面我們看幾個例子。 首先是經典遊戲DIABLO 2,要研究一個遊戲的競爭系統,第一步要做的就是看玩家玩這個遊戲大部分的時間是花在什麼上面,答案是:找裝備;其次再看看在這個遊戲裡什麼樣的角色是最值得崇拜,答案就是裝備好的玩家,等級高的玩家在這個遊戲裡並不值得崇拜,錢多的玩家也一樣,因此,我們可以斷定,此遊戲就只有一個競爭系統:物品競爭。由於這個競爭系統做得過於完美,所以,他只要一個競爭系統,就足夠了! 傳奇裡,大家花時間最多的事就是練級,或者找裝備,由此可見,此遊戲的競爭系統就是這兩樣。 UO裡,大家花時間最多的事情是什麼,不一定,有的是練級,有的是PK,有的是打礦石,有的是其他,所以可見,UO引入了一個多種競爭機制的系統,但是,仔細體會又會發現,這個“多種”其實並不是很多,而是在一些傳統系統上進一步擴充套件,多了幾個職業。 有人可能會問,那聯眾的競爭機制又是什麼呢?乍一看似乎很難下手,不過,我們仍然運用上面的方法來分析。大家把時間花在什麼上面?打牌下棋,可見,他直接引入了早已成熟了幾百年的競爭機制,他的成功就在於直接把現實中吸引大家的規則引入到了遊戲中。所以自然大受歡迎。 由此可見,做一個成功的網路遊戲,可以先把遊戲背景定下來,也可以以後再定,但最重要的是要想好應該採用什麼樣的競爭系統,不管引入一種還是幾種,一旦確定後,就要考慮怎樣讓遊戲世界更好的體現出你的競爭系統。如果一開始不確定競爭系統,而是一開始就深入構思整個遊戲世界,那就會面臨很大的市場風險了。 下面舉個策劃的例子:某天,我靈機一動,決定採用money競爭機制,於是我開始確定遊戲背景,古代?現代?未來?虛幻世界?我個人覺得現代似乎更容易體現這個競爭機制(這可不一定),下一步就是怎麼體現這個競爭機制:為什麼要有錢,有錢可以幹什麼,我得到錢的方法是什麼。於是,我就可以引入一些現實世界的賺錢手段,並規定開始我只能賺很少的錢,等我錢多了,就可以賺大錢,圍繞著這些想法,我們就可以構建出一個又一個的遊戲世界。當然,我現在只是舉例子罷了,其實對於這個遊戲世界,我並沒有什麼很好的想法,如果有朋友有,可以來信共同探討。 在想要策劃一個網路遊戲之前,一定要徵求玩家的意見,雖然很多人會說他想虛擬現實世界,對於這樣的回答,你可以開導他,告訴他你只想做一個簡單的遊戲世界,然後他就會慢慢縮小這個遊戲世界,最後你一定能發掘出他思想裡的競爭機制來,此時,你就得到了這個玩家思想的精華部分了(是不是太壞了,呵呵)。當你得到了很多精華的思想後,就可以做選擇了,找出那些有市場的創意來(這也是很難的一件事,看策劃者的眼光了),然後就用策劃例子裡的方法,逐步制定出整個遊戲世界,剩下的就是寫出詳細策劃。 遊戲策劃完成後該怎麼辦?當然是編碼了,雖然本篇中始終沒有談到技術問題,但是開發人員的技術水平是不可忽視的,如果水平不夠,遊戲都寫不出來,那我們的策劃師又白辛苦了。 由於沒有政府扶持,中國現在的遊戲開發現狀就是,很多開發小組裡的人員大多既是策劃師,又是程式設計師,甚至還是美工,更有甚人還要負責市場(民間開發小組裡這種情況比比皆是)!看看韓國,網路遊戲程式設計技術由政府出馬研究,各大公司直接拿過來用!也就是說,在某種程度上,韓國只要把策劃搞好就行了,這才是真正的政府扶持! 小結 看完本文後,各位有什麼想法,也許有人會說,空談理論!確實,本文太理論化了,而且又沒有談技術,所以很不合程式設計師的胃口。 但是,不管怎麼說,我希望程式設計師能把眼光看遠點,把目光從技術向市場轉移,把本文看成一個基類去繼承,去新增大家自己的方法,去覆蓋不夠理想的函式,最後再把大家的成果讓別人去繼承,這樣下去的話,我們國家的網路遊戲水平肯定能夠達到一個理想的高度! |