• Advertisement
Sign in to follow this  

Flicker Problem and Double Buffering

This topic is 4383 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
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);

Share this post


Link to post
Share on other sites
I have the frame rate set to 30, so GameCycle() goes through 30 times each second.

Share this post


Link to post
Share on other sites
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 operation
    bool 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 ;
    }

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement