BitBlt in GDI
In order to get rid of some flickering in A GDI app Ive been working on, Ive decided to do some double buffering, bitbltting from one HDC to another. I have two global variables, mainHDC and backHDC. the following is the relevant code in my game:
if(!(hwnd=CreateWindow(WINDOW_CLASS_NAME,
"title",
WS_OVERLAPPEDWINDOW |WS_VISIBLE,
0,0,
WINDOW_WIDTH,WINDOW_HEIGHT,
NULL,NULL,
hinstance,
NULL)))
return(0);
mainHDC = GetDC(hwnd);
backHDC=CreateCompatibleDC(hwnd);
Game_Init(backHDC);
//main game loop
while(true)
{
Game_Main(backHDC,timer);
//game main performs some game logic, and uses
// Rectangle(backHDC,.....) for some basic graphics
BitBlt(backHDC,0,0,200,200,mainHDC,0,0,NULL);
}
the code works correctly if I replace backHDC with mainHDC. What have I done wrong?
(I know Im passing backHDC as a parameter here, which is an optimization mistake that I''ll get rid of soon)
assuming that BitBlt call you posted is the one that you wanted to have put the graphics to the screen, then you have your DCs flipped.
You need to make mainDC the destination and backDC the source. Also note that to get rid of flicker, either make sure the background brush is NULL or that you handle the WM_ERASEBKGND message.
"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
You haven''t created a bitmap to render onto for your offscreen image. You need to call CreateCompatibleBitmap and then SelectObject to assign the newly created bitmap to the offscreen DC.
Skizz
Skizz
I wrote my first GDI game with back buffer a few months ago. Make sure you are putting your graphics on the back dc, and then BitBlt to your front or main dc. Your BitBlt should be reversed
You have
BitBlt(backHDC,0,0,200,200,mainHDC,0,0,NULL);
Rather this should be
BitBlt(mainHDC,0,0,200,200,backHDC,0,0,NULL);
The first one is where its going (the destination), the second one is the source. Also I use SRCCOPY instead of NULL. Here is mine, taken from GameTutorials but I changed the variable names
// OUTSIDE WinMain()
// Initialize globals for window, instance, and dc
HWND game_window = NULL;
HINSTANCE game_instance = NULL;
HDC game_dc = NULL;
// for back (double) buffering
HDC back_dc = NULL;
HBITMAP back_bmp = NULL;
HBITMAP old_bmp = NULL;
RECT back_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
......
// INSIDE GameInit() or your init function called once before GameMain()
game_dc = GetDC(game_window); // get the GDI device context
// for back (double) buffering
back_dc = CreateCompatibleDC(game_dc);
back_bmp = CreateCompatibleBitmap(game_dc, WINDOW_WIDTH, WINDOW_HEIGHT);
old_bmp = (HBITMAP)SelectObject(back_dc, back_bmp);
.....
// INSIDE WinMain()
// erase the back buffer
FillRect(back_dc, &back_rect, black_brush);
GameMain(); // game main processing function called repeatedly
// copy back buffer to front buffer
BitBlt(game_dc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, back_dc, 0, 0, SRCCOPY);
.....
// INSIDE GameQuit() or your clean up called once at end
// release the back buffer
SelectObject(back_dc, old_bmp);
DeleteObject(back_bmp);
DeleteDC(back_dc);
// release the device context from the game window
ReleaseDC(game_window, game_dc);
Mine also goes full screen and you can do that in GDI with ChangeDisplaySettings( ) using a DEVMODE struct
VazGames.com
Phil P
[edited by - PhilVaz on July 28, 2003 4:24:00 PM]
You have
BitBlt(backHDC,0,0,200,200,mainHDC,0,0,NULL);
Rather this should be
BitBlt(mainHDC,0,0,200,200,backHDC,0,0,NULL);
The first one is where its going (the destination), the second one is the source. Also I use SRCCOPY instead of NULL. Here is mine, taken from GameTutorials but I changed the variable names
// OUTSIDE WinMain()
// Initialize globals for window, instance, and dc
HWND game_window = NULL;
HINSTANCE game_instance = NULL;
HDC game_dc = NULL;
// for back (double) buffering
HDC back_dc = NULL;
HBITMAP back_bmp = NULL;
HBITMAP old_bmp = NULL;
RECT back_rect = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
......
// INSIDE GameInit() or your init function called once before GameMain()
game_dc = GetDC(game_window); // get the GDI device context
// for back (double) buffering
back_dc = CreateCompatibleDC(game_dc);
back_bmp = CreateCompatibleBitmap(game_dc, WINDOW_WIDTH, WINDOW_HEIGHT);
old_bmp = (HBITMAP)SelectObject(back_dc, back_bmp);
.....
// INSIDE WinMain()
// erase the back buffer
FillRect(back_dc, &back_rect, black_brush);
GameMain(); // game main processing function called repeatedly
// copy back buffer to front buffer
BitBlt(game_dc, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, back_dc, 0, 0, SRCCOPY);
.....
// INSIDE GameQuit() or your clean up called once at end
// release the back buffer
SelectObject(back_dc, old_bmp);
DeleteObject(back_bmp);
DeleteDC(back_dc);
// release the device context from the game window
ReleaseDC(game_window, game_dc);
Mine also goes full screen and you can do that in GDI with ChangeDisplaySettings( ) using a DEVMODE struct
VazGames.com
Phil P
[edited by - PhilVaz on July 28, 2003 4:24:00 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement