簡単なアニメーションやゲームなどを作成したとき、キャラクタの数が多いと画面がちらつく事があります。
これは WM_ERASEBKGND メッセージで背景を描画してから、WM_PAINT メッセージで図形などを描画するためです。
通常は、この仕組みで先にキャラクタの背景が描画され、その後にキャラクタを描画するからゲームなどで
キャラクタを連続的に描画すると毎回キャラクタが背景と共に消去されます。これがちらつきの原因です。
それでは、どうやったらちらつきをなくせるのか。
その方法の一つに[ダブル・バッファリング]という方法があります。
WM_PAINT メッセージの処理だけ紹介します。
(1)裏画面であるオフスクリーンにアニメーションなどの背景とキャラクタを全て描画。
(2)表画面であるクライアント領域にオフスクリーンの画像を一気に描画。
なお、WM_ERASEBKGND メッセージは処理しないようにします。
これを忘れると背景が毎回消去されてちらつきを防げません。
それでは具体的なプロシージャの記述を紹介します。
サンプル
// break付きのキーワード #define CASE break;case #define DEFAULT break;default // オフスクリーンの画面サイズ #define MAX_WIDTH (640) #define MAX_HEIGHT (480) // ウインドウ・プロシージャの関数 LRESULT CALLBACK mainWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static HBITMAP hBitmap; // ビットマップ static HDC hMemDC; // オフスクリーン static UINT saveX; static UINT saveY; switch ( uMsg ){ CASE WM_CREATE: { HDC hDC; // DCコンパチブルの作成 hDC = GetDC( hWnd ); hMemDC = CreateCompatibleDC( hDC ); hBitmap = CreateCompatibleBitmap( hDC, MAX_WIDTH, MAX_HEIGHT ); SelectObject( hMemDC, hBitmap ); SelectObject( hMemDC, GetStockObject(DC_PEN) ); SelectObject( hMemDC, GetStockObject(DC_BRUSH) ); ReleaseDC( hWnd, hDC ); } CASE WM_CLOSE: // DCコンパチブルの破棄 DeleteDC( hMemDC ); DeleteObject( hBitmap ); DestroyWindow( hWnd ); CASE WM_DESTROY: PostQuitMessage( 0 ); CASE WM_PAINT: { PAINTSTRUCT ps; HDC hDC; // DCコンパチブルの描画 hDC = BeginPaint( hWnd, &ps ); BitBlt( hDC, 0, 0, MAX_WIDTH, MAX_HEIGHT, hMemDC, 0, 0, SRCCOPY ); EndPaint( hWnd, &ps ); } CASE WM_ERASEBKGND: // 何も処理しない⇒塗り潰した return 1; CASE WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: { UINT cx = (SHORT)LOWORD(lParam); UINT cy = (SHORT)HIWORD(lParam); if ( GetKeyState(VK_SHIFT) < 0 ){ cx = saveX += 16; cy = saveY += 16; } SetDCPenColor( hMemDC, RGB(0xFF,0xFF,0x00) ); SetDCBrushColor( hMemDC, RGB(0x00,0x00,0xFF) ); Rectangle( hMemDC, cx, cy, (cx + 16*5), (cy + 16*3) ); InvalidateRect( hWnd, NULL, FALSE ); } CASE WM_RBUTTONUP: saveX = 0; saveY = 0; PatBlt( hMemDC, 0, 0, MAX_WIDTH, MAX_HEIGHT, BLACKNESS ); InvalidateRect( hWnd, NULL, FALSE ); DEFAULT:return DefWindowProc( hWnd, uMsg, wParam, lParam ); } return 0; }
※コメント投稿者のブログIDはブログ作成者のみに通知されます