2012年12月15日 星期六

自製小遊戲引擎 - 圖層繪圖與舞台流程

延續之前的心得~



在繪圖的部分,自己建立了一個類似圖層以及圖層管理員的類別。在該類別的使用上,首先必須先指定需要的圖層數來創造一個新的圖層管理員。之後,便可以在圖層中加入實踐了"SDisplayUnit"這個interface的物件(SGameUnit已經實踐該interface),這個interface其實只需要包含一個draw的function,來告訴圖層管理員"輪到我繪圖時,我要畫些什麼"。整個舞台只有一個圖層管理員,當舞台的流程進行到繪圖的階段時,除了部分背景或UI的繪圖以外,其餘的繪圖都是交給圖層管理員來處理。以目前的範例遊戲來說,當舞台開始繪圖時,會先針對所設定的背景物件進行繪製背景的動作,然後就進入圖層管理員的階段。圖層管理員會依照所設定的圖層數量,從第一個圖層開始,輪流叫出在第一圖層裡面的物件,並要求進行"繪製自己"的動作。第一圖層所有物件繪製完畢後,換第二圖層內的所有物件,然後第三圖層、第四圖層......。透過這樣的方式,確保一些具有強烈前後關係的元件能夠正確的被繪製出來,而不會出現背景覆蓋前景的狀況。

把引擎中最主要開發的部份說明完以後,再重新說明一下整個舞台(SGameHost)的詳細流程。這邊可能沒有辦法詳細說明每一個類別該如何使用,但我會盡我所能的說明,剩下的透過直接閱讀範例應該比較能掌握那個感覺。
首先,舞台的流程分成幾個不同的基本狀態:
GAMEREADY 遊戲準備好可以開始
GAMESTARTED 遊戲正在進行中
GAMEPAUSED 遊戲暫停中
GAMEOVERD 遊戲結束
根據不同的狀態,舞台的更新與繪圖的流程會稍微不同,這部分後面會說明,目前先留有個印象就好。

這些狀態之間的切換是藉由setStateChangeCMD(int)這個function來進行:
當舞台在GAMEREADY狀態下時,可以切換為GAMESTARTED的狀態
當舞台在GAMESTARTED狀態下時,可以切換為GAMEPAUSEDGAMEOVERD的狀態
當舞台在GAMEPAUSED狀態下時,可以切換為GAMESTARTED的狀態
當舞台在GAMEOVERD狀態下時,可以切換為GAMEREADY的狀態
這樣做的目的是為了將狀態的改變與舞台的更新同步化,如果不透過這個function直接去改變舞台狀態的話可能會產生更新與繪圖之間狀態相異的狀況。

在遊戲舞台的類別中,設有幾個abstarct function需要實踐,決定舞台狀態切換時需要進行的動作:
initial() 當舞台物件被創造時會進行一次的動作
gameStart() 當舞台從GAMEREADY切換為GAMESTARTED時進行的動作
gameOver() 當舞台從GAMESTARTED切換為GAMEOVERD時進行的動作
gamePause() 當舞台從GAMESTARTED切換為GAMEPAUSED時進行的動作
gameResume() 當舞台從GAMEPAUSED切換為GAMESTARTED時進行的動作
gameReady() 當舞台從GAMEOVERD切換為GAMEREADY時進行的動作
isGameOver() 當舞台為GAMESTARTED且此function回傳true時,舞台切換為GAMEOVERD
雖然不知道大部分的遊戲是怎麼做的,但我的構想是透過這些function來進行流程的控管。例如範例遊戲中,在initial()時創造新的SAsset(資源管理員),因為在遊戲過程中無論重新幾次遊戲都是使用同一個資源管理員,而在gameReady()時,釋放舊有的SLayer(圖層管理員)與SControler(演員管理員),重新創造空白的SLayer與SControler。如此一來,當遊戲結束並再一次進入GAMEREADY狀態時,就會類似初始化一般,達到可以遊戲重覆遊玩,不需要關閉程式重新開啟。

如同之前所提過的,舞台會不斷的重覆進行更新→繪圖→等待。在更新的階段中,只要舞台不處在GAMEPAUSED狀態下,舞台就會開始更新背景、演員、UI、判斷碰撞。其實這個部分還在檢討中,因為當舞台在GAMEPAUSED(暫停狀態)時,實際上遊戲應該還是在"部分進行"著的,從目前大部分單機遊戲中可以看到,當玩家按下暫停鍵後,遊戲本身的動作暫停了,但是與其說暫停,不如說"切換為另一種名為'暫停'的狀態",顯示著"-Pause-"的字樣依然更新閃爍著,甚至在部分遊戲,只有在暫停中才能進行存檔、screen shot之類的動作,說明了以舞台的角度來說,暫停中的舞台還是活著的。恩~~~不過目前就偷懶一下暫時這樣設計吧,期待以後的版本更新吧(如果存在的話)。
回到正題,當進行更新時,如果舞台處在GAMESTARTED狀態下,還會額外更新一個SScenario(劇本)物件,該物件是一個事先訂好的劇本,用來控制舞台何時或何種狀況下該進行什麼樣的動作,或加入什麼樣的演員。從射擊遊戲上來說,就是安排遊戲過了多久後該出現怎樣的敵人,這部分在範例中是看不到的,因為寫範例時很偷懶的只用玩家的分數來決定下一個時間切點加入新的敵人的機率有多高而已。
完成更新後,舞台進行繪圖,這部分就顯得相對單純許多。首先繪製背景,接著進入圖層管理員繪製各圖層的元件,然後繪製玩家與系統的UI。到這邊一個循環就算結束了,舞台會自動計算能夠等待的時間,進行等待,然後再開始進行下一個循環的動作,如此一來,整個遊戲的架構就算組起來了。

老實說對自己的說明並沒有太大的自信,不知道有多少人會有興趣點進來,還能有時間看完這些又臭又長的文字,甚至下載引擎自己玩玩看。但至少在開發這些的過程中發現了很多以前紙上談兵時想不到的問題,也學到了很多一般工作用的程式開發不會接觸到的技巧,收穫絕對是豐富的。只是就目前能看到的還存在一些問題,例如資源的控管(尤其是音樂)還處在一個半完成的狀態,劇本的編寫、網路連線等也是接下來要完成的課題,後面的路還很遠,想要回頭感嘆,似乎還太早了些。

最後,感謝真的能看到這邊的所有人,也希望如果有人試著使用這個引擎之後,能夠給予小弟一些心得或指教,感恩!m(_ _)m

沒有留言 :

張貼留言