■ 新・ゲーム開発講座




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


■第25夜:画面切替えB(伸縮タイプ)

さらに調子にのって?(^^)、#g_change コマンドを拡張してみましょう。あまりこればかりやりすぎてもヒンシュクものでしょうから、切替えに関してはこれで一区切とします。

■書式:#g_change type

背景画面からバックサーフェイスに画面内容を遅延込みで転送する。転送タイプは CURTAIN、SPREAD、STRETCH_X、STRETCH_Y のシンボルで判別する。



単にアコーディオンのように「びろ〜ん」と広がるだけですが、簡単なのでX/Y双方のバージョンを用意しましょう。ソースは
こちらです。

■フラグ

main.h の _Mode_stat のメンバに変更はありません。

■コマンド解釈部

ここも変更はありません。

■撃つ

基本は同じですが、パラメータ解釈部分に追加があります。新しく TYPE_STRETCH_X、TYPE_STRETCH_X というシンボルを定義して、#g_change コマンドのパラメータに併せて g_change_type に識別コードを設定しています。他は前回と同じです。



DWORD g_change_timer; //大麻・・・じゃなくてタイマ
DWORD g_change_wait = 20; //Wait値
int g_change_frame_counter; //フレームカウンタ
int g_change_type; //エフェクトタイプ

#define TYPE_CURTAIN 0
#define TYPE_SPREAD 1
#define TYPE_STRETCH_X 2
#define TYPE_STRETCH_Y 3

int Com_g_change()
{

char str[256],msg_str[256];

//パラメータ解析
TEXT++;
strcpy( str, Kaiseki_TextStr() );

if( strcmp( str,"CURTAIN" )==0 ){
g_change_type = TYPE_CURTAIN;
}else if( strcmp( str,"SPREAD" )==0 ){
g_change_type = TYPE_SPREAD;
}else if( strcmp( str,"STRETCH_X" )==0 ){
g_change_type = TYPE_STRETCH_X;
}else if( strcmp( str,"STRETCH_Y" )==0 ){
g_change_type = TYPE_STRETCH_Y;
}else{
sprintf( msg_str,"シンボル [%s] は不正です。強制終了〜♪",str );
msg( msg_str,"Com_g_change_task()");
PostQuitMessage(0);

}

//テキスト表示を停止する
Mode_stat.flag_text = OFF;

//画面切替えのフラグを立てる
Mode_stat.flag_g_change = ON;

//フレームカウンタをゼロクリア
g_change_frame_counter = 0;

//タイマーショット
HLS_timer_start(&g_change_timer);

return 0;


}



■回す/締める

ここも、前回の要領で理解できますね。Mainloop()から呼び出される Com_g_change_task() は、タイプ指定に応じてそれぞれの処理関数を呼び出しているだけです。伸縮型のタスクは、X方向が sub_Com_g_change_task_3()、Y方向が sub_Com_g_change_task_4() となっています。



int Com_g_change_task()
{

switch( g_change_type ){
case TYPE_CURTAIN:
sub_Com_g_change_task_1();
break;
case TYPE_SPREAD:
sub_Com_g_change_task_2();
break;
case TYPE_STRETCH_X:
sub_Com_g_change_task_3();
break;
case TYPE_STRETCH_Y:
sub_Com_g_change_task_4();
break;
}

return 0;

}


では、タスクの中身を見てみましょう。背景画面全体(640×480ピクセル)をX/Y方向に潰れた矩形領域に伸縮転送しているだけです。前回の放射エフェクトより簡単ですね。ただし、StretchBlt() は動作が遅いのでピッチを荒めにしてごまかし?を図っています(笑)高速なマシンなら「すこっ」と動きますが、遅いマシンだと「うにょろぉぉぉ〜ん」という感じになってしまうかも知れません。個人的にはタイマーチェックの部分を前回、前々回と別にしてやりたい気もしますが、まあとりあえず放っておきましょう(ぉぃ)。


//----------------------------
// 伸縮型(X)
//----------------------------

int sub_Com_g_change_task_3()
{

int pitch = 20;

//タイマーチェック
if( HLS_timer_check( g_change_timer,g_change_wait )==false )return 0;

//タイマーショット
HLS_timer_start(&g_change_timer);

StretchBlt( Back_DC,640/2-g_change_frame_counter,0,g_change_frame_counter*2,480,
BG_DC,0,0,640,480,SRCCOPY);


if( g_change_frame_counter < 640/2 ){
g_change_frame_counter += pitch;

}else{

//終了条件

//テキスト表示を再開する
Mode_stat.flag_text = ON;

//画面切替えのフラグをクリア
Mode_stat.flag_g_change = OFF;

//文字表示位置を初期化しておく
TEXT_X = TEXT_AREA.left;
TEXT_Y = TEXT_AREA.top;


}

return 0;

}

//----------------------------
// 伸縮型(Y)
//----------------------------

int sub_Com_g_change_task_4()
{

int pitch = 20;

//タイマーチェック
if( HLS_timer_check( g_change_timer,g_change_wait )==false )return 0;

//タイマーショット
HLS_timer_start(&g_change_timer);

StretchBlt( Back_DC, 0,480/2-g_change_frame_counter,640,g_change_frame_counter*2,
BG_DC,0,0,640,480,SRCCOPY);


if( g_change_frame_counter < 480/2 ){
g_change_frame_counter += pitch;

}else{

//終了条件

//テキスト表示を再開する
Mode_stat.flag_text = ON;

//画面切替えのフラグをクリア
Mode_stat.flag_g_change = OFF;

//文字表示位置を初期化しておく
TEXT_X = TEXT_AREA.left;
TEXT_Y = TEXT_AREA.top;

}

return 0;

}



これを実行すると以下のようになります。まあ、場面に応じて使い分け・・・でしょうか(^^)