Search code examples
c#winformsgdi+doublebuffered

Why should I do manual double buffering?


I am working on a game in C# (either 2.0 or 3.5 havn't decided yet). The game will be played on a map with a hexagonal grid. I appreciate that the UI for this map should use double buffering (lots of layers, so slow drawing). I know that I can enable double buffering through a style, or create my own buffer and handle it myself. Most recomendations I find on the web are to handle it yourself. I am wondering why? Obviously this allows me to avoid the assumptions that are inherent in the control double buffering, but I do not know what those assumptions are.

Again, I am not looking for code to explain how to double buffer my control, but rather why I would build this myself instead of using the double buffering style and allowing the CLR/Control class to handle it?


Solution

  • In WFA, double-buffering slows performance without completely eliminating flicker in custom graphics areas. For built-in GUI elements, like if you create a game built out of ImageButtons and Labels, the built-in double-buffered mode is great at hiding the redrawing of the control tree. However, there are a couple major problems with using it for a custom drawing area:

    • The draw buffer created when you just set up the application to draw double-buffered is used to draw the whole window and all child controls, not just your custom drawing area, so you add the overhead of redrawing every GUI element on the back buffer before page-flipping.
    • If anything invalidates the control, the Paint method is called. You may not be finished drawing when that happens and so you'll get an incomplete image shown to the user (not good in real-time graphics).

    By keeping the basic window GUI single-buffered, but creating an area on which you control the buffering, both of these problems are minimized.

    Double-buffering methods can be as simple as creating a Bitmap object as a back-buffer and drawing it to the draw area when you're good and ready, or setting up a seperate BufferedGraphicsContext to manage buffering of your custom draw area.