Archived

This topic is now archived and is closed to further replies.

GDI and Back Buffer Headaches

This topic is 5813 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''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

Share this post


Link to post
Share on other sites
You are on the right track, but instead of using a second DC, you need to use a BITMAP. I''d give you links, but most MFC books talk about this, and there are a few articles (try codeguru.com). Anyways, you do the GDI calls onto the bitmap, and then copy the bitmap to the DC. That''s a simplified way to doing it.

-ZaneX

Share this post


Link to post
Share on other sites