4.4 優(yōu)化渲染
目前我們所討論的代碼在每次更新時(shí)是這樣渲染圖形的:
● 清空后臺(tái)緩沖區(qū)。
● 將所有游戲?qū)ο罄L制到后臺(tái)緩沖區(qū)中。
● 將后臺(tái)緩沖區(qū)呈現(xiàn)在屏幕上。
這種方式很簡單,但效率不高。設(shè)想一個(gè)俄羅斯方塊游戲:我們將玩家的方塊向屏幕底部降落,游戲區(qū)域已經(jīng)有了很多其他的方塊,這些方塊已經(jīng)是完全靜止的了。以我們現(xiàn)在所用的渲染步驟,需要在每次更新畫面時(shí)也對那些靜態(tài)的方塊進(jìn)行重繪,即使它們與上一次畫面更新時(shí)相比沒有發(fā)生任何變化。如果能夠只對后臺(tái)緩沖區(qū)中那些實(shí)際發(fā)生了變化的一部分進(jìn)行重繪,那么效率將會(huì)明顯地提高。
該如何做呢?需要下列步驟:
● 判斷前一幀繪制完成后,發(fā)生了移動(dòng)的游戲?qū)ο笏嫉膮^(qū)域。
● 清空后臺(tái)緩沖區(qū),但只清空發(fā)生了移動(dòng)的區(qū)域。
● 對與移動(dòng)區(qū)域發(fā)生重疊的所有對象進(jìn)行繪制。
● 將移動(dòng)區(qū)域繪制到屏幕上,保留該區(qū)域以外的所有圖形不變。
實(shí)現(xiàn)這個(gè)改進(jìn)后能使引擎的表現(xiàn)有實(shí)質(zhì)性的改善。尤其是在那種包含了很多靜態(tài)元素的游戲中,通??梢员苊夂芏嗖槐匾闹乩L。
實(shí)現(xiàn)此優(yōu)化所需要進(jìn)行的改動(dòng)都發(fā)生在CGameEngineGDIBase類中,主要是其Render函數(shù)。首先要做的是判斷上次繪圖完成后發(fā)生了移動(dòng)的區(qū)域。
這個(gè)區(qū)域?qū)嶋H上包含了進(jìn)入了對象的區(qū)域(需要渲染移入對象的區(qū)域)以及移出對象的區(qū)域(也需要被重繪,這樣背景或者在該位置的其他任何對象才能重新顯示)。對象移出區(qū)域的渲染是很重要的,否則舊的對象會(huì)在后面形成拖尾。
注意:
在我們的實(shí)現(xiàn)中,將只計(jì)算游戲的單個(gè)移動(dòng)區(qū)域。還有一種方法是計(jì)算許多類似的小移動(dòng)區(qū)域,甚至是對每個(gè)對象的移動(dòng)區(qū)域都進(jìn)行計(jì)算。在大多數(shù)情況下,優(yōu)化渲染時(shí)使用單個(gè)區(qū)域?qū)嶋H上是一個(gè)效率比較高的方法,因?yàn)镚DI不必對多個(gè)單獨(dú)的小區(qū)域進(jìn)行記錄。該技術(shù)所用的代碼會(huì)簡單很多,它將Render函數(shù)的復(fù)雜度降到了最低。
示意圖4-4的對小球的移動(dòng)區(qū)域進(jìn)行了標(biāo)注,上一次調(diào)用Render函數(shù)時(shí)該區(qū)域的位置為灰色,本次調(diào)用時(shí)該區(qū)域?yàn)楹谏?。于是我們需要對方框中原來被小球遮擋了的方框以及該區(qū)域的背景進(jìn)行重繪。被虛線矩形標(biāo)注出來的區(qū)域?yàn)橐苿?dòng)區(qū)域。