4:フリップ
さて、前回まででプライマリサーフィスが作成されました。
今回はそれをさらにDirectDrawらしい使い方でやってみようと思います。
「バックバッファとフリップ」
バックバッファとは何かというと、「次に表示される画面を保存してあるサーフィス」です。
つまり、バックバッファに書き込み、それを全部プライマリに転送する訳ですね。
しかし、全部プライマリに転送するとなると、その間は何も出来なくなります。そこで「フリップ」と言う機能が出てきます。
これは全部転送せずに、直接バックバッファとプライマリを入れ替え(スワップ)てしまう訳です。
フリップのおかげで、システムが画面を表示している間もプログラム側では次に表示する画面をバックバッファに書き込める訳です。
さらにチラツキもなくなるので一石二鳥です。
では実際にやってみましょ
LPDIRECTDRAWSURFACE lpDDSBack;
・・・
// プライマリサーフィスの作成
// 設定した分のバックバッファも作成されます。
DDSURFACEDESC ddsd;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1; // バックバッファは1個
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
lpDD->CreateSurface(&ddsd,&lpDDSPrimary,0);
// 作成されたバックバッファを取得
DDSCAPS ddsCaps;
ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
lpDDSPrimary->GetAttachedSurface(&ddsCaps,&lpDDSBack);
・・・
// アイドル処理関数内
// フリップ
if(lpDDSPrimary->Flip(0,DDFLIP_WAIT)!=DD_OK) return 1;
サーフィスを使うときに、もう一つやらなければならない事があります。
前のプログラムを起動し、Alt+Tabで別のプログラムに移ってからまたもどると
真っ黒になって何も表示されないと思います。つまりサーフィスが消失してしまったわけです。
これではダメなのでサーフィスを取り戻さないといけません、このときに Restore と言うのを使います。
また、Alt+Tab で別のプログラムに移っている間中はアイドル処理をしないように変更します。
// WindowProc関数内…
・・・
case WM_ACTIVATEAPP:
{
// アクティブでフォアグラウンドで非アイコンなら TRUE
bActive = (BOOL)wp && GetForegroundWindow() == hWnd && !IsIconic(hWnd);
// サーフィスチェック
if(lpDDSPrimary && lpDDSPrimary->IsLost() == DDERR_SURFACELOST
|| lpDDSBack && lpDDSBack->IsLost() == DDERR_SURFACELOST)
{
// プライマリの方をリストアするだけで、バックバッファも戻ります。
// Restoreに失敗したらアクティブを取り消します。
if( !lpDDSPrimary || lpDDSPrimary->Restore()!=DD_OK) bActive=false;
}
}break;
・・・
// WinMain関数内
・・・
while(1)
{
// メッセージがないときにアイドル処理
while(win.bIdle && win.bActive && !PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
win.Idle(); // アイドル処理
}
・・・
リストアするときも、リリースするときも、バックバッファはプライマリにくっついているので
わざわざバックバッファを弄る必要はありません。
さて、これではれて完成です(今回は)。
実際起動してみれば分かりますが全然チラツキません(FPS表示の所なんかね)。
FPSが落ちれば、フリップしている様子がよく分かります(^^ゞ。
次回はビットマップを表示してみます。