サンプルコードのダウンロード
では、まずサンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、
お持ちの方はVisual C++でプロジェクトファイルを開いてください(「ddraw_06.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「ddraw_06.exe」をダブルクリックし、実行してみてください。
どうでしょう?画面が切り替わり、フルスクリーン化し、「フロントバッファ」と「バックバッファ」がカラフルに交互に表示されると思います(謎。
今回は、パレットを作成したいと思います。
パレット作成
まず初めに、StartDirectDraw自作関数内へパレットオブジェクト作成部分を追加します
(ディスプレイの色数が256色以下になっている時にだけ、パレットを使用する事が出来ます)。
//パレットの作成 if(lpDD->CreatePalette(DDPCAPS_8BIT,peEntry,&lpPalette,NULL)!=DD_OK) return FALSE; lpFront->SetPalette(lpPalette);
まず、DirectDrawオブジェクト(lpDD)のメンバである「CreatePalette」関数を呼び出します。構文は以下の通りです。
書式 | HRESULT CreatePalette( DWORD dwFlags, LPPALETTEENTRY lpColorTable, LPDIRECTDRAWPALETTE FAR *lplpDDPalette, IUnknown FAR *pUnkOuter ); |
---|---|
dwFlags | このフラグでは、作成したいパレットの種類(2,4,16,256色)をマクロで指定するらしいのですが、私は256しか使用したことがないので(というかこれが最適)DDPCAPS_8BITを指定します。 |
lpColorTable | このDirectDrawPaletteオブジェクトを初期化するための2、4、16、256色分のPALETTEENTRY型配列へのポインタ。今回はあらかじめ定義しておいたPALETTEENTRY peEntry[256];のポインタを引き渡します。 |
lplpDDPalette | 作成するDirectDrawPaletteオブジェクトの格納先をアドレスで指定するらしい。今回は、あらかじめ定義しておいたLPDIRECTDRAWPALETTE lpPaletteのアドレスを引き渡します。 |
pUnkOuter | 将来拡張した時使用するらしいので、NULLを指定。 |
戻り値 | 成功した場合はDD_OKが返ってくるらしい。 |
そうしたら、次にサーフェイスのメンバ「SetPalette」関数を呼び出し、フロントバッファに作成したパレットを関連付けます。
色の設定
さて、パレットを256個作成したら、その中に色を設定してやります。考え方としては、美術で256個の皿(部屋?)のあるパレットの中に、絵の具で色を作成するが、何故か絵の具が赤、緑、青の3つしか無く、その3つの絵の具の量を調整して様々な色を作成するというもの(わけわからん)。
まぁ、とりあえずコードを見てみますか。
PALETTEENTRY peEntry[256]; //パレット情報 略 //----------[ パレット情報設定 ]---------------------------------------------------------------- void SetPaletteColor(unsigned char no,unsigned char r,unsigned char g,unsigned char b){ if(no<0 || no>255) return; peEntry[no].peRed=r; peEntry[no].peGreen=g; peEntry[no].peBlue=b; peEntry[no].peFlags=1; lpPalette->SetEntries(0,no,1,&peEntry[no]); } 略 //パレット設定 SetPaletteColor(1,26,70,255); SetPaletteColor(2,255,255,0);
自作関数SetPaletteColorでは、256個のパレットの内、no番目の色を「赤」、「緑」、「青」によって設定します。
ここではPALETTEENTRY構造体を使用します。この構造体のメンバ「BYTE peRed」(BYTE = unsigned char)、「BYTE peGreen」、「BYTE peBlue」
にそれぞれ「赤」、「緑」、「青」の量を0~255の間で指定します(peFlagsメンバは1固定)。例えば、「赤」、「緑」、「青」を255,0,255にすると、赤と青が混ざった紫、127,127,127にすると、灰色というような感じです。
そうしたら、前に作成したDirectDrawPaletteオブジェクト「lpPalette」のメンバ
であるSetEntriesという関数を呼び出して、パレットの色を変更します。SetEntriesの構文は以下の通りです。
書式 | HRESULT SetEntries( DWORD dwFlags, DWORD dwStartingEntry, DWORD dwCount, LPPALETTEENTRY lpEntries ); |
---|---|
dwFlags | このフラグは現在使用していないらしいので0を指定しなければいけないらしい。 |
dwStartingEntry | 何番のパレットから設定するか(変更開始パレット番号)。 |
dwCount | 変更したいパレット数 |
lpEntries | パレットエントリ(PALETTEENTRY構造体)へのポインタ |
戻り値 | 成功した場合はDD_OKが返ってくるらしい。 |
この関数は、今回作成した自作関数のように1個1個パレットを設定するのでは無く、複数一気に変更出来るように
設計されています。ですから、peEntry[0]~peEntry[255]を全て変更し、lpPalette->SetEntries(0,0,256,peEntry);とでもすれば、全部一括してパレットを変更できます。
ただ、DirectDrawの特性上(?)0番(黒固定)と255番(白固定)のパレットは変更不可能になっています。
まぁ、白と黒は99%ゲームで使うと思うので変更出来ないからと言って気にはならないでしょう。
設定した色をGDI(テキスト)で使用してみる
今回は、自作関数DdTextOutを改造して、色を指定できるようにします。
//----------[ GDI関数を使用してテキストの出力 ]---------------------------------------------- void DdTextOut(LPDIRECTDRAWSURFACE sf,int x,int y,char *str,unsigned char col){ HDC hdc; sf->GetDC(&hdc); SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,RGB(peEntry[col].peRed,peEntry[col].peGreen,peEntry[col].peBlue)); TextOut(hdc,x,y,str,strlen(str)); sf->ReleaseDC(hdc); } 略 DdTextOut(lpFront,0,0,"フロントバッファ",1); DdTextOut(lpBack ,0,0,"バックバッファ" ,2);
まず、最初に付け加えたのがSetBkMode(hdc,TRANSPARENT);です。これは文字の背景を透明にするというもの。第5回までは、字の色が黒、背景が白という状態だったので
変な風に表示されていましたが、今回は背景を表示しないようにします。
次にSetTextColorという関数を呼び出しています。ここで色を設定しています。GDIで色を指定する場合はRGB値(COLORREF型)という1つの数値を用いるのですが
、なんやよーわからんのでマクロ「RGB(赤,緑,青)」という便利なものを使用してRGB値を指定します。RGB(255,0,255)とすれば紫のRGB値という感じです。で、GDIでDirectDrawPaletteの色をそのまま色番号で指定する事は出来ないので
前に設定したpeEntry構造体のメンバ値を使用してRGB値を設定しています。
パレット後始末
アプリケーション終了時には作成したDirectDrawPaletteオブジェクト(lpPalette)を解放しなければなりません。ですから自作関数EndDirectDrawの中に
「lpPalette->Release();」を追加する必要があります。まぁ、今まで通りマクロを使用する場合は「RELEASE(lpPalette);」ですが。