Posted on 2011-01-19 19:18
點點滴滴 閱讀(1101)
評論(0) 編輯 收藏 引用 所屬分類:
10 服務器
其中game工程生成的庫文件game.lib居然有近四百兆之巨,mangosd和realmd在連接這個庫的時候也要花上好長一段時間。當然,mangos現在的代碼量也確實不少了,這也就要考慮到大的工程項目的源代碼管理及模塊工程劃分,至少,像mangos現在這樣,代碼全部放入game目錄中,并且就做為一個大的工程的方式,其弊端是已經顯現了。另外還有功能模塊劃分的問題,需要找一個功能的實現時,不知道該到哪塊代碼去找,而要擴展某部分功能時,也是無從下手。
模塊劃分使用最廣泛也是最容易實現的應該算是按接口編程了,實現的方法不用我多說,程序員都知道。其好處也是顯而易見的,定義了接口之后,接口的實現便可以作為一個獨立模塊,也就可以單獨為一個工程了。
可以拿mangos處理玩家登錄的過程來做個比方,現在mangos的做法是一個很長的順序執行的過程,如果玩家在隊伍中,則向隊友發送上線消息,如果玩家有好友,則向好友發送上線消息,如果玩家有公會,則向會員發送上線消息,等等。這些代碼都是直接調用各功能部分的代碼來實現,如果這里考慮一下模塊劃分,并定義出相應的接口,那就可以改成調用好友模塊的上線處理接口,調用組隊模塊的上線處理接口,調用會會模塊的上線處理接口,等等。
有了接口后,這幾個模塊可以在另外的工程中實現,不用再混在game工程中。對象通過定義好的接口來調用,這樣只要沒有改動接口,模塊的實現修改都不會影響到game工程。
還可以再進一步,在游戲邏輯的處理上再做一些解耦合。還是上面這個例子,玩家在登錄時,先調用組隊模塊接口,再調用好友模塊接口,再調用公會模塊接口......這些順序的執行過程將這些模塊緊緊地耦合在了一起,當游戲邏輯變得越來越復雜時,類似的接口及調用數量會呈爆炸式的增長,這也將會成為另一個巨大的問題。
一個可行的方法是使用被稱作事件或者信號的對象來實現解耦合。仍然拿上面的例子來說,當玩家登錄成功時,玩家對象發出一個“玩家已登錄”的事件或者信號,對此事件感興趣的模塊,會響應這個事件并且做出相應的邏輯處理,具體來說就是好友模塊會向該玩家的好友廣播上線消息,組隊模塊會向該玩家的隊友廣播上線消息,公會模塊會向該玩家所在的公會廣播會員上線消息,等等。注冊感興趣的事件及響應事件的處理過程都是在各獨立模塊內部完成,玩家對象本身并不知道也不需要知道有這么些過程。這樣,想要刪除或者擴展功能就比較的方便了。
sigslot這個開源庫就提供了我們所要的這項功能。在玩家對象內部定義一個Signal對象,功能模塊從has_slot派生,并且將自己連接到玩家對象的signal對象上,這樣當玩家對象的signal對象被emit時便會調用到該模塊內。在收到這個信號時你可能還需要一些參數,至少應該知道到底是誰登錄了吧,沒關系,signal中可以帶任意多個參數,完全由你來控制,但遺憾的是他的slot不支持返回值。如果你不能容忍這樣大的一個功能缺失的話,boost::signal或許可以滿足你的要求,但太過于復雜的東西我一向不大喜歡,boost就屬于這一類,雖然他非常的強大。
還有一個可考慮的選擇是FastDelegate,不過你得自己做一些封裝才能實現我們上面提到的類似功能。雖然FastDelegate基本上只是實現了一個安全的回調函數的功能,但是自己封裝出來的東西或許更適合你的需求,也可以試一試。