オフスクリーンサーフェスの透過処理(スプライト)

DirectDrawでは、プライマリサーフェスの他にオフスクリーンサーフェスというサーフェスを利用できます。プライマリサーフェスは、画面そのもので大きさも画面サイズと同一だったのに対し、オフスクリーンサーフェスは純粋な「ビットマップ」として扱え、大きさも自由に設定できます。さらに、プライマリサーフェスやプライマリのバックバッファに対して抜き色を指定した透過処理も可能です。

 今回は、このオフスクリーンサーフェスを作成してバックバッファに透過処理をかけて転送し「スプライト」を作ってみましょう。DIBでの透過処理は、自分で1ピクセルずつ抜き色かどうか判別していましたが、オフスクリーンサーフェスでは抜き色を指定するだけで自動的に透過処理が行われます。

オフスクリーンサーフェスの作成と描画

 オフスクリーンサーフェス作成の手順は、プライマリサーフェスと大体同じで、まずDDSURFACEDESC構造体でサーフェスの機能などを設定し、それをDirectDrawオブジェクトのCreateSurface()関数に渡します。サーフェスの機能(DDSURFACEDESCddsCaps.dwCaps)には、DDSCAPS_OFFSCREENPLAINを指定し、サーフェスの大きさをdwWidth, dwHeightで設定。後は、プライマリサーフェス同様CreateSurface()関数ににDDSURFACEDESC構造体のアドレスと作成したサーフェスを参照するポインタのアドレスを渡せば、サーフェスが作成されてDD_OKが返ってくるはずです。

 例えば、64×64ピクセルのオフスクリーンサーフェスを作成する処理は以下のようになります。

  LPDIRECTDRAW lpDD=NULL;
  LPDIRECTDRAWSURFACE lpDDSOff=NULL;
  DDSURFACEDESC ddsdo;

  FillMemory(&ddsdo,0,sizeof(ddsdo)); // オフスクリーンサーフェス作成
  ddsdo.dwSize=sizeof(ddsdo);
  ddsdo.dwFlags=DDSD_CAPS| DDSD_WIDTH| DDSD_HEIGHT;
  ddsdo.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN;
  ddsdo.dwWidth=64;
  ddsdo.dwHeight=64;

  lpDD->CreateSurface(&ddsdo,&lpDDSOff,NULL);

 これでDirectDrawオブジェクトと同じ色形式で指定した大きさのオフスクリーンサーフェスが出来るので、後はプライマリサーフェスやバックバッファと同じようにロックしてサーフェスのビットマップへのポインタを取得すれば自由にアクセスできます。

  lpDDSOff->Lock(NULL,&ddsdo,DDLOCK_WAIT,NULL);
  lpBuf=(BYTE*)ddsdo.lpSurface; // オフスクリーンサーフェスのポインタ

       ・
       ・
      描画処理
       ・
       ・
  lpDDSOff->Unlock(NULL);

 オフスクリーンサーフェスをプライマリサーフェスやバックバッファに転送する時には、転送先サーフェスオブジェクトのBlt()あるいはBltFast()関数を使います。今回は、手軽に使えるBltFast()を使ってみました。

  RECT rec;

  rec.left=0;
  rec.top=0;
  rec.right=63;
  rec.bottom=63;

  lpDDSBack->BltFast(iX,iY,lpDDSOff,&rec,DDBLTFAST_NOCOLORKEY);

 BltFastの引数は最初の2つが転送(描画)する座標で次が転送するサーフェスのポインタ、後は転送範囲を示すRECT構造体と転送方式の指定になっています。上の例だと、lpDDSBackの(iX, iY)−(iX+63, iY+63)にlpDDSOffの(0,0)−(63,63)を転送するわけですね。

 転送方式は、そのまま上書きするか抜き色(カラーキー)による透過処理などを指定できます。上の例ではそのまま上書きするDDBLTFAST_NOCOLORKEYになっていますが、スプライトを使う時には転送元のカラーキーで透過処理を行うDDBLTFAST_SRCCOLORKEYを指定する事になるでしょう。

 カラーキーを設定するには、カラーキーの情報を入れるDDCOLORKEY構造体を作成し、その構造体をサーフェスのSetColorKey()に渡します。DDCOLORKEYは、dwColorSpaceLowValue, dwColorSpaceHighValueの2つのメンバを持ち、抜き色を範囲で指定する時にはそれぞれ抜き色の下限と上限を表しますが、抜き色が1つだけなら同じ値を設定します。この値は、通常32ビットのRGBですがパレットを使う時にはパレット番号とみなされるようです。
 例として、上の例で作成したオフスクリーンサーフェス(256色モード)にパレット番号0を抜き色指定してみましょう。

  DDCOLORKEY ddck;
  ddck.dwColorSpaceLowValue=0;
  ddck.dwColorSpaceHighValue=0;

  lpDDSOff->SetColorKey(DDCKEY_SRCBLT,&ddck);

 サーフェスで抜き色を設定したら、BltFastDDBLTFAST_SRCCOLORKEYを指定し透過処理を行う事ができます。

  lpDDSBack->BltFast(iX,iY,lpDDSOff,&rec,DDBLTFAST_SRCCOLORKEY);

プログラム

 画面上に四角いスプライトがあるので、カーソルキーで上下左右に移動してみましょう(エスケープキーで終了)。文字は、サーフェスのGetDC()でデバイスコンテキストを取得して描いています。

プログラムソース表示


Windowsプログラミング実験室 > プログラミング資料庫