-
Flickery API graphics
I'm experiencing some flickery graphics in this windows program. I tried using a double buffer, but I must've
done something wrong (though I'm pretty sure I did it all right).
Or is it that you cannot have completely flicker-free graphics in windows API, especially in this case where
a 640x480 screen is copied from the double buffer?
BmpPlayer and BmpTile are the HBITMAPs for the graphics.
I call this when the WM_PAINT message is sent (I invalidate the whole window if something is updated).
Code:
void RenderMap(HWND Handle)
{
//Data
RECT Rect;
PAINTSTRUCT PaintStruct;
HDC HdcWindow;
HDC HdcBitmap;
HDC HdcBuffer;
HBITMAP DoubleBuffer;
HBITMAP OldBuffer;
HBITMAP OldDevice;
//Setup
Rect.left = 0;
Rect.top = 0;
Rect.right = SCREENWIDTH;
Rect.bottom = SCREENHEIGHT;
HdcWindow = BeginPaint(Handle, &PaintStruct);
HdcBuffer = CreateCompatibleDC(HdcWindow);
DoubleBuffer = CreateCompatibleBitmap(HdcWindow, SCREENWIDTH, SCREENHEIGHT);
OldBuffer = (HBITMAP)SelectObject(HdcBuffer, DoubleBuffer);
//Clear background
FillRect(HdcBuffer, &Rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
//Draw the tiles
HdcBitmap = CreateCompatibleDC(HdcWindow);
OldDevice =(HBITMAP)SelectObject(HdcBitmap, BmpTile);
BitBlt(HdcBuffer, 32, 64, 32, 32, HdcBitmap, 0, 0, SRCCOPY);
BitBlt(HdcBuffer, 128, 96, 32, 32, HdcBitmap, 32, 0, SRCCOPY);
//Draw the items
//Draw the enemies
//Draw the effects
//Draw the player
SelectObject(HdcBitmap, BmpPlayer);
BitBlt(HdcBuffer, Header.StartPosition.X, Header.StartPosition.Y, 32, 64,
HdcBitmap, 0, 0, SRCCOPY);
//Copy data from buffer to window
BitBlt(HdcWindow, 0, 0, SCREENWIDTH, SCREENHEIGHT, HdcBuffer, 0, 0, SRCCOPY);
//Shutdown
SelectObject(HdcBuffer, OldBuffer);
DeleteDC(HdcBuffer);
SelectObject(HdcBitmap, OldDevice);
DeleteDC(HdcBitmap);
DeleteObject(DoubleBuffer);
EndPaint(Handle, &PaintStruct);
}
PS: This will only be the level editor for the game. The real game will be made in DX :).
-
when you invalidate the rect to update the window are you sure the eraseflag isn't set..?
cause that will cause flickering!
otherwise it's prettymuch up to you videocard but, offcourse depending on the amount you blt, I've had no problems with bliting 640x480 bitmaps...and my graphiccard is ****ty!!
/btq
-
Argh, you were right. The erase flag was set to TRUE.
It's fixed now, and no more flicker :).
Thanks alot for the quick answer!
-
-
With double buffering ALL the drawing should be done BEFORE the paint is called.
I have an array of structs (in my C progs) that contains all the details of a window. (HDCBuffer, HDCScreen, HWND ect)
When the app starts I create and init these.
While it runs they are global.
When it closes I free them.
Code:
resize DC's
draw to framebuffer
copy framebuffer to screenbuffer
call for paint
the actual paint function should not have any more in it than one BitBlt()
Code:
find update region (GetUpdateRect() )
BeginPaint
copy screenbuffer to paint DC (no stretching here)
EndPaint
also look at returning TRUE to any WM_ERASEBKGND msg's (if controls flicker rather than DC's).
-
Also could you put all this junk:
HdcBuffer = CreateCompatibleDC(HdcWindow);
DoubleBuffer = CreateCompatibleBitmap(HdcWindow, SCREENWIDTH, SCREENHEIGHT);
OldBuffer = (HBITMAP)SelectObject(HdcBuffer, DoubleBuffer);
and this:
HdcBitmap = CreateCompatibleDC(HdcWindow);
OldDevice =(HBITMAP)SelectObject(HdcBitmap, BmpTile);
into your WM_CREATE message.
And all the deleting stuff:
DeleteDC(HdcBuffer);
DeleteDC(HdcBitmap);
DeleteObject(DoubleBuffer);
into your WM_DESTROY
As your using them more or less permamently there is absolutely no use on creating them 5.000.000 times and destroying them immediately afterwards.
Also you could put the
(HBRUSH)GetStockObject(WHITE_BRUSH));
into WM_CREATE and use that handle from then on in your RenderMap... this reduces quite some overhead :)
-
>>Also could you put all this junk:
As long as you change the variables to STATIC's
And you can get the right HDC to create one compatible with.
Use GetDC() wth the HWND of the control or dialog or even the main screen (and remember to ReleaseDC() when finished with one you 'Get')
As I said
"When the app starts I create and init these.
While it runs they are global.
When it closes I free them. "
-
Thanks for the tips.
I already knew that it wasn't so good to recreate the double buffer in every render call, but since speed wasn't that big concern in this program, I was too lazy to do change it :D.