2012-07-05 53 views
0

我第一次問一個問題,這裏這麼糾正我,如果I'm做錯了。優化我的棋局C#

圖片我的棋一套: http://img842.imageshack.us/img842/2695/65744343.png

我每次都進入了一塊它滯後約1秒鐘。每件作品和瓷磚都有一張圖片,正好有96張圖片。每當我移動一塊它清除黑色的一切,然後更新圖形。

在國際象棋的早期階段,我沒有任何圖像和使用不同的顏色來代替,只有幾件,沒有明顯的滯後和部分在瞬間移動。

 public void updateGraphics(PaintEventArgs e, Graphics g, Bitmap frame) 
    { 
     g = Graphics.FromImage(frame); 
     g.Clear(Color.Black); 


     colorMap(g); 

     g.Dispose(); 
     e.Graphics.DrawImageUnscaled(frame, 0, 0); 
    } 

功能顏色表(G)是這樣的:

 private void colorMap(Graphics g) 
    { 
     for (int y = 0; y < SomeInts.amount; y++) 
     { 
      for (int x = 0; x < SomeInts.amount; x++) 
      { 
       //Tiles 
       Bundle.tile[x, y].colorBody(g, x, y); 

       //Pieces 
       player1.colorAll(g); 
       player2.colorAll(g); 
      } 
     } 
    } 

的colorAll函數執行它看起來像這樣每件colorBody(G)功能:

 public void colorBody(Graphics g) 
    { 
     //base.colorBody() does the following: body = new Rectangle(x * SomeInts.size + SomeInts.size/4, y * SomeInts.size + SomeInts.size/4, size, size); 
     base.colorBody(); 

     if (team == 1) 
     { 
      //If its a white queen 
      image = Image.FromFile("textures/piece/white/queen.png"); 
     } 
     if (team == 2) 
     { 
      //If its a black queen 
      image = Image.FromFile("textures/piece/black/queen.png"); 
     } 
     g.DrawImage(image, body); 
    } 

和finaly的功能移動所述片:

 public void movePiece(MouseEventArgs e) 
    { 
     for (int y = 0; y < SomeInts.amount; y++) 
     { 
      for (int x = 0; x < SomeInts.amount; x++) 
      { 
       if (Bundle.tile[x, y].body.Contains(e.Location)) 
       { 
        //Ignore this 
        for (int i = 0; i < queens.Count; i++) 
        { 
         Queen temp = queens.ElementAt<Queen>(i); 
         temp.move(x, y); 
        } 
        //Relevant 
        player1.move(x, y); 
        player2.move(x, y); 
       } 
      } 
     } 
    } 

感謝您閱讀這一切!如果我的編碼示例不夠,我可以鏈接到整個程序。

+0

您的圖像有多大?我會猜測它們非常大。 – mydogisbox 2012-07-05 14:34:25

+2

'Image.FromFile()' - 你是否爲每一幀重新加載每個方塊的圖像?你可以加載所有的圖像一次,只是重新使用這些副本? (也就是說,重新加載它們都應該相當便宜。)這是在OnPaint()嗎?您是否重繪了所有內容或只是改變了什麼/請求重繪了什麼?你究竟如何爲這些作品下方的方塊着色 - 效率如何? – Rup 2012-07-05 14:35:19

+1

一個很好的舊雙緩衝技術將幫助你很多,並加上@rup建議以避免每次調用FromFile。 – 2012-07-05 14:36:57

回答

7

你調用在每次刷新Image.FromFile,對於每一個形象 - 從磁盤每次重裝有效的每個圖像文件。

您是否考慮過加載圖像一次,並將結果Image存儲在某個有用的地方? (比方說,一個數組,Image[2,6]就足夠了)

+0

很好看。這使零感覺和嚴重創造滯後。 – TomTom 2012-07-05 14:37:29

+0

我從來沒有這樣做。謝謝,我會試試看! – 2012-07-05 15:27:56

3

爲什麼你每次重繪板?難道你不能把板子留在原來的位置,並在其上顯示背景透明的圖像?這樣你就有一張圖像作爲背景(電路板),再加上64張放在電路板上的較小圖像,只需更改每次移動時顯示的圖像即可。

這樣一來,就可以讓Windows處理繪圖...

另外,裝載片的圖像在應用程序的開始。

+0

聽起來很有趣。你能舉個例子嗎? – 2012-07-05 15:26:22

+0

還有一個圖像控制板。然後,放置8x8更小的圖像控件(通過網格佈局管理器)放置在電路板上。圖像控件可以在運行時根據棋子綁定到圖像上... – 2012-07-06 07:17:36

0

好了,你看這個:

不要清除整個董事會,但只需要清除那些部分。

備選:

更新到WPF - 它移動繪製到圖形卡 - ,只是左右移動件,以智能的方式(即,具有用於每一塊的控制/對象)。

+0

我在考慮這個問題,但沒有提出一個好的方法。你能給我一個代碼樣本嗎? – 2012-07-05 15:25:17

1

除了不能打電話Image.FromFile()updateGraphics()(這絕對是你最大的問題),你不應該試圖重新繪製整個電路板的每個在每次調用updateGraphics() - 大部分時間,只有一小部分的董事會將失效。

PaintEventArgs包含參數ClipRectangle,它指定了電路板的哪個部分需要重新繪製。看看你不能找出哪些瓷磚與矩形相交,並重繪那些磚:)

提示:寫一個函數Point ScreenToTileCoords(Point)這需要一個屏幕座標,並返回其板平鋪在該座標。然後,你需要重新繪製的唯一瓦片

Point upperLeftTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Left, e.ClipRectangle.Top); 
Point lowerRightTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Right - 1, e.ClipRectangle.Bottom- 1); 

此外,還要確保你的控制是雙緩衝,以避免撕裂。這比上述評論中的@Steve B的鏈接簡單得多;假設這是一個UserControl,只需設置

this.DoubleBuffered = true; 
+0

我會盡力,謝謝。 – 2012-07-05 15:41:18

+0

檢查緩存在form1中的Duoble。我會研究那個clipRectangle的東西。 – 2012-07-05 15:51:08