I''m just starting to learn game programming in C++, and I''ve been going through the "Game Programming Genesis" series. I decided to take a moment after the 3rd article to write a simple pong game using only GDI. I wrote a simple bitmap and sprite class, and was successful in getting a few graphics on the screen, but after putting more than one graphic up, I noticed terrible flicker. I figured a back buffer would help, so I tried to implement one using a memory device context. All I got was a blank screen. Here''s my main loop:
CSprite* board = new CSprite(0, 0, BOARD, hInstance);
CSprite* paddle = new CSprite(20, p1Y, PADDLE1, hInstance);
// main loop - inifinite (can only be exited by encountering WM_QUIT)
while(TRUE)
{
// check the message queue
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT) // exit loop on quit
break;
// send the message on its merry way
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// GetTickCount() returns the number of milliseconds since
// the system was started. It''s a good way to lock your display
// to a certain frame rate,
nStartTime = GetTickCount();
// update the display
paddle->draw(hBackDC);
board->draw(hBackDC);
// Swap the surfaces
BitBlt(hMainDC,0,0,scrWidth,scrHeight,hBackDC,0,0,SRCCOPY);
DeleteObject(WhiteBrush);
if (KEYSTATE(VK_UP))
paddle->SetY(p1Y++);
if (KEYSTATE(VK_DOWN))
paddle->SetY(p1Y--);
// lock to 30 FPS - 33ms per frame
while ((GetTickCount() - nStartTime) < 33);
// post a WM_CLOSE message if escape key is being pressed
if (KEYSTATE(VK_ESCAPE))
PostMessage(hwnd, WM_CLOSE, 0, 0);
}
as well as the class definitions:
class CBitmap
{
public:
//Constuctors
CBitmap() { mWidth=mHeight=0; }
CBitmap( int nResID ) { mResID=nResID; }
~CBitmap() { DeleteDC(mSrcDC); }
// Member Functions
int LoadBitmapResource(HINSTANCE hinst);
void SetRes( int nResID ) { mResID=nResID; }
HDC GetSrcDC() { return mSrcDC; }
int GetWidth() { return mWidth; }
int GetHeight() { return mHeight; }
private:
int mWidth, mHeight;
int mResID;
HDC mSrcDC;
HBITMAP mHbitmap;
};
class CSprite
{
public:
//Constuctors
CSprite() { mX=mY=mWidth=mHeight=0; }
CSprite( int nX, int nY, int nResID, HINSTANCE hinst );
~CSprite() { delete mBitmap; }
// Member Functions
void draw(HDC &hDestDC);
void SetY( int nY ) { mY = nY; }
private:
int mX, mY, mWidth, mHeight;
int mResID;
CBitmap* mBitmap;
};
and the class implementations:
int CBitmap::LoadBitmapResource(HINSTANCE hinst)
{
BITMAP bmp; // structure for bitmap info
// first load the bitmap resource
if ((mHbitmap = (HBITMAP)LoadImage(hinst, MAKEINTRESOURCE(mResID),
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION)) == NULL)
return(FALSE);
// create a DC for the bitmap to use
if ((mSrcDC = CreateCompatibleDC(NULL)) == NULL)
return(FALSE);
// select the bitmap into the DC
if (SelectObject(mSrcDC, mHbitmap) == NULL)
return(FALSE);
// get image dimensions
if (GetObject(mHbitmap, sizeof(BITMAP), &bmp) == 0)
return(FALSE);
mWidth = bmp.bmWidth;
mHeight = bmp.bmHeight;
// return success!
return(TRUE);
}
// CSprite Implementations
// ======================================================
CSprite::CSprite( int nX, int nY, int nResID, HINSTANCE hinst )
{
mX=nX;
mY=nY;
mResID=nResID;
mBitmap = new CBitmap();
mBitmap->SetRes(mResID);
mBitmap->LoadBitmapResource(hinst);
mWidth=mBitmap->GetWidth();
mHeight=mBitmap->GetHeight();
}
void CSprite::draw(HDC &hDestDC)
{
// copy image from one DC to the other
BitBlt(hDestDC, mX, mY, mWidth, mHeight, mBitmap->GetSrcDC(), 0, 0, SRCCOPY);
}
I know that''s a lot of code, but I''m really lost, and I''m sure I''m just inexperienced enough to miss what''s going on. Any help would be appreciated.
Matt ''''Mix'''' Fox
mix@coil-inc.com