4.4.2 強(qiáng)制重繪
在將后臺緩沖區(qū)中的圖像呈現(xiàn)到游戲窗體中時,很多時候并不只是顯示移動矩形區(qū)域,而是需要強(qiáng)行將整個區(qū)域進(jìn)行呈現(xiàn)。例如下列實例:
● 當(dāng)游戲首次啟動時 如果不對整個窗體進(jìn)行重繪,那么可能會因為那些初始靜態(tài)對象繪制失敗而終止程序。并且會發(fā)現(xiàn)繪制在Windows Mobile的Today頁面上,而不是在空白窗口中。
● 當(dāng)游戲被重置時 在這個階段,所有的游戲?qū)ο蠖家l(fā)生明顯的變動。執(zhí)行一次完整的重繪才能確保每個對象都能正確顯示。
● 當(dāng)游戲窗體大小變化時 如果窗體大小發(fā)生改變(例如,由于設(shè)備方向由橫屏變?yōu)?/p>
豎屏),就需要重新繪制,對整個游戲畫面進(jìn)行重新顯示,才能適應(yīng)新的窗體大小。
我們通過調(diào)用CGameEngineGDIBase.ForceRepaint方法來實現(xiàn)重繪,該方法要做三件事情:
● 將一個名為_forceRerender的類變量設(shè)置為true。下次調(diào)用Render函數(shù)時會檢查該變量,確保對整個后臺緩沖區(qū)進(jìn)行重建。
● 將一個名為_forceRepaint的類變量設(shè)置為true。下次調(diào)用Present函數(shù)時會檢查該變量,確保將整個后臺緩沖區(qū)進(jìn)行重建。
● 使整個游戲窗體失效。
4.4.3 性能影響
Bounce項目中所引用的游戲引擎項目已經(jīng)包含了上面所介紹的優(yōu)化渲染時所需要的代碼,當(dāng)項目運行時會顯示幀率,因此我們可以看到執(zhí)行效率優(yōu)化后的效果。為了與未優(yōu)化渲染時進(jìn)行對比,我們只要在CGameEngineGDIBase.Advance方法起始的地方插入代碼來調(diào)用ForceRepaint函數(shù)即可。
在設(shè)備上分別運行優(yōu)化后的代碼與未優(yōu)化的代碼,通過在不同的設(shè)備上進(jìn)行測試,我得到了下列對比結(jié)果:
● HTC Touch Pro2 (WVGA) 未優(yōu)化時31幀/s,優(yōu)化后45幀/s(性能提高了45%)。
● i-mate PDA2 (QVGA) 未優(yōu)化時32幀/s,優(yōu)化后40幀/s(性能提高了25%)。
從這個數(shù)據(jù)可以看出在屏幕越大性能提高越多(可以預(yù)料到)。與本示例相比,那些移動區(qū)域小的游戲會有更加明顯的提升。
4.5 引擎的其他功能
本游戲引擎已經(jīng)為我們提供了一個簡單而且經(jīng)過了優(yōu)化的圖形框架,還可以讓它執(zhí)行一些其他的任務(wù)。接下來我們就看看還可以添加哪些其他功能。
4.5.1 與設(shè)備進(jìn)行交互
在第1章中曾經(jīng)討論過,要記得我們是運行在一個多任務(wù)的設(shè)備中,能夠執(zhí)行各種各樣其他功能,其中一些傳統(tǒng)的功能要比游戲更重要。因此,我們需要能夠處理設(shè)備上各種可能發(fā)生的交互事件。在本節(jié)中將介紹這個遺留的主題,以保證我們的游戲可以與設(shè)備和諧地進(jìn)行交互。
1. 最小化及還原
玩家在任何時刻都可能會決定單擊X按鈕將游戲最小化,或者用其他的方式退出我們的游戲。同樣,其他應(yīng)用程序也可能會突然獲得焦點,從而迫使游戲最小化(例如來電)。當(dāng)發(fā)生這些情況時,我們需要做兩件事:
● 停止游戲的運行。暫停任何操作,盡可能減少CPU使用率。
● 等待游戲重新激活,然后使游戲繼續(xù),并且強(qiáng)制對屏幕進(jìn)行一次重繪,這樣所有對象都會顯示。
將游戲進(jìn)程掛起是由游戲本身負(fù)責(zé)的,因為游戲引擎無法知道設(shè)備何時有來電。我們已經(jīng)在窗體的RenderLoop函數(shù)中看到了如何處理這種情況。
然而,引擎可以在其Advance方法中確認(rèn)游戲窗體是否擁有焦點。如果沒有,它可以暫停游戲的運行,為操作系統(tǒng)讓出資源。這些發(fā)生在CGameEngineGDIBase.Advance方法中,如程序清單4-19所示。
程序清單4-19 在Advance方法中檢測焦點
/// <summary>
/// Advance the simulation by one frame
/// </summary>
public override void Advance()
{
// If the game form doesn't have focus, sleep for a moment and
// return without any further processing
if (!GameForm.Focused)
{
System.Threading.Thread.Sleep(100);
return;
}
[... – the rest of the Advance procedure continues here ...]
}
通過調(diào)用Sleep函數(shù)將應(yīng)用程序進(jìn)程掛起1/10秒,允許操作系統(tǒng)執(zhí)行其他等待執(zhí)行的任務(wù)。由于游戲?qū)嶋H進(jìn)入了循環(huán)休眠狀態(tài),因此CPU使用率會非常低。不過,我仍然推薦對主游戲窗體本身檢測是否擁有焦點而不是依靠該方法。
當(dāng)游戲窗體重新激活時,需要強(qiáng)制執(zhí)行一次重繪,以完整地渲染背景。這需要在CGameEngineGDIBase類的構(gòu)造函數(shù)中為游戲窗體添加Activated事件處理程序。要注意,是在引擎基類中添加該事件處理程序而不是在窗體本身中添加,因此我們不能像通常那樣使用窗體屬性窗口,而必須以編程的方式添加:
// Add an Activated handler for the game form
gameForm.Activated += new System.EventHandler(GameFormActivated);