DirectDrawは、ビデオカードのビデオメモリに直接アクセスするバッファ(サーフェイス)を提供します。今表示されている画面を記憶したビデオメモリ領域は「プライマリサーフェイス」と呼ばれ、ここに直接ピクセルの情報を書きこむ事でその結果はただちに画面に反映されるわけです。さらにDirectDrawには、プライマリサーフェイスと同形式のバックバッファを複数とっておきそのバッファを一瞬のうちにプライマリサーフェイスに「フリップ」(切り替え)する機能もあるので、Windowsでも高速かつちらつきのない「ダブルバッファ」を実現できるようになりました(もっとも、これはDIBSectionでもある程度可能でしたが)。このような特長を活かして、最近では多くのゲームがDirectDrawベースになっていますね。 DirectDrawの使い方 DirectDrawを使うには、まずDirectDrawオブジェクトを作成し初期化します。作成にはDirectDrawCreateという関数を使い、この関数にLPDIRECTDRAW型ポインタのアドレスを渡すと、DirectDrawオブジェクトが生成されそのアドレスが関数に渡したLPDIRECTDRAW型ポインタに入るようです。 DirectDrawCreate(NULL,&lpDD,NULL ); // DIRECTDRAWオブジェクト作成 lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); // 動作モード設定 lpDD->SetDisplayMode(640,480,8); // 画面を640*480、256色モードに設定 DirectDrawオブジェクトを作成したら、次はビデオメモリにアクセスるためのプライマリサーフェイスを作りましょう。サーフェイスの作成には、DirectDrawオブジェクトのCreateSurface関数を使います。この関数は、引数にDDSURFACEDESC型構造体のアドレスやプライマリサーフェイスへのポインタをとるので、呼び出す前にDDSURFACEDESC型構造体を作成しておいてください。 FillMemory(&ddsd,0,sizeof(ddsd)); // DDSURFACEDESC構造体初期化 ddsd.dwSize=sizeof(ddsd); ddsd.dwFlags=DDSD_CAPS; ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE; lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL ); // プライマリサーフェイス作成 今回は、画面の色数が256色でしたので、パレットの設定も行います。 パレットの設定はPALETTEENTRY型配列を作成してDirectDrawオブジェクトのCreatePalette関数でパレットを作り、そのパレットをサーフェイスのSetPalette関数でパレットとして設定するだけです。 lpDD->CreatePalette(DDPCAPS_8BIT,pePal,&lpDPalette,NULL); // パレット作成 lpDPalette->SetEntries(0,0,256,pePal); // パレットの設定範囲指定 lpDDSPrimary->SetPalette(lpDPalette); // サーフェイスにパレット設定 プライマリサーフェイス(ビデオメモリ)へのアクセス プライマリサーフェイスにアクセスするには、まずサーフェイスを「ロック」します。これで、サーフェイスへのポインタをロックする時に渡したDDSURFACEDESC構造体のメンバ変数lpSurfaceから取得できるようになるので、後は読み書きするだけです。例えば、1ピクセル1バイト(8ビット)で640×480のサーフェイスなら、先頭からx+y×640を足したアドレスに書きこめば(x、y)のピクセルを書きかえられる事になります。なお、y方向の座標は、GDI同様上から下に増えていくようです。DIBとは逆なので、DIBファイルをそのまま転送する時などは、要注意ですね。 lpDDSPrimary->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); // サーフェイスをロック BYTE* lpVideoMemory=(BYTE*)ddsd.lpSurface; // サーフェイスへのポインタ取得 lpVideoMemory[x+y*640]=0; //(x,y)に0を書きこむ lpDDSPrimary->Unlock(NULL); // サーフェイスをアンロック アプリケーション終了時には、サーフェイス・DirectDrawオブジェクトともRelease関数で解放するようにしてください。 case WM_DESTROY : // 終了処理 lpDD->RestoreDisplayMode(); // 画面モードを元に戻す if (lpDDSPrimary) // サーフェイス解放 lpDDSPrimary->Release(); if (lpDD) // DirectDrawオブジェクト解放 lpDD->Release(); プログラム 今回のプログラムは、640×480・8ビットのプライマリサーフェイスにランダムに点を打つ関数drawをメインループから呼び出すものです。実行すると、アプリケーションが全画面を覆いランダムに点を打っていきます。終了する時には、エスケープキーを押してください。 void draw(void) { lpDDSPrimary->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL ); BYTE* lpVideoMemory=(BYTE*)ddsd.lpSurface; lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0); lpVideoMemory[rand() % 640+(rand() % 480)*640]=rand() % 256; lpDDSPrimary->Unlock(NULL); } プログラムをコンパイルする時には、DirectX5以上のSDKをインストールする必要があります。ソースをダウンロードしたら、拡張子をcppにしてプロジェクトの設定でddraw.libをリンクしてからビルドしてください。 プログラムソース表示
|