8. 添加其他函數(shù)
我們還將在基類中添加一些更加深入的功能集,供引擎或者游戲自身使用。
首先,要添加的是一個隨機(jī)數(shù)生成器。該生成器只是.NET System.Random類的一個實例。通過引擎訪問隨機(jī)數(shù)生成器會有兩個優(yōu)點:第一,每當(dāng)需要隨機(jī)數(shù)時就可以調(diào)用它,而不用創(chuàng)建本地實例,從而使代碼能夠更加簡單;第二(也是最有用的),我們有機(jī)會為隨機(jī)數(shù)生成器指定一個固定的隨機(jī)種子。采用固定的隨機(jī)數(shù)種子,使應(yīng)用程序生成的隨機(jī)數(shù)字每次都是同一個序列,這樣就可以重復(fù)同一個游戲場景來進(jìn)行測試(不考慮與玩家的交互)。
還要添加一些代碼,用來在游戲運行期間返回游戲的幀率(使用FramesPerSecond屬性)。它記錄了每一秒中屏幕上的圖形更新次數(shù)。我們將盡量獲得幀率的最高值,因為幀率越高,動畫就會越平滑。當(dāng)幀率降為很低時,游戲會看上去很卡,所以對幀率值進(jìn)行監(jiān)視是很有用的。
最后,還要有另一個對象管理函數(shù)RemoveTerminatedObjects。當(dāng)某個對象不再被游戲所需要時,我們就為它設(shè)置一個標(biāo)志,告訴引擎該對象將要終止了。RemoveTerminatedObjects函數(shù)會從對象集合中將所有包含該標(biāo)志的對象刪除。對象必須通過這種方式來刪除(而不是馬上從集合中將它們刪除),因為我們需要在它們被銷毀之前進(jìn)行清除;在Advance函數(shù)的最后來執(zhí)行這個任務(wù)。在本章后文中介紹優(yōu)化圖形渲染時將解釋為什么需要用這種方式來刪除對象。
4.2.2 CgameObjectBase類
下面對CGameObjectBase類進(jìn)行概要的介紹:
● 目的 顯示游戲中的圖形對象。
● 類型 抽象基類。
● 父類 無。
● 子類 專門用于游戲的圖形API實現(xiàn),例如用于GDI引擎。
● 主要功能
● Xpos、Ypos、Zpos、LastXPos、LastYPos、LastZPos 用于定義對象位置的屬性。
● IsNew, Terminate 用于定義對象狀態(tài)的屬性。
● Render 允許將對象繪制到游戲中。
● Update 允許對象自己進(jìn)行移動并產(chǎn)生動畫。
有很多對象都繼承于游戲?qū)ο?,所以我們來看看這些對象的基類。
CgameObjectBase類是另一個抽象基類,我們所有實際的游戲?qū)ο蠖紝乃^承。在其構(gòu)造函數(shù)中要傳遞一個對CGameEngineBase游戲引擎(或者是其子類)的引用。該對象中存儲了一個私有的類變量_gameEngine,通過訪問權(quán)限為protected的GameEngine屬性可以訪問它。這樣所有的對象都可以在其運行平臺中訪問游戲引擎實例。
1. 對象的位置
CGameObjectBase類中包含了用于跟蹤對象位置的一系列屬性值。我們保存每個對象當(dāng)前的x坐標(biāo)、y坐標(biāo)和z坐標(biāo)。在第3章中已經(jīng)介紹過x坐標(biāo)和y坐標(biāo);z坐標(biāo)用于表示對象在第三個維度上的位置,在屏幕中但不在屏幕上(事實上z軸應(yīng)與屏幕垂直)。在本書后文中介紹用OpenGL ES開發(fā)3D圖形時,z坐標(biāo)才會扮演重要的角色。
對于每一種坐標(biāo),我們都會將對象當(dāng)前的位置及先前的位置保存起來。這樣做有兩個重要的原因。首先,有兩個位置才能判斷對象是否移動了。本章后文中會介紹如何使用該信息使游戲引擎在渲染時更加有效。其次,將兩個位置都保存的話,能使對象在這兩個位置之間移動時更加平滑。在第5章中討論游戲所用的不同的計時方式時將會用到它。
位置的值使用以下6種屬性表示:Xpos、Ypos、Zpos、LastXPos、LastYPos以及LastZPos。前三個屬性值將返回對象的當(dāng)前位置;它們被定義為虛屬性,如果需要,將在繼承對象類中被重寫。其他三個屬性用于返回對象的上一個位置。
與位置屬性相關(guān)的是UpdatePreviousPosition函數(shù)。它將所有對象的當(dāng)前位置屬性中的值復(fù)制到先前位置屬性中。每當(dāng)需要更新對象的位置時,在計算出對象的新位置之前,就可以通過游戲引擎來調(diào)用該函數(shù),這樣可以確保對象的先前位置屬性準(zhǔn)確而及時。
所有這些與坐標(biāo)相關(guān)的屬性都用float類型來存儲值。這似乎不太必要,畢竟我們不能繪制半個像素,為何要用分?jǐn)?shù)來標(biāo)志像素的位置呢?
雖然不能在非整數(shù)位置上繪制對象,但用非整數(shù)來更新其位置還是很有用的。例如,您想在屏幕上以非常慢的速度顯示太陽的移動軌跡,就會發(fā)現(xiàn),如果每幀移動一個像素,那么移動的速度會過快。與通過實現(xiàn)復(fù)雜的邏輯使在若干幀后才移動一次相比,現(xiàn)在可以按照0.1或是0.01的增量來移動。這樣就將速度降到原來的1/10或1/100,不需要任何額外的代碼。
當(dāng)以后開始使用OpenGL ES時就能發(fā)現(xiàn)這樣做的另外一個好處了。OpenGL ES所使用的坐標(biāo)系與屏幕上的像素沒有對應(yīng)關(guān)系。因此,以分?jǐn)?shù)的方式來修改對象的位置實際會對其顯示位置產(chǎn)生影響。