第1章 基礎知識

1-4.DirectDrawの使い方

この授業ではまず640×480の8ビット(256色)のフルスクリーンモードでゲームを作成する。その場合のDirectDrawの使用方法は次のとおり。

  1. DirectDrawの主要オブジェクトの生成と初期化
  2. ビットマップ関連オブジェクトの生成と初期化
  3. パレットオブジェクトの生成とパレット情報の設定
    ***ここまでがDirectDraw使用前準備***
  4. 画像の描画
  5. フリップ
    ***ここまでがゲームループ内の処理***
  6. DirectDrawの主要オブジェクト、ビットマップ関連オブジェクトの開放
    ***ここまでがプログラム終了時に行う処理***

※オブジェクトについては用語集の「オブジェクトの項」を参照

(a) DirectDrawの主要オブジェクトの生成と初期化

DirectDrawの主要オブジェクトの生成と初期化を行うプログラムを紹介する。なお、エラー処理は含まれていない。

/* グローバル変数として宣言 */
LPDIRECTDRAW7           g_pDD = NULL;           // DirectDraw オブジェクト
LPDIRECTDRAWSURFACE7    g_pDDSPrimary = NULL;   // プライマリ・サーフェイス
LPDIRECTDRAWSURFACE7    g_pDDSBack = NULL;      // バック・サーフェイス


/* プログラム */
HRESULT   hRet;

// IDirectDraw7インターフェイスの取得
hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL);

// 協調レベルの設定
hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);

// ビデオモードの設定 640x480x8
hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0);

// プライマリ・サーフェイスの生成
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);

// バック・サーフェイスの生成
ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);

《解説》

1.IDirectDrawインターフェイスの取得
DirectDrawを使うにはまずIDirectDraw7インターフェイスを取得する。通常はアプリケーションで1つ。
DirectDrawCreateEx関数はIDirectDraw7インターフェイスの取得に成功するとDD_OKを返す。
2.画面モードの設定
アプリケーションがどのような状態で実行されるかをセットする。まず、フルスクリーン・モードかウィンドウ・モードかを決め(協調レベルの設定)、次に画面サイズと色数を決める(ビデオ・モードの設定)。
3.プライマリ・サーフェイスの生成
ディスプレイに表示されるサーフェイスを生成する。
4.バック・サーフェイスの生成
ダブル・バッファリングを行うためにバック・サーフェイスを生成する。
正確には、プライマリ・サーフェイス作成時にバック・バッファを生成するよう指定しているため、GetAttachedSurface関数でバック・サーフェイスを取得する。

《ここまでで何ができたのか?》

(b) ビットマップ関連オブジェクトの生成と初期化

用意したビットマップをDirectDrawで使うためのプログラムを紹介する。この処理は通常、用意した画像の数だけ行う。なお、エラー処理は含まれていない。

/* グローバル変数として宣言 */
LPDIRECTDRAWSURFACE7    g_pDDSBackimg = NULL;   // 背景画像用オフスクリーン・サーフェイス
char szBackimgBmp[] = "BACKIMG";   // 背景画像データ名


/* プログラム */
HRESULT   hRet;

// オフスクリーン・サーフェイスを生成する(画像毎)
/* 背景画像 */
g_pDDSBackimg = DDLoadBitmap(g_pDD, szBackimgBmp, 0, 0);

《解説》

DDLoadBitmap関数は、Microsoftが作成したDirectDraw汎用モジュール「ddutil.cpp」に入っている関数で、以下の機能を持つ。

  1. オフスクリーン・サーフェイス・オブジェクトを生成し、そのオブジェクトへのポインタを返す。
  2. リソースに用意したビットマップを、オフスクリーン・サーフェイスへ転送する。

《ここまでで何ができたのか?》

(c) パレットオブジェクトの生成とパレット情報の設定

256色のゲームを考えるため、パレットを用意しなければならない。パレットは元となるビットマップから作成し、プライマリ・サーフェイスに設定する。なお、エラー処理は含まれていない。

/* グローバル変数として宣言 */
LPDIRECTDRAWPALETTE    g_pDDPal = NULL;  // プライマリサーフェイスパレット


/* プログラム */
HRESULT   hRet;

// パレットの生成(指定した画像を元に、パレット情報を作成する)
g_pDDPal = DDLoadPalette(g_pDD, szBackimgBmp);

// プライマリー・サーフェイスにパレットを設定する。
hRet = g_pDDSPrimary->SetPalette(g_pDDPal);

《解説》

DDLoadPalette関数は、Microsoftが作成したDirectDraw汎用モジュール「ddutil.cpp」に入っている関数で、以下の機能を持つ。

  1. パレット・オブジェクトを生成し、そのオブジェクトへのポインタを返す。
  2. リソースに用意したビットマップを参照してパレット情報を取り出し、ビデオメモリに転送する。

SetPalette関数は、プライマリ・サーフェイス・オブジェクトが持つメンバー関数で、以下の機能を持つ。

  1. 作成されたパレット情報をプライマリ・サーフェイスのパレットとして設定する。
    (デフォルトのパレットを無視する)

《ここまでで何ができたのか?》

(d) 画像の描画

画像の描画は、描画したい画像(オフスクリーン・サーフェイス)の矩形をバック・サーフェイスに転送することで行われる。なお、エラー処理は含まれていない。

/* プログラム */
HRESULT   hRet;
RECT      lpSrcRect = {0, 0, 640, 480};  // 画像の矩形
DWORD     x = 0;  // 転送先のx座標
DWORD     y = 0;  // 転送先のy座標

hRet = g_pDDSBack->BltFast(x, y, g_pDDBackimg, lpSrcRect, DDBLTFAST_XXXXXX);

《解説》

BltFast関数は、バック・サーフェイス・オブジェクトが持つメンバー関数で、以下の機能を持つ。

  1. ビデオメモリ内のデータ転送を行う。
  2. 3つ目の引数に指定したオフスクリーン・サーフェイスから4つ目の引数に指定した矩形を取り出し、バック・サーフェイスのx、y座標に転送する。
  3. 転送の際、5つ目の引数でパラメータを指定する(詳細は後期で説明)。

《ここまでで何ができたのか?》

(e) フリップ

バック・サーフェイスに転送した画像をディスプレイに表示するには、プライマリ・サーフェイスとバック・サーフェイスを切り替える、つまりフリップを行う。この処理は、表示したい画像を全てバック・サーフェイスに転送してから一度だけ行う。なお、エラー処理は含まれていない。

/* プログラム */
HRESULT hRet;

hRet = g_pDDSPrimary->Flip(NULL, 0);

《解説》

Flip関数は、プライマリ・サーフェイス・オブジェクトが持つメンバー関数で、プライマリ・サーフェイスとバック・サーフェイスを入れ替えるの機能を持つ。

《ここまでで何ができたのか?》

(f) DirectDrawオブジェクトの開放

プログラム終了時、作成済みのDirectDrawオブジェクトを開放しなければならない。

開放するDirectDrawの各種オブジェクト

  1. プライマリ・サーフェイス
  2. 画像ごとのオフスクリーン・サーフェイス
  3. パレット
  4. DirectDrawオブジェクト

※バック・サーフェイスはプライマリ・サーフェイスにアタッチして作成されているため、プライマリ・サーフェイスを開放すればバック・サーフェイスも自動的に開放される。

《プログラム例》

//-----------------------------------------------------------------------------
// 関数名 : ReleaseDraw()
// 機能概要: Direct Draw オブジェクトの削除
//-----------------------------------------------------------------------------
void ReleaseDraw(void)
{
    if (g_pDD != NULL)
    {
        if (g_pDDSPrimary != NULL) // プライマリーサーフェイス
        {
            g_pDDSPrimary->Release();
            g_pDDSPrimary = NULL;
        }
        if (g_pDDSStart != NULL) // スタート画像用サーフェイス
        {
            g_pDDSStart->Release();
            g_pDDSStart = NULL;
        }
        if (g_pDDPal != NULL) // パレット
        {
            g_pDDPal->Release();
            g_pDDPal = NULL;
        }
        g_pDD->Release(); // DirectDrawオブジェクト
        g_pDD = NULL;
    }

}

《解説》

《ここまでで何ができたのか?》


[ TOP ] [ Next ]