古の技術でゲームプログラミング 第13回

 

今回もゲームに必須の技術、画像のブロック転送です。

 

前回、メモリ上にビットマップを作る方法についてきましたが、今度はそれをウインドウのクライアント領域に転送して画面表示しよう、というお話です。

 

おおまかな手順は以下の通り。

 

1) ビットマップをロードする

2) メモリデバイスコンテキストを作る

3) メモリデバイスコンテキストにビットマップを紐づける

4) ウインドウのデバイスコンテキストを取得する

5) ビットマップからウインドウにブロック転送を行う

 

って感じ。

 

では順番に行ってみましょう。

 

 

 

  1) ビットマップをロードする

 

とりあえずは前回の記事で書いた通りLoadImageでビットマップをロードするのが早いかな?

 

 

 

  2) メモリデバイスコンテキストを作る

 

CreateCompatibleDCというAPIを使います。

パラメータに渡すデバイスコンテキストと互換性のあるデバイスコンテキストを作ってくれます。

 

ここでも前回の記事で書いた画面のDCを作って渡せばおっけー。

↓ね。

HDC hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);

 

 

  3) メモリデバイスコンテキストにビットマップを紐づける

 

この手順をこなすことでメモリデバイスコンテキストを通してビットマップにいろいろできるようになります。

 

使うAPIは以下。

 

HBITMAP bitmap_old = (HBITMAP)SelectObject(mem_dc, (HGDIOBJ)hbitmap);

 

1つ目のパラメータに2)で作ったメモリDCを渡します。

2つ目のパラメータは1)で作ったビットマップを渡します。

これでメモリDCに対してビットマップの紐づけができます。

 

で、リターンはもともとメモリDCにくっついてたビットマップが返ってきます。

メモリDCを使い終わって削除するときは同じ要領でこのもともとのビットマップを選択してから削除する必要があります。

 

SelectObject(mem_dc, (HGDIOBJ)bitmap_old);
DeleteDC(mem_dc);

こんな感じ。

 

 

  4) ウインドウのデバイスコンテキストを取得する

 

ウインドウのクライアント領域のデバイスコンテキストの取得方法は2通りあります。

 

①ウインドウプロシージャでのWM_PAINTメッセージ処理時

 

 たしかテンプレプロジェクトですでに実装されてたと思うけど

 以下のようにDCを取得して使い終わったら解放します。

PAINTSTRUCT ps;

HDC hdc = BeginPaint(hWnd, &ps); // DC取得
 :   // 描画コード
EndPaint(hWnd, &ps); // DC解放

 

 ちなみにウインドウに描画命令を出すには以下のAPIを使う。

InvalidateRect(hWnd, NULL, FALSE);

 1個目のパラメータ:ウインドウハンドル

 2個目のパラメータ:更新領域を示すRECT構造体? 全域更新ならNULLでOK

 3個目のパラメータ:バックグラウンドの塗りつぶしをするかどうか FALSEでOK

 

 

 

②上記①以外のタイミング

 今回はこっちのやり方してないので記憶を頼りに書いてる。

 なので間違ってる可能性が微妙にあるかも・・

HDC hdc = GetDC(hWnd);  // DC取得
 ; // 描画コード
ReleaseDC(hWnd, hdc);  // DC解放

 

 

  5) ビットマップからウインドウにブロック転送を行う

 

ブロック転送用のAPIはいろいろバリエーションがありますが一番基本手金ヤツから。

 

BOOL BitBlt(
        HDC hdc,
        int x,
        int y,
        int cx,
        int cy,
        HDC hdcSrc,
        int x1,
        int y1,
        DWORD rop );

こいつは普通に転送元ビットマップ⇒転送先ビットマップに矩形領域を転送します。

 

hdc : 転送先のデバイスコンテキスト

x, y, cx, cy : 転送先の座標、幅、高さ

hdcsrc : 転送元のデバイスコンテキスト

x1, y1 : 転送元の座標

rop : 転送方法をいろいろ指定できる

   SRCCOPY : 転送元⇒先にふつーにコピー

   SRCPAINT : 転送元⇒先の色をOR演算

   SRCAND : 転送元⇒先の色をAND演算

   BLACKNESS : 転送先を黒く塗りつぶす

   WHITENESS : 転送先を白く塗りつぶす

 

あとはBitBltの兄弟たち。

 

StretchBlt()

 拡大縮小転送できるヤツ

 拡大/縮小の品質をSetStretchBltModeで設定しておける

 

TransparentBlt()

 抜き色転送ができるヤツ

 こいつは抜き色をRGBQUADで指定できる

 スプライト描画とかに使えるんだけど、BitBltに比べて低速なため昔はマスク画像とBitBltのOR/AND転送でやってた。

 今時はこいつでもいけるんだろうか。

 

AlphaBlend()

 アルファブレンドできるヤツ。

 フェードイン/アウトとかで使えるけどやっぱり低速。

 画像全体にかかるアルファ値を指定するか、ピクセル単位にアルファ値をもたせておくことができる。

 が…ピクセル単位にアルファ値を持たせたい場合DDBでどうやるかは知らない。

 

 

おしまい。