簡體   English   中英

如何更快地使屏幕無效?

[英]How to invalidate screen faster?

在我目前的項目(生命游戲)中,我需要重繪屏幕,因為大約有200個物體在移動。 我可以想到兩種方法,但沒有任何線索會更快:

我可以:
1)為整個屏幕調用Invalidate(),並在Paint處理程序中有以下內容:

void Paint(object sender, PaintEventArgs e)
{
   foreach(Cell c in ListOfCells)
          {
             e.DrawImage(c,c.x,c.y);
          }
}

2)或者我可以使每個單元格的屏幕的每個部分無效:

public void MyInvalidate()
{
  foreach(Cell c in ListOfCells)
              {
                 Invalidate(c.X,c.Y,c.Width,c.Height);
              }


}

並擁有與上面相同的處理程序

現在,第一條規則始終是“不要過早優化”。 您需要確保需要優化清潔代碼。

現在,在生命游戲中,你最初看的是一個非常空的屏幕。 然而,隨着比賽的進行,越來越多的細胞將被填滿,最終將成為整個棋盤。 現在,GOL規則規定大多數這些細胞將從一個周期變為另一個周期。

您還需要通過“使區域無效”來理解它的含義。 在Windows中,無效區域“加起來”以形成“更新區域”,以便WM_PAINT消息可以告訴程序要繪制屏幕的哪個部分。 在Paint事件處理程序中,使用RectVisible來確定是否要刷新單元格。

換句話說,做方法1的“成本”(假設板尺寸為n):

(n x n) x (redraw cell + update cell on screen)

請注意,我假設您在繪制單元格之前記得要清除屏幕,否則在上一個循環中過去“活着”的單元格將保留在屏幕上。 因此,這假設您要在整個屏幕上繪制活動單元格或空白單元格。

做方法2的“成本”:

(v) x (redraw cell + update cell on screen) + (n x n) x (RectVisible call)

其中v =改變的細胞數(見下面的警告)。

因此,方法1比方法2更快,如果:

(n x n) x redraw < v x redraw + (n x n) x RectVisible
n2 x (redraw - RectVisible) < v x redraw
v > ((redraw - RectVisible) / redraw) x n2
v > (1 - RectVisible/redraw) x n2

換句話說,改變的單元的數量必須大於1減去(RectVisible cost / redraw cost)的比率。 現在,與在屏幕上繪制位圖相比, RectVisible通常非常快,特別是如果您的單元格具有高分辨率。 因此,Rectvisible / redraw通常是一個非常小的數字,只有當有> 99%的電路板同時改變時,方法1才比方法2更快,這是不太可能的。

換句話說,您會發現方法2通常會產生更高的性能,因為如果要在剪切區域之外(即不在更新區域內)繪制圖像, DrawImage通常會跳過整個操作。

CAVEAT - 您的代碼,因為它不起作用

但是,方法2中的代碼將不起作用。 你必須記住在最后一個循環中“清空”曾經有“活”細胞的“死”細胞。 換句話說,您使“已更改”的單元格無效,而不僅僅是那些“活着”的單元格。 細胞是“活着”多個循環, 不需要無效。 因此, MyInvalidate方法中的邏輯存在缺陷。

如果您堅持使用與第一個相同的Paint事件處理程序,第二個代碼將沒有任何好處,因為基本上您將多次重繪所有單元格(因為對於每個單元格,您將重繪所有其他單元格細胞也是如此)。 要解決此問題,您可以檢查e.ClipRectangle ,並僅重繪該矩形內的單元格。

但是,如果您屏幕上唯一的東西是單元格(因此您沒有大量其他顯示元素,例如UI控件),那么第一種方法是您將獲得的最佳方法(即只是無效( )整個屏幕)。 僅當您使大量未更改的屏幕區域無效時,才會出現性能損失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM