■ 新・ゲーム開発講座




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


■第36夜:コメント文

本講座の開設当初は予定になかったのですが、前回 config.txt でコメントを入れるのに #jump コマンドでカッコ悪い逃げ方をしましたので(笑)、せっかくだからコメント文にも対応もしておこうかな・・・などと思い立ちました。そんな訳で今回は、
スクリプト中にコメントを入れる方法について解説します。

「コメントくらいなんだ〜」と言う方もいるかもしれませんが、スクリプトもちょっと込み入ったものを書き始めると、途端に構造把握ができにくくなって来るものです。やはり、一言二言コメントが挿入できるようにしておくのは必要なことなんですよね。プログラム的に見たコメント文は、単にテキストを無視するだけの動作なので実装もらくちんです。

ちなみに、例として以下に「彼女と触手の素敵な関係」のスクリプトの一部を示します。
## に続く部分がコメント文ですが、これが無かったら書いた本人でさえ「えーと、えーと・・・・」になりそうですね(笑)。


【サンプルスクリプト:彼女と触手の素敵な関係より】

#run_on
#clear_define_table WORK00,WORK03
#define WORK00,rika_x
#define WORK01,rika_y
#define WORK02,paku_x
#define WORK03,paku_y

#mov rika_x,250 ##利香表示位置X
#mov rika_y,60
##利香表示位置Y
#mov paku_x,rika_x
#mov paku_y,rika_y
#add paku_x,50
#add paku_y,50
#g_copy VRAM,0,0,BGRAM01,0,0,640,480
##背景
#g_copy VRAM,rika_x,rika_y,BGRAM02,0,0,150,340
##利香

#disp_date VRAM,20,20,BGRAM03,@MONTH,@DAY,午前 ##日付
#disp_stat VRAM,20,60,BGRAM03
##ステータス

#interval_anime_on VRAM,paku_x,paku_y,BGRAM02,150,0,60,50,y,6,50,5000
#wd 0
#text_mode ADV
#run_off


■書式

そんな訳で、コメントの書式です。面倒なので「長野旅行記」「彼女と触手〜」と同じ仕様にします。アセンブラの REM や C++ の // と同様の1行コメントですが、実用上これで充分でしょう。

書式:##コメント文〜

##を見つけたら行末までをコメント文とみなして無視する


■実装

今回の講座で開発しているシステムでは、コマンド識別子として # を使っています。## をコメントとして使用することで、実はコメント文もコマンドの変形バージョンとして実装が可能です。通常のコマンドがスペース区切りの独立した単語になるのと違い #############・・・・などの表記も許容したいので、コマンド解析を担当するTextEngine.cppCommand_call() で、単純な文字列比較ではなく # が2回続いたら行末まで飛ばすようにしてしまいましょう。そんな訳で、今回はコマンド用の関数は作らず、Command_call() の内部に少々手を加えるだけで済ませてしまいます。なんと↓たったこれだけ(爆笑)

※蛇足ながら解説しますと、Command_call() が呼ばれた時点でテキストポインタ *TEXT はコマンド識別子 # を指しているので、前後を調べて隣りにも # があればコメント文だな、と判定している訳ですね。


void Command_call()
{

char com_name[256];
int i=0;
int flag=OFF;

//コメント文対応
if( *(TEXT+1)=='#' || *(TEXT-1)=='#' ) {

//#が2回連続したらコメント文なので行末(CR=0x0d)までテキストポインタを飛ばす

while( *TEXT!=0x0d ) TEXT++;
return;

}

TEXT++; //#を飛ばす

//コマンド文字列の切り出し
while( *TEXT>0x20 ) {
com_name[i] = *TEXT;
TEXT++;
i++;
}
TEXT--;
com_name[i]=0; //これはNULL文字

//コマンド名の評価 → 処理関数呼び出し
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;} //ファイル間ジャンプ
if( strcmp(com_name,"select3" )==0 ){ Com_select3(); flag=ON;} //3択
if( strcmp(com_name,"play_wav")==0 ){ Com_play_wav(); flag=ON;} //WAV演奏開始
if( strcmp(com_name,"stop_wav")==0 ){ Com_stop_wav(); flag=ON;} //WAV演奏停止
if( strcmp(com_name,"play_midi")==0 ){ Com_play_midi(); flag=ON;} //MIDI演奏開始
if( strcmp(com_name,"stop_midi")==0 ){ Com_stop_midi(); flag=ON;} //MIDI演奏停止
if( strcmp(com_name,"set_font_size")==0 ){ Com_set_font_size(); flag=ON;} //フォントサイズ変更
if( strcmp(com_name,"set_text_area")==0 ){ Com_set_text_area(); flag=ON;} //テキストエリア変更
if( strcmp(com_name,"set_text_wait")==0 ){ Com_set_text_wait(); flag=ON;} //テキストウェイト変更
if( strcmp(com_name,"set_text_color")==0 ){Com_set_text_color();flag=ON;} //テキストカラー変更

// ↑
//そのうちここに他のコマンドも追加していきましょう
// ↓

//フラグを見て、切り出されたコマンド名が有効なコマンドだったかどうか確認する
if( flag == OFF ){

char str[256];

sprintf( str,"警告:無効なコマンド [#%s] が記述されています",com_name);
MessageBox(NULL,str,"Command_call()",MB_OK);

}


}

あれれ、if 文の *(TEXT+1)=='#' は分かるけど *(TEXT-1)=='#' って何だ?・・・という方・・・鋭いです。実はこれ、お恥ずかしながらバグ対策だったりするのです(大爆死 ^0^;)。コマンドパラメータ解析関数の最後でテキストポインタを+1していることが原因で、コマンド行でスペースまたはTABを1個だけ挟んでコメントが続いた場合、最初の # が読み飛ばされてしまう場合があるんです(超大汗 ^^;)。そんな訳で、とりあえず前後1バイトを調べて # が連続していたら・・・という判定方式になっています。ちょっとカッコ悪いですね・・・反省 m(_ _)m

とゆーことで、ソースはこちらに置いておきますので動作確認などしてみて下さい。実質4行の追加程度でわざわざフルセットでダウンロードできるあたり、我ながら粋狂なことなど思いますが・・・まあ気にしない、気にしない(笑)。次回からは、もうちょっと真面目にやりますのでご勘弁願います(をい ^0^;)