前回はDirectDrawオブジェクトとプライマリサーフェィスを作成し、プライマリサーフェィスに書きこんでみました。ただDirectDrawで描画する時には、プライマリサーフェィスに直接描くのではなく、プライマリサーフェイスと同じ大きさ・形式の「バックバッファ」に描画してそれをプライマリサーフェィスに「フリップ」する事が多いようです。フリップとは、プライマリサーフェイス(表示面)とバックバッファ(描画用ビットマップ)を一瞬にして「切り替える」もので、フリップすると瞬時にバックバッファの内容が画面に表示されます。
今回は、このバックバッファを持つプライマリサーフェイスを作成し、バックバッファに書きこんでその内容をフリップしてみましょう。
バックバッファに描画するには、まずバックバッファを利用できるプライマリサーフェイスを作りそのプライマリサーフェイスに「アタッチ」されたバックバッファを取得します。これで、バックバッファをサーフェイスとして扱えるようになるので、後はプライマリサーフェイス同様ロックして直接書きこんだりGDIで描画する事が出来るようになるわけです。ただし、バックバッファをフリップ出来るのは全画面モードだけなので注意してください。
バックバッファを利用できるプライマリサーフェイスは、以下のようにして作成します。
ddsd.dwSize=sizeof(ddsd); ddsd.dwFlags=DDSD_CAPS| DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE| DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL);
プライマリサーフェイスのみ利用する時との違いは、サーフェイスの「能力」を指定するdwCapsでフリップ可能を示すDDSCAPS_FLIPと複合サーフェイスを示すDDSCAPS_COMPLEXを指定し、さらにバックバッファの数(dwBackBufferCount)を1に設定している点ですね。 これで、プライマリサーフェイスにバックバッファが用意されたので、後はそのバックバッファへの参照をプライマリサーフェイスオブジェクト(と言えるのかな)の関数GetAttachedSurfaceで取得します。
ddscaps.dwCaps = DDSCAPS_BACKBUFFER; lpDDSPrimary->GetAttachedSurface(&ddscaps,&lpDDSBack);
プログラムを実行するとバックバッファに白い領域が書きこまれ、それが明るさを変えながら上下に動いて行きます。
これは、まずバックバッファ全体(640×480ピクセル)を0(黒のパレット番号)で初期化し、次に640×dwHeightピクセル分64−255の数値(bPl)を書き込んで行く事で処理しました。バックバッファへの書きこみは、前回同様サーフェイス(バックバッファ)をロックしてから取得したアドレスに書きこんでいます。
フリップは垂直帰線回帰を待って行われるようなので、特に調整しないでも安定した周期で実行されていますね。
void draw(void) { // バックバッファに描画、フリップ lpDDSBack->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); BYTE* lpBuf=(BYTE*)ddsd.lpSurface; FillMemory(lpBuf,640*480,0); FillMemory(lpBuf,640*dwHeight,bPl); lpDDSBack->Unlock(NULL); lpDDSPrimary->Flip(NULL, DDFLIP_WAIT); if (dwHeight==479) dwDHeight=-1; else if (dwHeight==0) dwDHeight=1; dwHeight+=dwDHeight; if (bPl==255) dwDPl=-1; else if (bPl==64) dwDPl=1; if (dwHeight % 2==0) // 2周期に一度色変更 bPl+=dwDPl; }
プログラムをコンパイルする時には、DirectX5以上のSDKをインストールする必要があります。ソースをダウンロードしたら、拡張子をcppにしてプロジェクトの設定でddraw.libをリンクしてからビルドしてください。
エスケープキーを押すと終了します。