2016-03-29 8 views
3

私は現在C#でタイルベースのゲームを作っていますが、タイルを描画するたびに多くのCPUを使い、タイルが大きくなるにつれて(ゲームをフルスクリーンにすると)、それはもっと消費します。 これは私のタイルクラスです:Graphics.Drawを使用して効率的にタイルをレンダリングするには?

public class Tiles 
{ 
    //PRIVATE : 

    //variabiles 
    private int XPosition, YPosition; 
    private Image Texture; 
    private bool Colidable; 
    private int SizeW = 32; 
    private int SizeH = 32; 
    private Resizer resizer = new Resizer(); 
    //methods 




    //PUBLIC : 

    //variabiles 


    //methods 

    //CONSTRUCTOR 
    public Tiles(int _x,int _y,Image _i, int _sW = 32, int _sH = 32, bool _c = false) 
    { 
     XPosition = _x;//set position X 
     YPosition = _y;//set position Y 
     SizeW = _sW; 
     SizeH = _sH; 
     Texture = resizer.ResizeImage(_i, SizeW, SizeH) ;// set texture 

     Colidable = _c;//set if the tile is colidable,default : false 
     resizer = null; 
    } 

    //DRAW METHOD 
    //gets graphics object to draw on, adn draws at the position of the tile 
    public void Draw(Graphics _g) 
    { 
     _g.DrawImage(this.Texture, this.XPosition, this.YPosition); 
    } 

    //GET PRIVATE MEBERS 
    //returns if the tile is colidable 
    public bool getColidable() 
    { 

     return this.Colidable; 

    } 
} 

、これは私がタイルを描く方法です:

private void DrawMap(Graphics _g) 
    { 
     //CALLS THE DRAW METHOD OF EACH TILE 
     for (int i = 0; i < MAP_WIDTH; i++) 
     { 
      for (int j = 0; j < MAP_HEIGHT; j++) 
      { 
       Tile[i, j].Draw(_g); 
      } 

     } 

    } 
    bool TilesUpdate = false; 


    private void _Window_Paint(object sender, PaintEventArgs e) 
    { 
     e.Graphics.Clear(Color.Black); 

     if (isGameRunning) 
     { 

      DrawMap(e.Graphics); 
     } 
     else 
     { 
      FullRezolutionBtn.Draw(e.Graphics); 
      BigRezolutionBtn.Draw(e.Graphics); 
      NormalRezolutionBtn.Draw(e.Graphics); 
     } 

    } 


    private void Update_Tick(object sender, EventArgs e) 
    { 
     Invalidate(); 

    } 

私はマップが20×20のタイルであり、それがの50%前後をcosumingだことを言及したいと思いますcpuをフルスクリーンで表示します。

+0

投稿したコードは大丈夫ですが、スピードアップの仕方はわかりません。スマートな無効化とスマートな描画を試してください(無効化された部分のみを描画します) –

+0

パーツが無効になっているかどうかを確認するにはどうすればよいですか? –

+0

'e.ClipRectangle.IntersectsWith(part.Rectangle)' –

答えて

1

私がコメントで言及したように、方向は絵を少なくすることであるべきです。 1つの方法は、その部分に関連するものが変更された場合にのみ、描画キャンバスの部分を無効にしてペイントすることです。 Windows自体は、コントロール/ウィンドウの最適化を行います。

ここは例です。どのようにGadgetクラスは、いくつかのプロパティが変更されたときにそのクラスの長方形を無効にします。次に、ペイント中にe.ClipRectangeと交差する矩形だけが描画されます。これにより、描画操作の数が大幅に削減されます。

using System; 
using System.Drawing; 
using System.Windows.Forms; 

namespace Samples 
{ 
    class Gadget 
    { 
     public readonly Control Canvas; 

     public Gadget(Control canvas) { Canvas = canvas; } 

     private Rectangle bounds; 
     public Rectangle Bounds 
     { 
      get { return bounds; } 
      set 
      { 
       if (bounds == value) return; 
       // NOTE: Invalidate both old and new rectangle 
       Invalidate(); 
       bounds = value; 
       Invalidate(); 
      } 
     } 

     private Color color; 
     public Color Color 
     { 
      get { return color; } 
      set 
      { 
       if (color == value) return; 
       color = value; 
       Invalidate(); 
      } 
     } 

     public void Invalidate() 
     { 
      Canvas.Invalidate(bounds); 
     } 

     public void Draw(Graphics g) 
     { 
      using (var brush = new SolidBrush(color)) 
       g.FillRectangle(brush, bounds); 
     } 
    } 


    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      var form = new Form { WindowState = FormWindowState.Maximized }; 
      int rows = 9, cols = 9; 
      var gadgets = new Gadget[rows, cols]; 
      var rg = new Random(); 
      Color[] colors = { Color.Yellow, Color.Blue, Color.Red, Color.Green, Color.Magenta }; 
      int size = 64; 
      var canvas = form; 
      for (int r = 0, y = 8; r < rows; r++, y += size) 
       for (int c = 0, x = 8; c < cols; c++, x += size) 
        gadgets[r, c] = new Gadget(canvas) { Color = colors[rg.Next(colors.Length)], Bounds = new Rectangle(x, y, size, size) }; 
      int paintCount = 0, drawCount = 0; 
      canvas.Paint += (sender, e) => 
      { 
       paintCount++; 
       for (int r = 0; r < rows; r++) 
       { 
        for (int c = 0; c < cols; c++) 
        { 
         if (e.ClipRectangle.IntersectsWith(gadgets[r, c].Bounds)) 
         { 
          gadgets[r, c].Draw(e.Graphics); 
          drawCount++; 
         } 
        } 
       } 
       form.Text = $"Paint:{paintCount} Draw:{drawCount} of {(long)paintCount * rows * cols}"; 
      }; 
      var timer = new Timer { Interval = 100 }; 
      timer.Tick += (sender, e) => 
      { 
       gadgets[rg.Next(rows), rg.Next(cols)].Color = colors[rg.Next(colors.Length)]; 
      }; 
      timer.Start(); 


      Application.Run(form); 
     } 
    } 
} 
+0

ありがとうございました!これはまさに私が探していたものです!非常にありがとう! –

0

リサイザクラスの仕組みが不明です。毎回すべてのイメージのサイズを変更するときに問題があると思います。

Texture = resizer.ResizeImage(_i, SizeW, SizeH) ;// set texture 

私は以下のようなタイルの描画機能を更新すると同時に、この

Texture = _i;// set texture but do not resize image now 

のように線の上に置き換えます。

public void Draw(Graphics _g) 
{ 
    //now specify the location and size of the image. 
    _g.DrawImage(Texture , new Rectangle(this.XPosition, this.YPosition, SizeW, SizeH)); 

} 

うまくいけば、パフォーマンスを向上させるはずです。 それがちらつければ使用することができますDouble Buffer

関連する問題