サンプルコードのダウンロード
では、まずサンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、お持ちの方はVisual C++でプロジェクトファイルを開いてください(「effec_05.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「effec_05.exe」をダブルクリックし、実行してみてください(何かキーを押すと終了します)。
どうでしょう?画面が切り替わり、写真が表示され、その明度が徐々に変わっていくのが解ると思います。
というわけで、今回はパレットを操作して画像のメイドを変更するぜっ!(壊
明度のお勉強
さて、明度を変更するというテクニックはよく見かけますよね?
例えばゲームで何か表示していて、次のシーン(場面)に移りたい場合に、画面を段々暗くし(フェード・アウト)、画面が真っ暗な間に次の画像を読み込んでおき(まだ表示はしない)準備が終わったら段々明るくしていき(フェード・イン)新しいシーンが始まる・・・というのがあります。
まず、こういったものは「パレットを操作」して明度を変更していると考えて良いでしょう。
というか、256色環境で明度を変更する方法はパレット操作以外まず無いです(近似色検索という解答は未定義)。
では、パレットをどうやって変化させたらいいか、についでですが、簡単です。
明るくしたければ各RGB値を増やしてやればいいし、暗くしたければRGB値を減らしてやればいいのです。
例えばRGB値が(100,25,30)だとして、1明るくしたいのなら各RGB値に1を足して(101,26,31)という感じ。
ただ、ここで注意してもらいたいのが、各RGB値は0~255でなければならないと言うことです。255を越えた場合は255、0より小さくなった場合は
0という風にです。あとはこの作業を256色パレット全てに行えばいい・・・はずですが、
パレット0番と255番は白・黒固定色なので、それ以外を全て変更すればいいのです。
今回はもうちょっと突っ込んでおきましょうかね。
例えば
int bright=50; //明度を変更する値(50は適当 BYTE red=230; //パレットの値(赤のみ) BYTE = unsigned char red+=bright; if(red>255) red=255; if(red<0) red=0;
というような事はしないようにしてくださいね。
今週のコードチェック(壊
今回の主なコードはコレ。
略 //----------[ パレットの明るさ変更 ]------------------------------------------------------------ //面倒なのでマクロでやってまう(良い子はマネしないでね) #define SET_PAL(dest,src,bright) do{int v=src+bright;if(v>255)v=255;if(v<0)v=0;dest=v;}while(0) void SetPaletteBright(int bright){ PALETTEENTRY pal_tmp[256]; for(int i=1;i<255;i++){ //0:黒固定 1:白固定 SET_PAL(pal_tmp[i].peRed ,peEntry[i].peRed ,bright); SET_PAL(pal_tmp[i].peGreen,peEntry[i].peGreen,bright); SET_PAL(pal_tmp[i].peBlue ,peEntry[i].peBlue ,bright); } //垂直帰線待ち(ちらつき防止) VsyncWait(); //更新 lpPalette->SetEntries(0,1,254,&pal_tmp[1]); }
パレットの設定については「DirectDraw基礎 第6回」でやりました。
また垂直帰線については「DirectDraw基礎 第14回」でやりました。
略 //----------[ メイン関数 ]---------------------------------------------------------------------- int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow){ 略 //DirectDraw開始 StartDirectDraw(hw); //パレット設定 LoadPalette("bridge.bmp"); //ビットマップをバックバッファへ読み込む LoadBitmap(lpBack,"bridge.bmp",0,0,320,240); //フリッピング(画面へ表示) Flip(); DWORD tim; int bright=0,b_add=1; while(1){ //疑似タイマー処理 tim=timeGetTime(); //明るさ変更 bright+=b_add; if(bright6gt;=255 || bright<=-255) b_add=-b_add; SetPaletteBright(bright); do{ //メッセージループ while(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){ if(!GetMessage(&msg,NULL,0,0)) Quit(); TranslateMessage(&msg); DispatchMessage(&msg); } }while(timeGetTime()<tim+16); //1000/60=16.666(60FPS) } return(FALSE); }
見て解るとおり、一度画面に写真を表示したら、後はパレットを変更しているだけです。
明度を変更する関数でマクロを使ってしまったので、初心者にはちょっと解りにくいかもしれませんが、これを機、マクロの勉強をしてみてください。マクロを使うとホント楽なので・・・
あ、ちなみにビデオカードによっては、この「パレットを設定」する時間がやたらかかるものがあるので、「パレットを使えば高速に出来る!」とか思いこまないようにしてください。