程序清單4-18 ClipRegion可視化調(diào)試代碼
// Debug: draw a rectangle around the clip area so we can see what we have
// redrawn
using (Pen p = new Pen(Color.Blue))
{
backGfx.DrawRectangle(p, renderRect.X, renderRect.Y,
renderRect.Width - 1, renderRect.Height - 1);
}
運(yùn)行Bounce項(xiàng)目時(shí)啟用該代碼,屏幕上的顯示效果如圖4-6所示。
當(dāng)前繪制矩形后面的方框痕跡顯示了每一幀中的ClipRegion。由于我們只對(duì)移動(dòng)區(qū)域進(jìn)行更新,因此舊的繪制區(qū)域在屏幕的后面形成了一條軌跡。這可以讓我們很容易地看到在游戲運(yùn)行時(shí)對(duì)哪些區(qū)域進(jìn)行了繪制。
4.4.1 添加、更新和刪除對(duì)象
有三個(gè)進(jìn)一步的操作可以影響到移動(dòng)區(qū)域,但與對(duì)象的移動(dòng)并不直接相關(guān):即添加新對(duì)象、刪除已有對(duì)象、更新靜態(tài)對(duì)象的圖。
添加一個(gè)新對(duì)象時(shí),即使它是完全靜止的,還是需要對(duì)它進(jìn)行渲染,否則它會(huì)保持不可見直到落入到移動(dòng)矩形區(qū)域中。因此,我們需要在每個(gè)對(duì)象被創(chuàng)建時(shí)在其內(nèi)部設(shè)置一個(gè)名為IsNew的標(biāo)志,任何設(shè)置了該標(biāo)志的對(duì)象都將被包含到累加的移動(dòng)矩形區(qū)域中,而不用考慮它們坐標(biāo)的變化。
對(duì)象生命周期的另一個(gè)端點(diǎn)是終止。當(dāng)一個(gè)對(duì)象不再被需要時(shí),我們需要對(duì)屏幕區(qū)域進(jìn)行重繪,使該對(duì)象從畫面中消失。因此我們需要使用一個(gè)Terminate標(biāo)志,在本章中已經(jīng)多次提到了它。被標(biāo)記為終止的對(duì)象不會(huì)被重繪,但它們?nèi)员徽J(rèn)為是屬于移動(dòng)矩形區(qū)域的。處理完畢后,使用RemoveTerminatedObjects函數(shù)將它們從游戲?qū)ο罅斜碇袆h除。
任何沒有使用Terminate標(biāo)志但被直接從列表中刪除了的對(duì)象將仍然留在屏幕的后面,直到移動(dòng)矩形將它們完全擦除掉,所以,在終止對(duì)象時(shí)要記得使用這種方法。
CGameObjectGDIBase包含了Check If Moved函數(shù),游戲的每一步運(yùn)行都會(huì)由引擎來(lái)調(diào)用該函數(shù)。該函數(shù)根據(jù)條件來(lái)查找需要進(jìn)行重繪的對(duì)象(發(fā)生移動(dòng)的對(duì)象、新對(duì)象或終止對(duì)象)。如果發(fā)現(xiàn)匹配的對(duì)象,就將其HasMoved屬性設(shè)置為true。然后在下一次調(diào)用Render函數(shù)時(shí)設(shè)置它。
最后,我們會(huì)碰到這種情形:對(duì)象的圖像被修改了,但位置并沒有發(fā)生改變。在這種情況下,需要對(duì)它進(jìn)行重繪才能使用戶看到新圖像,但就我們目前所描述的條件來(lái)看,這種情況不會(huì)發(fā)生,因?yàn)閷?duì)象都不是新對(duì)象,也沒有被終止且沒有發(fā)生移動(dòng)。
在這種情形下,我們可以將對(duì)象的HasMoved屬性設(shè)置為true,強(qiáng)制對(duì)其進(jìn)行重繪。當(dāng)下一次調(diào)用Render函數(shù)時(shí),該函數(shù)會(huì)查看該標(biāo)志是否被設(shè)置,如果設(shè)置了,那么不論其他的屬性值如何發(fā)生變化,對(duì)象都會(huì)被重繪。