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

では、まずサンプルコードをダウンロードし、解凍してください。
私は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);
}

見て解るとおり、一度画面に写真を表示したら、後はパレットを変更しているだけです。
明度を変更する関数でマクロを使ってしまったので、初心者にはちょっと解りにくいかもしれませんが、これを機、マクロの勉強をしてみてください。マクロを使うとホント楽なので・・・

あ、ちなみにビデオカードによっては、この「パレットを設定」する時間がやたらかかるものがあるので、「パレットを使えば高速に出来る!」とか思いこまないようにしてください。

記事検索

アーカイブ