[HMC]年間5250円で独自ドメイン付属、ウィルスチェックありのレンタルサーバ!
Last update : 1999/08/22
DirectDraw基礎 第9回
サーフェイスの全消去、拡大縮小付きデータ転送
サンプルコードのダウンロード
  では、まずサンプルコードをダウンロードし、解凍して下さい。 私はVisual C++6.0でコンパイルしているので、をお持ちの方は Visual C++でプロジェクトファイルを開いて下さい(「ddraw_09.dsw」をダブルクリックすれば開けます)。 圧縮ファイルに含まれる「ddraw_09.exe」をダブルクリックし、実行してみて下さい。どうでしょう?画面が切り替わり、フルスクリーン化し、 スライム(?)らしき絵が段々小さくなっていくのが解ると思います。
  というわけで今回は、サーフェイスの全消去と、拡大縮小付きの転送について書いていきたいと思います。
サーフェイスの全消去
  シューティングゲーム等では、バックバッファを一度全て消し、そこに全てキャラクターを配置して、フリップという処理を繰り返し行います(たぶん)。 このとき、もしバックバッファを消さないと、前に書き込んだ分が残ったままになってしまいます(まぁ、当たり前の話なのですが(^^;)。DirectDrawでは、この場合 矩形領域を何かの色で塗りつぶすという処理をすることになります(矩形塗りつぶし)。では、コードを見てみましょう。
  塗りつぶしには、サーフェイスのメンバ関数である「Blt」を呼び出します(前回作成した自作関数Bltと名前が同じですが、全く違うものなので注意して下さい)。Blt関数はもともと転送用(拡大縮小にも使用)なのですが、 いろいろな機能がついていて、良いような悪いような(謎)関数です。で、いろいろな機能を使用したい場合は DDBLTFX構造体にいろいろデータをぶち込んで、Blt関数に引き渡してやります。ZeroMemoryという関数は データを指定したバイト分0にするというものです(普通は知ってるはず)。dwSizeにはデータのサイズを入れてやります。 で、塗りつぶしたい色のパレット番号をメンバdwFillColorに入れてやるのですが、今回は黒(パレット0番)なので何もしなくていい事になります。 Bltの構文は以下の通りです。

書式HRESULT Blt( LPRECT lpDestRect, LPDIRECTDRAWSURFACE lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx );
lpDestRectブロック転送する転送先のサーフェス上の矩形の左上および右下の位置を定義した RECT 構造体へのポインタ。このパラメータが NULL であると、転送先の全サーフェスが使われる。
lpDDSrcSurfaceブロック転送操作の転送元である DirectDraw サーフェスへのポインタ。
lpSrcRectブロック転送される転送元サーフェス上の矩形の左上および右下の場所を定義した RECT 構造体へのポインタ。このパラメータが NULL であると、転送元の全サーフェスが使われる。
dwFlags指定できる主なフラグは以下の通りです。
DDBLT_COLORFILL転送先サーフェス上の転送先矩形を埋めるRGB 色として DDBLTFX構造体のdwFillColor メンバを使用する。
DDBLT_KEYSRC転送元サーフェスと関連づけられたカラーキーを使用する(透明色)。
DDBLT_WAIT何らかの原因で転送出来ない時に転送できるまで待つ。
これらはOR演算子(|)を使用して複数同時に指定可能です。
lpDDBltFxDDBLTFX構造体へのポインタ。
戻り値 成功するとDD_OKが返ってくるらしい。

  今回は、サーフェイスの全領域を黒(パレット0番)で塗りつぶすのでlpDestRectはNULLになっていますが、 RECT構造体を使用して部分的に塗りつぶす事も出来ます。
拡大縮小付きデータ転送
  拡大縮小付きデータ転送は自作関数「BltStretch」にまとめました。

  Bltの構文については上で説明した通りです。転送先のサーフェイスがBlt関数を呼び出すことになります。BltFast関数(第8回参照)と似てる部分もあるのですが、転送先の指定にRECT構造体を使用していたり、透明色を使用しない時に 特に指定が無いという事が違う点ですかね。転送元と転送先のサイズが違うときに拡大縮小を行います。 サイズが同じ時はそのまま転送するのですが、ハードウェアの転送であればBltFastと速度は同じらしいです。
  まぁ今回は、特別な機能を使用していないのでDDBLTFX構造体へのポインタはNULLを指定してます。 拡大縮小機能は普通のビデオカードではまず対応していないでしょう。その場合、ソフトウェアでエミュレートするのですが、ビデオメモリ内に作成されたサーフェイス間のデータ転送は非常にたるいです。ですからシステムメモリ内のサーフェイス間で拡大縮小をした後で ビデオメモリ内のサーフェイスへ転送する方がいいかもしれませんね。