Eliminating Flicker with Double Buffering


The sprite manager is now complete and ready to use within a program example. However, one bit of unfinished business needs to be addressed before pressing onward with an example. You might have noticed an annoying flicker in all the animated examples throughout the book thus far. This flicker is caused by the fact that the background image on the game screen is repainted before painting the animated graphics. In other words, animated graphics objects are erased and repainted each time they are moved. Because the erase and repaint process is taking place directly on the game screen, the image appears to flicker. To better understand the problem, imagine a movie in which a blank background is displayed quickly in between each frame containing actors that move. Although the film is cooking along at a fast enough pace to give the illusion of movement, you would still see a noticeable flicker because of the blank backgrounds.

The flicker problem associated with sprite animation can be solved using a technique known as double buffering . In double buffering, you perform all of your erasing and drawing on an offscreen drawing surface that isn't visible to the user . After all the drawing is finished, the end result is painted straight to the game screen in one pass. Because no visible erasing is taking place, the end result is flicker-free animation. Figure 11.1 shows the difference between traditional single-buffer animation and double-buffer animation that eliminates flicker.

Figure 11.1. Double-buffer animation eliminates the annoying flicker associated with drawing directly to the game screen with a single buffer.

graphics/11fig01.gif

graphics/book.gif

A buffer is simply an area in memory to which you are drawing graphics. The buffer in traditional single-buffer animation is the game screen itself, whereas double-buffer animation adds an offscreen memory buffer to the equation.


Figure 11.1 reveals how an offscreen memory buffer is used to perform all the incremental animation drawing, with only the finished image being drawn to the game screen. This might sound like a tricky programming problem, but double-buffering is really not very hard to incorporate into your games . The first step is to add two global variables to keep track of the offscreen device context and bitmap that serve as the offscreen buffer. Following is an example of how to create these global variables :

 HDC     _hOffscreenDC; HBITMAP _hOffscreenBitmap; 

With these variables in place, you need to create the offscreen device context and then use it to create an offscreen bitmap the same size as the game screen. The offscreen bitmap then needs to be selected into the offscreen device context, and you're ready to go. The following code shows how these tasks are accomplished:

 // Create the offscreen device context and bitmap _hOffscreenDC = CreateCompatibleDC(GetDC(hWindow)); _hOffscreenBitmap = CreateCompatibleBitmap(GetDC(hWindow),   _pGame->GetWidth(), _pGame->GetHeight()); SelectObject(_hOffscreenDC, _hOffscreenBitmap); 

You now have an offscreen bitmap the same size as your game screen that is selected into an offscreen device context to which you can draw. The following code reveals how easy it is to use the offscreen device context and bitmap to add double-buffer support to the paint code in a game:

 // Obtain a device context for repainting the game HWND  hWindow = _pGame->GetWindow(); HDC   hDC = GetDC(hWindow); // Paint the game to the offscreen device context GamePaint(_hOffscreenDC); // Blit the offscreen bitmap to the game screen BitBlt(hDC, 0, 0, _pGame->GetWidth(), _pGame->GetHeight(),   _hOffscreenDC, 0, 0, SRCCOPY); // Cleanup ReleaseDC(hWindow, hDC); 

This code would fit in perfectly in a GameCycle() function. The familiar GamePaint() function is passed the offscreen device context, which means that all the game painting takes place offscreen. The resulting image is then painted, or blitted , to the game screen's device context at once, which eliminates the possibility of flicker. Notice that this code is structured so that you don't have to do anything special in the GamePaint() function.

It's still important to clean up after yourself, and the following code shows how to clean up the offscreen bitmap and device context:

 // Cleanup the offscreen device context and bitmap DeleteObject(_hOffscreenBitmap); DeleteDC(_hOffscreenDC); 

Although the double-buffer code isn't technically part of the sprite manager, it is nonetheless an important improvement to sprite animation, and a technique you should definitely use in all of your future sprite animation programs. The next sections build on what you've learned thus far in this hour to revamp the Fore program example from the previous hour to support the sprite manager and double-buffer animation.



Sams Teach Yourself Game Programming in 24 Hours
Sams Teach Yourself Game Programming in 24 Hours
ISBN: 067232461X
EAN: 2147483647
Year: 2002
Pages: 271

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net