Silverlight C# 游戏开发:游戏循环体的五种设计方式
我們在游戲設計和開發中,尤其是引擎開發中,邏輯循環是一個重要組成部分,循環決定了游戲的基礎邏輯和運行方式,在不同的開發環境和語言下,對于循環的釋義甚至相差甚遠,那么我想和大家分享的是在Silverlight游戲開發中,循環的設計方式和做法。
以下內容來自以往的游戲開發經驗,可能在其他語言中的相關文章更加詳細,謹在這里討論有關在Silverlight游戲開發中的應用。
特別提示:如果你的《數據結構》學的不好,不要看,你會吐飯,如果你的《數據結構》學的很棒,不要看,你會吐血。
在傳統的開發觀念中,無論任何開發環境,它都逃不出While,代碼一般是這樣:
?
那么在Silverlight游戲開發中,我們是否也可以這樣應用呢?道理上差不多,但是只是實現了一個根(Root)部,這方面深藍色右手以及很多其他朋友都有了各種各樣的解決方案,有興趣的朋友可以找他們的文章,無論是用線程(Thread)、故事板(Storyboard)、Rending、DispatcherTimer,都是一個好的循環體的開始。那么我們是否到底在游戲產品(或者叫成品更加貼切)的角度考慮更加深層的細節。
對于游戲而言,尤其是網絡游戲,我們將面臨著大量的交互,這些交互可能來自用戶,也可能來自自身的游戲邏輯,其他的都好說,最現實的問題是,當一個游戲的同屏幕呈現100個以上的角色的時候,我們的循環是否因此而“卡”住,在早期的時候,我陷入了一個誤區,呈現足夠多的角色就是最大的性能體現(能呈現600個角色不卡),現在看來卻是不然,因為單純的角色呈現,有幾百個不算什么,當在一個整體游戲的執行時候,它是否還能保持足夠的流暢,因為我們的戰斗邏輯、界面邏輯、場景管理器無時不刻在消耗著系統資源,而此時的角色也絕非幾張圖片那么簡單,他們身上的裝備、部件、特效都將成為游戲開發者的負擔。
在此種情況下,優化循環過程相當重要,作為團隊經驗積累,今次拿出來大家一起研討,看看是否這么回事,有什么好的想法和建議歡迎一起交流一下:)
針對于在一個游戲整體下的部分,用到循環最多應是動畫,對此,我總結了在Silverlight游戲設計中能應用的五種循環方式,這些方式在傳統的游戲開發中是非常常見的,只不過沒有人愿意拿出來分享,兩個原因:第一、太簡單,講出來怕笑話,第二、太神秘,我們要將其封裝起來,這樣才能忽悠人,下面的五種循環設計模式名字自己亂起的不好,還請見諒。
那么好,我們設計一個場景:有一個OBJ內部有一個LogicLoop的方法,內部實現了最簡單的它會切換動畫幀,并且向一個方向走,走到底會從頭繼續走。而場景中有非常多的OBJ。
一、自身式循環
自身式循環比較容易理解,比如一個精靈控件,自己內部實現一個循環,來不停的檢測和執行邏輯,開發者都不需要去單獨做什么,只需要new出來它們自己就會執行邏輯了,這種方式非常便捷和方便,開發起來也相對容易,互相之間沒有任何關系,此時需要借助單例之類的設計模式來解決互相的結合問題。圖示如下:
?
很顯然,我們自身邏輯有一個最大的問題是獨自的性能占用,如果一個場景(不是同屏)有幾百個這樣的循環時,那么游戲各個線程就會吃掉大量的CPU,尤其是用Thread、Storyboard、DispatcherTimer的時候。
?
二、鏈條式循環
自身邏輯存在各自的循環消耗問題,那么有沒有辦法將各自的循環邏輯統一到一個循環中呢,如果學過數據結構,我們可以透過鏈表的形式來做,基本的原理是將各個循環體放入到一個大循環中,然后從第一個開始執行循環邏輯,只執行一次,然后下一個,到底以后回來繼續執行,模型如下:
這是一種常見的處理方法,能夠大大降低系統消耗,而且C#提供了迭代器等好用的遍歷,使得我們結合面向對象的思路更方便。示意代碼如下:
鏈條式循環最大的優點是將所有的獨立循環全部集中到一個大循環中,需要注意的有一個問題,那就是動態處理,因為游戲當中的物體生成和銷毀是非常頻繁的,正在循環的時候發生了集合改變,那么就危險了,我們的做法有兩種,分別是數組轉換和回收判斷,數組轉換非常容易,將集合拷貝到一個數組中,然后循環數組的各個元素;回收判斷是通過標識將物體摘出到一個回收列表中,然后在安全的時機清理。
鏈條式循環的優點可以創造一個游戲的RootHead,將所有的元素加入到這個RootHead當中,創建一個主循環然后遍歷即可,當然了,你需要通過基類的方式來達到目的。
這是一種好的方式嗎?在某種情況是的,它能解決性能損耗,當然了,要是內部實現的邏輯過于復雜,有的時候可能還得借助一下另外線程。但是,在游戲產品中,有一個更加直接的需求,那就是系統問題,也就是說,你的循環到底有多足夠大才能讓包容一切,比如場景管理中的場景物體,如果有邏輯循環就直接加入到這個大循環中嗎?在游戲運行時,有一些循環在特定的時候是不需要使用的,或者不需要執行的,也為后續開發造成了障礙,所以,在我們的MMOROG引擎中,最多應用是下面的這種循環模式。
三、子樹式循環
?
子樹循環顧名思義,使用樹狀結構來處理循環邏輯,我們實際應用中還有可以分為:活動子樹式循環和固定子樹循環,為了方便講解,主要講固定子樹循環的模式。
我們知道在一個游戲中,有很多的系統,比如場景系統、戰斗系統、隊伍系統、公會系統、聊天系統……N多系統,它們自己內部是否有一個循環呢?如果從直觀角度上,上述系統可能不需要循環,但是事實不然,比如隊伍系統,可能為了完成組隊、移動等行為,專門有一個循環來處理判斷邏輯,雖然這個邏輯很簡單,再比如公會系統是否有每10秒鐘刷新一下公會列表的需求……
?
?
如上圖所示,我們利用子對象的方式創造一顆樹,然后逐一進行遍歷,在執行過程可以使用迭代,也可以使用遞歸,不管那種方式,對于子樹而言沒有太大的區別,但是對于性能而言,我們可以做一些有趣的優化,當一個系統關閉的時候,它在樹中就不執行了——具體用什么方法,看情況而定,無論是拆枝還是邏輯判定都行。我們得到的效果是,關閉的子樹下面的元素也不會執行循環,多么簡單,比鏈條式的容易多了,一斷全都斷。
子樹式循環在常用系統級別非常常用,對于那些比較頻繁的更換的邏輯比較實用,比如特效動畫、地圖系統等等,具體的算法和操作在《數據結構》中有明確的答案,可以在其中找到想要的東西:)。
?
四、區間式循環
區間式循環嚴格意義上是循環中的一個判定方式,而不是實現模式,原理是將游戲系統各個部分拆分開,掛入不同的循環結構中,如果說鏈條式和子樹式是一種Object集中,區間式可以說是一種Objects集合打散,釋義圖如下:
?
區間式在大系統級別,可以分拆最消耗性能的部分,到另外一個線程(或循環結構)中完成循環,比如說戰斗系統、地圖處理、場景管理器,而場景管理器下也可以帶入一個區間式循環,將場景分割,然后對一個區域范圍的物體進行處理(如果想想上面的圖是否可以做成一個二維數組呢?),對于超出區域和不在區域范圍內的循環邏輯完全視而不見,否則的話,要處理一片大場景中的N多個角色,無論是在自身、鏈條、子樹都會一筆不小的開銷。
區間式最大的優點是加強了范圍判定,如果寫的好,還可以多重結合,使用二維(三維也行)數組完成各個需要循環邏輯的分配,將不需要的拆分出去,這里的算法可能稍微有點意思,類似哈希和List的結合,要注意的是當一個物體(OBJ)從區間1到區間2的時候,會發生什么事情:)
五、組合式循環
其實組合式循環是一個非常偷懶的部分,因為組合的是前四種而已,在游戲開發中,并不是上述的那種方式最好,而是因地制宜,什么樣的模式滿足什么樣的需求,不能只是單純為了達到高效而高效,更加要注意未來開發的順利程度,避免返工。
?
如上圖所示,我們可以很清楚的分析不同循環方式在不同的環境下的應用:
自身式循環比較適合界面,因為比較固定,而且復雜邏輯不多,當然了這只是在Silverlight的UI當中比較適用,其實主邏輯就是一個很大的自身循環,Root的循環方式就是一個自身式循環。
鏈條式循環比較使用與第二級的游戲系統,將系統全部串起來,以達到快速遍歷目的,但是在系統的下一級,就是子樹式循環,系統元素全部在一個系統下,下面的子樹中也可能會出現鏈條式,很顯然是一種最頻繁的組合方式。
區間式循環主要是應用在場景系統,可能需要一個鏈條循環或者子樹循環帶動,具體情況需要看游戲的設計模式,如果單個場景(比如地圖)是使用單例的方式,那么使用鏈條式循環帶動循環邏輯比較合適,如果單個場景是通過new出來的,那么使用子樹方式來切換銜接更加容易明了。
以上是我們在做MMORPG時候的一些小小經驗總結,上述中我們用的最多是組合式循環(廢話,組合式全包了),但是對于一些小型的游戲,建議還是不要設計這么復雜,對于大型的網絡游戲而言,程序設計這部分的重要性非比尋常,最后,看過很多這樣或那樣的說法,網頁游戲對于性能是不行的,我想大部分的性能問題并不是技術本身,而是開發者沒有將一個游戲本身思考清楚,什么時候我們用什么方法可以達到什么目的,而很多的開發者期望也這個方便,那個也好,一味的追求萬事俱備只欠東風的美好環境,殊不知,所謂的拿來思想只會使自己退步,期望各位開發者多能從中找到一點靈感,為自己的提升有個交代:)。
本文轉自nowpaper 51CTO博客,原文鏈接:http://blog.51cto.com/nowpaper/712448
總結
以上是生活随笔為你收集整理的Silverlight C# 游戏开发:游戏循环体的五种设计方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hyper-V 的导入和导出
- 下一篇: split、replace、indexo