Skip to main content
GameDev.net gamedev.net
🔒 Locked

Flicker Problem and Double Buffering

Started by furinto Jan 19, 2006 at 10:27 PM 3 replies 1.4k views
Original Post
furinto
furinto
I have in my game some code to use an offscreen device context (buffer) to elimate bitmap flickering in my game as everything is redrawn each cycle. The code is taken from source code included with a book, and i've seen it work before. But for some reason, I still get flickering in the game i'm creating myself. These are delarations in my header file:
HDC         _hOffscreenDC;
HBITMAP     _hOffscreenBitmap;

This is my GameCycle() function:
void GameCycle()
{

  if (!_bGameOver)
  {
    // Update the sprites
    _pGame->UpdateSprites();

    // 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);
      
    // Force a repaint to redraw the sprites
    InvalidateRect(_pGame->GetWindow(), NULL, FALSE);

    // Cleanup
    ReleaseDC(hWindow, hDC);
  }
}

Can anybody suggest what I should do if this isn't eliminating flickering? Also, I feel I should point out that I get no errors. It compiles and runs without a hitch. I just don't see the buffer working the way I guess I think it should.
Skeleton_V@T
Skeleton_V@T
Does your GameCycle () run at hundreds loops per second ?.

If so, consider moving your GameCycle () function into the process of WM_PAINT message instead. Win32 GDI functions are not designed to be called rapidly in a loop (Windows takes care of many underlying things that makes GDI functions very slow). You window should be redrawn when necessary also.

One alternative: You may create a timer with an appropriate interval then move this line to the timer function:
    // Force a repaint to redraw the sprites    InvalidateRect(_pGame->GetWindow(), NULL, FALSE);
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
furinto
furinto
I have the frame rate set to 30, so GameCycle() goes through 30 times each second.
Skeleton_V@T
Skeleton_V@T
Flickering is a common phenomenon with Win32 drawing functions, at the easiest you may try drawing a rectangle moving from the left to the right side of the client area, even at low frame rate (30 FPS) you may notice the artifact.

The best alternative is to switch to a real graphics API such as OpenGL, in case you don't want to mess with it (yet), you may try the following solutions:

  1. If you have set a valid window background, set it back to NULL then clear the client area yourself in your drawing routine.
  2. Update things need to be updated: You calculate the bounding rectangles of the moved objects, then pass that RECT struct to InvalidateRect (), it may reduce flickering. You may BitBlt () only that rectangle as well.
  3. I've rewritten your code a bit (not much, but it has improvements):
    //Besure to notice the caller about the result of the operationbool GameCycle(){  if (!_bGameOver)  {    // Update the sprites    _pGame->UpdateSprites();    // Obtain a device context for repainting the game    HWND  const hWindow = _pGame->GetWindow(); //Be const-correct    HDC   const hDC = GetDC(hWindow); //Be const-correct    if (hDC == NULL) return false ; //Don't forget to check the return value,                                    //especially with Win32 API functions    // Paint the game to the offscreen device context    GamePaint(_hOffscreenDC) ;    // Blit the offscreen bitmap to the game screen    if (!BitBlt(hDC, 0, 0, _pGame->GetWidth(), _pGame->GetHeight(),        _hOffscreenDC, 0, 0, SRCCOPY)) return false ;          // Force a repaint to redraw the sprites    if (!InvalidateRect(hWindow, NULL, FALSE)) return false ; //You may reuse hWindow here    // Cleanup    if (!ReleaseDC(hWindow, hDC)) return false ;  }  //No error      return true ;}
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
mark_dev
mark_dev
The InvalidateRect after you blit will cause Windows to think the window needs updating. What do you have in your WM_PAINT handler? If it draws/clears anything that could be the cause of your flicker.

If you keep the loop as it is, you should blit the offscreen to the main window on WM_PAINT and mark the window as updated. Then dont invalidate in game cycle or possibly use ValidateRect(...) for the rectangle you do blit.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.