■ 新・ゲーム開発講座




■ へっぽこプログラミング入門♪


■第55夜:フェードイン/アウト(アルファブレンド版)

せっかく前回でお手軽アルファブレンドを紹介したので、第53夜で実装したフェード処理をアルファブレンドで置き換えてみましょう。ソースはこちらです。

ドットマスクが不要になって、BitBlt() AlphaBlend() に変わっただけなので特に解説は不要だと思います。問題は処理速度で、やはり遅いマシンだと微妙につらいかも…(^^;)



//------------------------------------------------------------
// フェードアウト(AlphaBlend版)
//
// 書式:#fade_out
//
// 画面を段階的に暗くする。
//
// ※実質的に「改ページ処理」の一種に相当するのでセーブ
// ポイント処理も行う。
//------------------------------------------------------------

DWORD fade_timer;
int fade_rate;

HDC Fade_DC; //デバイスコンテキスト(フェード処理用)
HBITMAP hFade_Bitmap; //フェード画面本体のハンドル

void _make_fade_surface()
//フェード処理用のワーク画面を生成する
{

HDC work_hdc; //作業用のDC

work_hdc=GetDC(hwnd); //主(表)画面のDCの内容を取得
Fade_DC =CreateCompatibleDC(work_hdc); //同じ設定でバック画面用のDCを生成
hFade_Bitmap =CreateCompatibleBitmap(work_hdc,640,480); //主(表)画面と同じ属性で画面生成
SelectObject(Fade_DC,hFade_Bitmap); //DCと画面本体を関連付ける
ReleaseDC(hwnd,work_hdc); //作業用DCを開放

Boxf(Fade_DC,MK_RECT(0,0,640,480),RGB(0,0,0)); //ワーク画面を黒で塗りつぶす

}

int Com_fade_out()
{

TEXT++;

//作業用サーフェイス作成(同時に黒で初期化)
_make_fade_surface();

//フラグ操作
Mode_stat.flag_fade_out = ON; //フェードアウトのフラグを立てる
Mode_stat.flag_cursor_blink = OFF; //カーソル表示は停止しておく
Mode_stat.flag_text = OFF; //テキスト表示は停止しておく

//Alpha値カウンタ初期化
fade_rate = 0;

//タイマーを撃つ
HLS_timer_start( &fade_timer );
return 0;

}

int Com_fade_out_task()
{

//タイマー処理
if( HLS_timer_check(fade_timer,50)==false )return 0;

HLS_timer_start( &fade_timer ); //次回処理にむけてタイマーを撃つ

//アルファブレンド
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = fade_rate*255/100; //0〜255で表すブレンド値

AlphaBlend( Back_DC,0,0,640,480,Fade_DC,0,0,640,480,bf);

fade_rate += 5; // 5%刻みでアルファ値を上げていく

if( fade_rate>100 ){

Mode_stat.flag_fade_out = OFF; //フェードアウトのフラグをクリア
Mode_stat.flag_cursor_blink = OFF; //カーソル表示は消したまま
Mode_stat.flag_text = ON; //テキスト表示戻し

DeleteDC( Fade_DC ); //作業用DCの消去

//テキスト表示位置をリセット
TEXT_X = TEXT_AREA.left; //強制的にテキストエリアの左端へ
TEXT_Y = TEXT_AREA.top; //強制的にテキストエリアの上端へ

//念のため BitBlt() で完全コピー
BitBlt(Back_DC,0,0,640,480,Fade_DC,0,0,SRCCOPY);

//フェードアウト処理後Back画面は真っ黒になるため、ダミーとして
//真っ黒なBMPファイル名をキャッシュに書き込んでおきます。
sprintf( BK_bmp_fname,"%sblack.bmp",G_PATH);
if( _save_point_mode == _AUTO_ )make_save_info(); //セーブポイント処理

}

return 0;

}


//------------------------------------------------------------
// フェードイン
//
// 書式:#fade_in
//
// Back画面にBG画面の内容をアルファブレンドしていく
//
// ※実質的な「改ページ処理」に相当するので、フラグが AUTO
// になっている場合はSaveポイント処理する。
//------------------------------------------------------------

int Com_fade_in()
{

TEXT++;

//フラグ操作
Mode_stat.flag_fade_in = ON; //フェードアウトのフラグを立てる
Mode_stat.flag_cursor_blink = OFF; //カーソル表示は停止しておく
Mode_stat.flag_text = OFF; //テキスト表示は停止しておく

//カウンタ初期化
fade_rate = 0;

//タイマーを撃つ
HLS_timer_start( &fade_timer );
return 0;

}

int Com_fade_in_task()
{

//タイマー処理
if( HLS_timer_check(fade_timer,50)==false )return 0;

HLS_timer_start( &fade_timer ); //次回処理にむけてタイマーを撃つ

//アルファブレンド(BG面から直接バックサーフェイスへ)
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = fade_rate*255/100; //0〜255で表すブレンド値

AlphaBlend( Back_DC,0,0,640,480,BG_DC,0,0,640,480,bf);

fade_rate += 5; // 5%刻みでアルファ値を上げていく

if( fade_rate>100 ) {

//ブレンド値が100%を超えたら終了処理
Mode_stat.flag_fade_in = OFF; //フェードアウトのフラグをクリア
Mode_stat.flag_cursor_blink = OFF; //カーソル表示は消したまま
Mode_stat.flag_text = ON; //テキスト表示戻し

//テキスト表示位置をリセット
TEXT_X = TEXT_AREA.left; //強制的にテキストエリアの左端へ
TEXT_Y = TEXT_AREA.top; //強制的にテキストエリアの上端へ

//念のため BitBlt() で完全コピー
BitBlt(Back_DC,0,0,640,480,BG_DC,0,0,SRCCOPY);

//BG画面とBack画面の内容が等しくなったのでキャッシュ内容をコピー
strcpy( BK_bmp_fname,BG_bmp_fname );
if( _save_point_mode == _AUTO_ )make_save_info(); //セーブポイント処理

}

return 0;

}


実行してみると、セレロン500MHzクラスのマシンではFPSが瞬間的にガクンと下がって処理の重さが実感できます…(汗 ^^;) でも合成がなめらかで綺麗なので、これを見てしまうとドットマスク式に戻る気は失せてしまいそうですねぇ。まさに、腐ってもアルファブレンドといえましょう(なんだそりゃ:爆)

さて、とりあえず演出系のコマンドはこのくらいで一通り整備できましたでしょうか。贅沢をいえばきりがありませんが、このあたりでいったん一区切りをつけましょう。