程序清單3-15 在屏幕上繪制彈跳顏色塊
private void Method1_SimpleDraw_Paint(object sender, PaintEventArgs e)
{
// Draw our box at its current location
using (Brush b = new SolidBrush(Color.Blue))
{
gfx.FillRectangle(b, xpos, ypos, boxSize, boxSize);
}
}
這段代碼完成了基礎工作。但是,動畫的閃爍情況很嚴重。您可以運行配套下載代碼中的3_4_RenderingMethods示例項目,然后選擇使用SimpleDraw呈現(xiàn)模式就能看到這種情況。雖然顏色塊可以按照我們期望的方式移動,但移動時有比較嚴重的閃爍。這種類型的圖形顯示顯然不能用于任何游戲。
注意:
由于不同的仿真器緩沖區(qū)對屏幕的更新方式不同,所以在有一些模擬器上運行該示例時閃爍可能不是特別明顯。要看該動畫的真實情況,要在實際的手機上運行程序。
如何才能避免發(fā)生這樣的閃爍呢?我們看看在生成圖形時實際發(fā)生了什么情況。
您會注意到Paint事件中并沒有實際對窗體進行清除,但我們看到顏色塊在移動時身后并沒有產(chǎn)生軌跡。這是因為每次繪圖時GDI會自動清除屏幕,然后才會繪制新的顏色塊。由于所有這些操作都直接發(fā)生窗體上,而窗體正是我們所能看到的,窗體上的清除操作與繪圖操作交互出現(xiàn):在當清除操作已經(jīng)完成而顏色塊尚未繪制完成的間隙,窗體是空白的。
為了避免這種沖突,我們改變一下圖形的繪制方式。不直接在屏幕上進行繪制,而是創(chuàng)建一個屏幕外緩沖區(qū),并且在其中進行所有的繪圖操作。在繪圖的同時,屏幕上先前顯示的東西都還保留在原位。
當所有的繪圖工作完成后,用一個單獨的操作將完整的緩沖區(qū)中的圖像復制到屏幕上。這樣,每個生成的畫面可以直接切換到下一個畫面,而看不到任何分步完成的圖形操作。這個技術被稱為雙緩沖,因為使用了兩個圖形緩沖區(qū):可見部分的緩沖區(qū)(顯示在屏幕上)以及非可見部分的后臺緩沖區(qū)(在該緩沖區(qū)中生成圖形)。
在使用雙緩沖進行繪圖時還有一個不同的地方,由于我們是自己創(chuàng)建的后臺緩沖區(qū),因此可以對它進行完全的控制。與直接在窗體中進行繪制有所不同,GDI不會干擾緩沖區(qū)中已存在的內(nèi)容,這意味著在上一個畫面中所繪制的東西在下一次繪制時仍然存在。這非常有用,因為任何實際上沒有發(fā)生移動的圖形都可以保留在原地而不需要對它進行重繪。在下一章中我們會根據(jù)這種方法對游戲進行有效地優(yōu)化。
此外還需要在繪制顏色塊之前將緩沖區(qū)清空。否則在運行該動畫時,顏色塊的后面會存在拖尾,程序清單3-16演示了如何對后臺緩沖區(qū)進行初始化,如何在后臺緩沖區(qū)中繪圖以及將它復制到窗體上使圖形可見。