2. 存儲對象狀態(tài)
除了對象的位置,在游戲引擎中還有兩個與其狀態(tài)相關(guān)的其他屬性。它們是IsNew和Terminate。
IsNew用于指示該對象自上次更新后是否已添加到游戲引擎中。我們可以通過該屬性來確認對象在屏幕上的初始顯示是否正確。對于新對象,該屬性會自動被設(shè)置為true,當(dāng)游戲引擎對它進行了一次更新操作后,該屬性就自動被設(shè)置為false。
Terminate屬性(我們曾經(jīng)提到過)用于請求將對象從仿真環(huán)境中刪除。要請求終止操作的話只需要將該屬性值設(shè)置為true,當(dāng)游戲發(fā)生下一次更新時,對象就會從游戲中刪除。
3. 對象中的方法
最后,我們需要在引擎中添加兩個虛函數(shù),供對象完成操作任務(wù)。
首先是Render,對象通過該函數(shù)來將自身繪制到后臺緩沖區(qū)中。與CgameEngineBase類中的Render方法類似,該方法以一個Graphics對象作為參數(shù),在該階段實際并不做任何操作,它將在繼承類的對象中得以使用。
另一個函數(shù)是Update。您很快就能看到我們可以使許多對象自主(或部分自主),它們可以控制自己的移動位置,在一定程度上與引擎控制系統(tǒng)保持獨立。因此,引擎將調(diào)用該函數(shù)使對象可以根據(jù)需要執(zhí)行各種力所能及的操作。再一次,在基類中該函數(shù)不包含代碼,但是繼承類要對它進行重寫。
4.2.3 CGameObjectGDIBase類
下面對CGameObjectGDIBase類進行概要的介紹:
● 目的 一個CGameObjectBase類的實現(xiàn),提供GDI圖形所需的功能。
● 類型 抽象基類。
● 父類 CgameObjectBase。
● 子類 各個游戲的游戲?qū)ο?,?chuàng)建在獨立的程序集中。
● 主要功能
● Width和Height 尺寸屬性。
● HasMoved和GetRenderRectangle 判斷移動狀態(tài)以及對象所在的區(qū)域。
雖然我們對游戲?qū)ο箢惖挠懻撨€不多,但能看到GDI的脈絡(luò)。CGameObjectGDIBase類是另一個抽象類,其內(nèi)容不是很多,只是添加了一些使GDI渲染引擎能夠高效工作的屬性與方法。
1. 在GDI中設(shè)置對象的狀態(tài)
首先要添加的是用于跟蹤對象Width和Height的屬性。這是兩個很重要的屬性,根據(jù)它們提供的信息就可以得到每個對象在屏幕上占用的空間。在本章后文介紹渲染引擎優(yōu)化時將使用到它。
我們還要添加一個名為GetRenderRectangle的函數(shù)。對象根據(jù)自己的位置及尺寸在屏幕上進行繪制,該函數(shù)將得到對象占用的矩形區(qū)域,并返回該矩形,在對象本身的Render方法中及游戲引擎優(yōu)化中都將使用該函數(shù),在本章后文中將會看到。在內(nèi)部,對象也記錄了其先前的位置,每當(dāng)發(fā)生移動時,該位置的值都會進行更新。這也對后面的優(yōu)化有幫助。
2. 對象移動
然后我們添加一個名為HasMoved的屬性。我們用它來標(biāo)識對象是否往某個方向移動了。移動不僅僅包括其位置的變化,還包括對象是否添加到了游戲引擎中,或者對象是否被終止。這些條件中的任何一個如果發(fā)生,都需要在窗體上重繪對象。
該屬性通過CheckIfMoved函數(shù)進行更新。該函數(shù)檢查對象中的每一個相關(guān)的狀態(tài)屬性,如果任何一個狀態(tài)屬性發(fā)生變化,就認為對象發(fā)生了移動,而將HasMoved屬性設(shè)置為true,該函數(shù)如程序清單4-6所示。
程序清單4-6 CheckIfMoved 函數(shù)
/// <summary>
/// Determine whether any of our object state has changed in a way that would
/// require the object to be redrawn. If so, set the HasMoved flag to true.
/// </summary>
internal virtual void CheckIfMoved()
{
if (XPos != LastXPos) HasMoved = true;
if (YPos != LastYPos) HasMoved = true;
if (ZPos != LastZPos) HasMoved = true;
if (IsNew) HasMoved = true;
if (Terminate) HasMoved = true;
}
另外,對任何一個位置屬性(Xpos、Ypos或ZPos)進行修改,都將使HasMoved屬性被設(shè)置為true。