サンプルコードのダウンロード

では、まずddraw_09サンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、
お持ちの方はVisual C++でプロジェクトファイルを開いてください(「ddraw_09.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「ddraw_09.exe」をダブルクリックし、実行してみてください。
どうでしょう?画面が切り替わり、フルスクリーン化し、スライム(?)らしき絵が段々小さくなっていくのが解ると思います。

というわけで今回は、サーフェイスの全消去と、拡大縮小付きの転送について書いていきたいと思います。

サーフェイスの全消去

シューティングゲーム等では、バックバッファを一度全て消し、そこに全てキャラクターを配置して、フリップという処理を繰り返し行います(たぶん)。
このとき、もしバックバッファを消さないと、前に書き込んだ分が残ったままになってしまいます(まぁ、当たり前の話なのですが(^^;)。
DirectDrawでは、この場合矩形領域を何かの色で塗りつぶすという処理をすることになります(矩形塗りつぶし)。

では、コードを見てみましょう。

//----------[ サーフェイス全消去 ]--------------------------------------------------------------
void ClearScreen(LPDIRECTDRAWSURFACE sf){
	DDBLTFX ddbltfx;
	ZeroMemory(&ddbltfx,sizeof(DDBLTFX));
	ddbltfx.dwSize=sizeof(DDBLTFX);
	//ddbltfx.dwFillColor=0;
	sf->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx);
}

塗りつぶしには、サーフェイスのメンバ関数である「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演算子(|)を使用して複数同時に指定可能です。

lpDDBltFx DDBLTFX構造体へのポインタ。
戻り値 成功するとDD_OKが返ってくるらしい。

今回は、サーフェイスの全領域を黒(パレット0番)で塗りつぶすのでlpDestRectはNULLになっていますが、RECT構造体を使用して部分的に塗りつぶす事も出来ます。

拡大縮小付きデータ転送

拡大縮小付きデータ転送は自作関数「BltStretch」にまとめました。

//----------[ 拡大縮小付きデータ転送 ]----------------------------------------------------------
void BltStretch(LPDIRECTDRAWSURFACE saki,int sx,int sy,int swidth,int sheight,
		        LPDIRECTDRAWSURFACE moto,int mx,int my,int mwidth,int mheight,char trans){
	DWORD key[2]={0,DDBLT_KEYSRC};
	RECT r_saki={sx,sy,sx+swidth,sy+sheight};
	RECT r_moto={mx,my,mx+mwidth,my+mheight};
	saki->Blt(&r_saki,moto,&r_moto,key[trans] | DDBLT_WAIT,NULL);
}

Bltの構文については上で説明した通りです。
転送先のサーフェイスがBlt関数を呼び出すことになります。
BltFast関数(第8回参照)と似てる部分もあるのですが、転送先の指定にRECT構造体を使用していたり、透明色を使用しない時に特に指定が無いという事が違う点ですかね。
転送元と転送先のサイズが違うときに拡大縮小を行います。
サイズが同じ時はそのまま転送するのですが、ハードウェアの転送であればBltFastと速度は同じらしいです。

まぁ今回は、特別な機能を使用していないのでDDBLTFX構造体へのポインタはNULLを指定してます。
拡大縮小機能は普通のビデオカードではまず対応していないでしょう。
その場合、ソフトウェアでエミュレートするのですが、ビデオメモリ内に作成されたサーフェイス間のデータ転送は非常にたるいです。
ですからシステムメモリ内のサーフェイス間で拡大縮小をした後でビデオメモリ内のサーフェイスへ転送する方がいいかもしれませんね。

記事検索

アーカイブ