■ 新・ゲーム開発講座




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


■第11夜:スクリプトコマンドの基礎「遅延」A

えー、前回の続きです。コマンド実行部を呼ぶまでが少々長かったかもしれませんが(笑)、前回と今回の内容が分かってしまえば、あとは Mainloop()Command_call() に同じ要領で別コマンドをぶら下げていけば良いのでルーチンワークみたいな感じで機能充実できるようになります。そんな訳で、今回はコマンドの実行部分の記述について解説します。

コマンド実行の各要素は、初期化(撃つ)、タスク(回す)、終了(締める)の3要素に分解できる・・・といいました。もっとうまい表現があるのかも知れませんが、なるべく定型化して説明したほうが分かりやすいかな・・・と思ってのことです。他のサイトではそんなこと一言も言ってないぞー、とゆーユッコミは却下します(^^;)。



繰り返しになりますが、「撃つ」部分は基本的に Mainloop で参照している処理フラグを立てるのが最大の役割です。ただし今回作成しているシステムではトリガ(処理開始の引き金)となるのがテキスト解釈 → コマンド評価の部分になりますので、処理の中にはスクリプト上のパラメータ類(もしあればですが)の読み込み等も含まれます。

また「回す」部分は Mainloop から繰り返し呼ばれるコマンドのタスク処理部分(ここではタッチ&ゴー式にタイムスライス状の処理を行うくらいの意味合いでタスクと呼んでいます ^^)にあたります。

そして「締める」部分は処理フラグをクリアして、「回す」処理が Mainloop から呼ばれないようにするものです。タスク処理の中でカウンタやタイマーを回して終了条件を判定する場合もあれば、キー/マウス入力をトリガにして終了条件を判定する場合もあります。

以上の機能を関数にまとめると、2つないし3つの関数構成になります。「締める」部分があまりに単純な場合は、「回す」部分に含めて記述してしまってもかまいません。実際、ここで示す遅延処理ではそうなっています。

■撃つ

では具体的に見てみましょう(前回のソースは今回も共通です ^^)。TextEngine.cpp のスクリプトコマンド評価関数 Command_call() #delay というコマンド文字列を評価し、適合したら Com_delay() という関数を呼んでいます。これが「撃つ」処理を呼んでいるところです。実際の処理内容は以下のようになります。



DWORD delay_timer; //タイマー用変数
DWORD delay_wait; //何ミリ秒待つのか記憶しておく変数

int Com_delay()
{

//待ち時間を解析する
delay_wait = kaiseki_10();

flag_delay = ON;

HLS_timer_start(&delay_timer); //遅延のためのタイマーを撃つ

return 0;


}


まあ、クラスにまとめてしまえばもう少しスッキリするのでしょうが、とりあえずグローバル変数と関数のセットで行きます(汗 ^^;)。処理の内容ですが、まずはテキスト上のパラメータを解析しています。kaiseki_10() というのはテキスト中の10進数を解析して結果を返す関数で、TextEngine.cpp に記述してあります。いちいち解説はしないのでソースをご覧ください(^^)。解析した結果は変数 delay_wait に格納しています。そして、Mainloop で参照しているフラグ flag_delayONにします。これでタスク部分が Mainloop から連続コールされるようになった訳ですね。最後に、遅延処理を行うためにタイマーを撃っています。

タイマー処理ですが、GetTickCount() でシステム起動からの経過時間をメモしておき、後にふたたび GetTickCount() で時間を取得して差を調べる、という方法を用いています。いちいち if 文を書くのも面倒なので、以下のような関数を作って呼び出すようにしています(BasicTips.cppにもう少し詳しい記述あり)。



int HLS_timer_start( DWORD *timer )
{

*timer = GetTickCount();

return 0;


}

int HLS_timer_check( DWORD timer , DWORD wait_time )
{

if( timer+wait_time <= GetTickCount() )return true;

return false;


}



■回す/締める

フラグが ON になったら、Mainloop から「回す」部分に相当するタスク処理が呼ばれます。Text_Com_01.cppCom_delay_task() がそれに相当します。見れば分かりますが、やっていることは至極単純です。指定時間経過していなければ何もせずリターン、指定時間経過したらフラグを解除。・・・これだけです。このフラグを解除する部分が「締める」動作にあたります。あまりに単純なので一緒に記述している訳ですね(笑)



int Com_delay_task()
{

//指定時間経過したか? → していなければ何もせずに戻る(=待ち続ける=「回す」処理)
if( HLS_timer_check( delay_timer,delay_wait)==false )return 0;

//遅延フラグを解除する(これで Mainloop()側で文字表示が可能になる)
flag_delay = OFF;

return 0;


}


■では、実際に動作を♪

では、ソース(前回と共通)をコンパイルして実行させてみましょう。ずらずらとテキストが表示されて行き、途中で1秒と3秒の遅延が実行されたと思います。テキストファイル dafault.txt(これがデフォルトのスクリプトファイルです)の内容をいろいろ変更して、TAB や改行が無視されていることも確認してみて下さい。以降、これを雛形にしてコマンドを増やして行きます。