1

I'm workning on a project in C#, Windows form, and I require a grid of squares to do that. I have been able to generate the squares, but the problem is that I need to generate up to 20,736 of them. I was able to this in C++ without any issues using the SDL library, but in C# I am expierencing very bad lag with so many squares.

I want the squares to update every 1/100th of a second so I am using a timer to redraw the squares then, but the lag is incredible. I first tried to generate a grid of buttons, but the program just stopped. Then I tried a grid of PictureBoxes, imporvement, but not much, and then I tried Pen and Rectangle which yielded improvement too. So what is the most efficient way to draw 20,000 squares to the screen?

    //Timer that ticks every 1/100th of a second 

    public void MyTimer_Tick(object sender,EventArgs eArgs)   {
          count++;
          numLabel.Text = count.ToString();
          for (int i = 0; i < 60; i++)
          {
              for (int j = 0; j < 60; j++)
              {
                  editSquares((i * (18 + 2)), (j * (18 + 2)), 18, 18, Color.Black);
              }
          }
    }

    //Draw a square

    public void drawSquares(int x, int y, int w, int h)
    {
        cell = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
        System.Drawing.Graphics formGraphics = this.CreateGraphics();
        formGraphics.FillRectangle(cell, new Rectangle(x, y, w, h));
        formGraphics.Dispose();
        cell.Dispose();
    }

    //Edit Squares      

    public void editSquares(int x, int y, int w, int h,Color color)
    {
        cell = new System.Drawing.SolidBrush(System.Drawing.Color.Red);
        cell.Color = color;
        System.Drawing.Graphics formGraphics = this.CreateGraphics();
        formGraphics.FillRectangle(cell, new Rectangle(x, y, w, h));
        cell.Dispose();
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ben Elo
  • 73
  • 1
  • 11

2 Answers2

1

Instead of creating and disposing the Brush each time in editSquares, at startup create a brush for each color you need, then pass in the relevant brush as a parameter. Same goes for the Graphics object.

However, probably the best efficiency gain can be made by only redrawing those cells that have changed - thanks to Kal_Torak for pointing this out.

Surfbutler
  • 1,529
  • 2
  • 17
  • 38
  • 1
    Good question, maybe the OP is best placed to answer that though :) – Surfbutler Jul 26 '12 at 22:17
  • I forgot about the whole 60fps. I'll change that, thanks. And I don't understand how to change values on a specific rectangle in the grid, that's why I was writing and rewriting every time. – Ben Elo Jul 26 '12 at 22:20
  • 1
    I'm pretty sure you can't change the value of a rectangle in Winforms, as it's a graphics primitive that doesn't hold state (unlike a graphics object). By the way, WPF would be a better bet than Winforms for drawing speed, as it draws offscreen (and many more graphics hold their own state so you don't have to). – Surfbutler Jul 26 '12 at 22:36
  • So yesterday I made the Game of Life in C++ using SDL, I want to do this in C#. Can I use SDL again? Is WPF better then SDL? – Ben Elo Jul 26 '12 at 22:43
  • I'm going to have to disagree with @Surfbutler on this. I've personally spent the last 6 months or so doing a lot of custom low level WPF graphics, and it is NOT fast enough for 20,000 entities to be drawn at 60 FPS. I'm actually building an arcade game using WPF, and while the API itself is very enjoyable and convenient, it's simply not built for any kind of extensive realtime rendering. There is just too much inefficiency in how the rendering is handled under the hood. Don't get me wrong, I love WPF, but it's the wrong tool for this job. – Kal_Torak Jul 26 '12 at 22:51
  • 1
    Although, if you were not concerned with full redraw at 60FPS, you could probably do quite well with WPF if you only alter the cells that have changed. – Kal_Torak Jul 26 '12 at 23:05
  • DirectX would definitely work, though it's quite a lot more work to set up. You might want to look into using Direct2D specifically, if you're doing a 2D only game. – Kal_Torak Jul 27 '12 at 06:34
  • @Kal_Torak: Yes agree on WPF not being fast enough for 20,000 entities - was only pointing out it would be faster! :) +1 for your comment on only altering the changed cells. – Surfbutler Jul 27 '12 at 07:46
  • I changed the code to only alter the changed cells, and it ran much faster, but I'm still worried that if a user wanted to change all 20,000 entities then they'd expierence lag. – Ben Elo Jul 30 '12 at 17:27
  • @BenElo: Hmm, sorry to be negative but you might be approaching the limits of what is possible with a managed language. 20,000+ entities at 60fps, essentially rendered in real-time, is probably asking too much. Do you have a feel for how long each draw phase is actually taking if all 20,000 cells are changed? Also, have you actually achieved this in your C++ version? – Surfbutler Jul 31 '12 at 06:33
  • The SDL version worked very well in C++ because it set up all the rectangles and then drew them at the same time, instead of what I'm expierenceing in C# were it draws them one at a time. – Ben Elo Jul 31 '12 at 22:34
  • This is exactly what WPF does, as I explained earlier (though it still wouldn't be as quick as C++). You haven't fully answered my question by the way :) – Surfbutler Aug 01 '12 at 07:26
1

Have you tried the answer detailed here?

The top answer is identical to how we do it at work. Our applications aren't super graphics intensive (so I'm not guaranteeing that our solution is optimal), but I think the writeable bitmap lock may prevent unnecessary error checking or screen updates.

Community
  • 1
  • 1
Alex
  • 266
  • 1
  • 6