正文

開發(fā)游戲引擎(18)

Windows移動(dòng)游戲開發(fā)實(shí)戰(zhàn) 作者:(美)Adam Dawes


 

4.4.2  強(qiáng)制重繪

在將后臺緩沖區(qū)中的圖像呈現(xiàn)到游戲窗體中時(shí),很多時(shí)候并不只是顯示移動(dòng)矩形區(qū)域,而是需要強(qiáng)行將整個(gè)區(qū)域進(jìn)行呈現(xiàn)。例如下列實(shí)例:

● 當(dāng)游戲首次啟動(dòng)時(shí)  如果不對整個(gè)窗體進(jìn)行重繪,那么可能會因?yàn)槟切┏跏检o態(tài)對象繪制失敗而終止程序。并且會發(fā)現(xiàn)繪制在Windows Mobile的Today頁面上,而不是在空白窗口中。

● 當(dāng)游戲被重置時(shí)  在這個(gè)階段,所有的游戲?qū)ο蠖家l(fā)生明顯的變動(dòng)。執(zhí)行一次完整的重繪才能確保每個(gè)對象都能正確顯示。

● 當(dāng)游戲窗體大小變化時(shí)  如果窗體大小發(fā)生改變(例如,由于設(shè)備方向由橫屏變?yōu)?/p>

豎屏),就需要重新繪制,對整個(gè)游戲畫面進(jìn)行重新顯示,才能適應(yīng)新的窗體大小。

我們通過調(diào)用CGameEngineGDIBase.ForceRepaint方法來實(shí)現(xiàn)重繪,該方法要做三件事情:

● 將一個(gè)名為_forceRerender的類變量設(shè)置為true。下次調(diào)用Render函數(shù)時(shí)會檢查該變量,確保對整個(gè)后臺緩沖區(qū)進(jìn)行重建。

● 將一個(gè)名為_forceRepaint的類變量設(shè)置為true。下次調(diào)用Present函數(shù)時(shí)會檢查該變量,確保將整個(gè)后臺緩沖區(qū)進(jìn)行重建。

● 使整個(gè)游戲窗體失效。

4.4.3  性能影響

Bounce項(xiàng)目中所引用的游戲引擎項(xiàng)目已經(jīng)包含了上面所介紹的優(yōu)化渲染時(shí)所需要的代碼,當(dāng)項(xiàng)目運(yùn)行時(shí)會顯示幀率,因此我們可以看到執(zhí)行效率優(yōu)化后的效果。為了與未優(yōu)化渲染時(shí)進(jìn)行對比,我們只要在CGameEngineGDIBase.Advance方法起始的地方插入代碼來調(diào)用ForceRepaint函數(shù)即可。

在設(shè)備上分別運(yùn)行優(yōu)化后的代碼與未優(yōu)化的代碼,通過在不同的設(shè)備上進(jìn)行測試,我得到了下列對比結(jié)果:

● HTC Touch Pro2 (WVGA)  未優(yōu)化時(shí)31幀/s,優(yōu)化后45幀/s(性能提高了45%)。

● i-mate PDA2 (QVGA)  未優(yōu)化時(shí)32幀/s,優(yōu)化后40幀/s(性能提高了25%)。

從這個(gè)數(shù)據(jù)可以看出在屏幕越大性能提高越多(可以預(yù)料到)。與本示例相比,那些移動(dòng)區(qū)域小的游戲會有更加明顯的提升。

4.5  引擎的其他功能

本游戲引擎已經(jīng)為我們提供了一個(gè)簡單而且經(jīng)過了優(yōu)化的圖形框架,還可以讓它執(zhí)行一些其他的任務(wù)。接下來我們就看看還可以添加哪些其他功能。

4.5.1  與設(shè)備進(jìn)行交互

在第1章中曾經(jīng)討論過,要記得我們是運(yùn)行在一個(gè)多任務(wù)的設(shè)備中,能夠執(zhí)行各種各樣其他功能,其中一些傳統(tǒng)的功能要比游戲更重要。因此,我們需要能夠處理設(shè)備上各種可能發(fā)生的交互事件。在本節(jié)中將介紹這個(gè)遺留的主題,以保證我們的游戲可以與設(shè)備和諧地進(jìn)行交互。

1. 最小化及還原

玩家在任何時(shí)刻都可能會決定單擊X按鈕將游戲最小化,或者用其他的方式退出我們的游戲。同樣,其他應(yīng)用程序也可能會突然獲得焦點(diǎn),從而迫使游戲最小化(例如來電)。當(dāng)發(fā)生這些情況時(shí),我們需要做兩件事:

● 停止游戲的運(yùn)行。暫停任何操作,盡可能減少CPU使用率。

● 等待游戲重新激活,然后使游戲繼續(xù),并且強(qiáng)制對屏幕進(jìn)行一次重繪,這樣所有對象都會顯示。

將游戲進(jìn)程掛起是由游戲本身負(fù)責(zé)的,因?yàn)橛螒蛞鏌o法知道設(shè)備何時(shí)有來電。我們已經(jīng)在窗體的RenderLoop函數(shù)中看到了如何處理這種情況。

然而,引擎可以在其Advance方法中確認(rèn)游戲窗體是否擁有焦點(diǎn)。如果沒有,它可以暫停游戲的運(yùn)行,為操作系統(tǒng)讓出資源。這些發(fā)生在CGameEngineGDIBase.Advance方法中,如程序清單4-19所示。

程序清單4-19  在Advance方法中檢測焦點(diǎn)

/// <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使用率會非常低。不過,我仍然推薦對主游戲窗體本身檢測是否擁有焦點(diǎn)而不是依靠該方法。

當(dāng)游戲窗體重新激活時(shí),需要強(qiáng)制執(zhí)行一次重繪,以完整地渲染背景。這需要在CGameEngineGDIBase類的構(gòu)造函數(shù)中為游戲窗體添加Activated事件處理程序。要注意,是在引擎基類中添加該事件處理程序而不是在窗體本身中添加,因此我們不能像通常那樣使用窗體屬性窗口,而必須以編程的方式添加:

// Add an Activated handler for the game form

gameForm.Activated += new System.EventHandler(GameFormActivated);


上一章目錄下一章

Copyright ? 讀書網(wǎng) hotzeplotz.com 2005-2020, All Rights Reserved.
鄂ICP備15019699號 鄂公網(wǎng)安備 42010302001612號