■ 新・ゲーム開発講座




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


■第29夜:スクリプトファイル間のジャンプ

前回のラベルジャンプは1本のスクリプトファイル内でポンポンと飛び回るものでした。今回はこれを拡張して、別ファイルのラベルに制御を移す処理を記述しましょう。複数のファイル間を自由にジャンプできるようになると、シナリオファイルの管理(シーン分け、キャラ分けなど)が楽になります。書式は、以下のように致しましょう。

■書式:#file_change file_name,*LABEL:

テキストファイル file_name を読み込んで、その中にあるラベル *LABEL: の直後に制御を移す。



また1本の文章として編集可能な文章量(注:テキストエディタのプログラム的許容量ではなく、書いている本人が全体を把握できる文章量という意味)はおよそ20〜30KB程度ではないかと思います。これを越えるようなシナリオ量の場合、スクリプトの分割に対応することはある種、福音ともいえるでしょう(^^)。ちなみにWindows付属のメモ帳は私の環境では約30KBほどのテキスト量で編集不能になります(メモリを増やせばまだ行けるのかな?)。…まあ、それはともかく解説を進めましょう(爆)。

■処理の概要

ジャンプコマンドの変形版です。ラベルサーチの直前で、指定されたスクリプトファイルを読み込んでおけば万事完了です♪(^^)

■Mode_stat

今回の処理では Mode_stat は使用しません。

■コマンド解釈部

TextEngine.cpp の void Command_call() に以下の部分を加えます。



void Command_call()
{

//省略

//コマンド名の評価 → 処理関数呼び出し
if( strcmp(com_name,"delay" )==0 ){ Com_delay(); flag=ON;} //遅延
if( strcmp(com_name,"wait" )==0 ){ Com_cursor_blink(); flag=ON;} //カーソルブリンク
if( strcmp(com_name,"w" )==0 ){ Com_cursor_blink(); flag=ON;} //カーソルブリンク
if( strcmp(com_name,"halt" )==0 ){ Com_halt(); flag=ON;} //終了
if( strcmp(com_name,"page" )==0 ){ Com_page(); flag=ON;} //改ページ
if( strcmp(com_name,"g_load" )==0 ){ Com_g_load(); flag=ON;} //BMPのLOAD
if( strcmp(com_name,"g_copy" )==0 ){ Com_g_copy(); flag=ON;} //BMPのCOPY
if( strcmp(com_name,"g_change")==0 ){ Com_g_change(); flag=ON;} //画面切替
if( strcmp(com_name,"flag_on" )==0 ){ Com_flag_on(); flag=ON;} //イベントフラグON
if( strcmp(com_name,"flag_off")==0 ){ Com_flag_off(); flag=ON;} //イベントフラグOFF
if( strcmp(com_name,"disp_flag")==0 ){ Com_disp_flag(); flag=ON;} //イベントフラグ表示
if( strcmp(com_name,"if_flag" )==0 ){ Com_if_flag(); flag=ON;} //フラグによる分岐
if( strcmp(com_name,"jump" )==0 ){ Com_jump(); flag=ON;} //ラベルジャンプ
if( strcmp(com_name,"file_change")==0 ){Com_file_change(); flag=ON;} //ファイル間ジャンプ

//省略


}


■コマンド実行部

コマンド実行部は以下のようになります。フタを開けてみれば、ラベルジャンプの内容をそっくりコピーしてファイル読込みを付け足しているだけです(爆笑)。とは言え、こんな些細な工夫でも出来ることがどんどん広がっていくのは楽しいものですね(^0^)。

なお、スクリプトファイルが大量に増えたときのことを考えて、ここではついでにスクリプトファイルを txt というサブフォルダに格納するように変更しました。ソース中の TEXT_PATH main.h で定義しているパス名です。


int Com_jump()
{

char f_name[256];
char LABEL_1[256],LABEL_2[256];
char *ptr; //作業用ポインタ
int cnt=0; //カウンタ(0で初期化しておく)
int flag=OFF; //loop flag

//パラメータ文字列からジャンプ先のファイル名を切り出す
TEXT++;
strcpy( f_name,TEXT_PATH ); //テキストスクリプトのパス
strcat( f_name,Kaiseki_TextStr() );
while( *TEXT==' ' || *TEXT==',' )TEXT++; //次のパラメータ先頭までポインタを進める

//パラメータ文字列から目標となるラベルを切り出す
TEXT++;
strcpy( LABEL_1,Kaiseki_TextStr() );

//ジャンプ先スクリプトファイルを読む
HLS_bload( f_name, (char *)TEXT_BUF );

//作業用ポインタ *ptr をテキストバッファ先頭にフィット
ptr = (char *)TEXT_BUF;

//1文字ずつ比較して「*」を探す
do{
if( *ptr=='*' ){

//*を見つけた

//それは行頭か?→まずはTAB(0x09)、SPACE(0x20)をたどってさかのぼる
int j=-1;
int flag=OFF;
while( *(ptr+j)=='\x9' || *(ptr+j)=='\x20' )j--;

//その先にあるのが前の行の「行末」ならジャンプ先候補となり得る
switch( *(ptr+j) ){
case 0xd: //CR
case 0xa: flag=ON; //LF
break;

default: //スクリプトの最初の1行の先頭だった場合を考慮
if( TEXT_BUF - (unsigned char*)(ptr+j) > 0 ) {
flag=ON;
}
}

//ラベルの切り出し
int i=0;
do{
LABEL_2[i]=*ptr;
ptr++;
i++;
cnt++;
}while( i<32 && *ptr!=' ' && *ptr!='\xa' && *ptr!='\xd' && *ptr!='\x9' );
LABEL_2[i]=0;

//行頭フラグが立ち、かつラベルが一致したら脱出
if( flag==ON && strcmp(LABEL_1,LABEL_2)==0 ){
goto OUTLOOP;
}


}else{
// *ではない
ptr++;
cnt++;

}
}while( cnt<SIZE_OF_TEXT_BUF && flag==OFF);

char str[256];
sprintf(str,"ラベル [%s] が見つかりません。強制終了の刑♪",LABEL_1);
msg(str,"Com_jump()");
PostQuitMessage(0);



OUTLOOP:

TEXT = (unsigned char *)ptr; //テキストポインタ書換え(ジャンプ)

return 0;


}

いかがでしょうか。ソースはこちらです。サンプルスクリプトの記述と実際の動作を比較してみて下さい♪