VRM4スクリプト講座 第5回 ~時限式信号制御~

何だか妙にカッコいいような名前(?)ですが、やることは簡単です。

1、信号を通過したら信号を赤にする。
2、その後、一定間隔で信号を青へと推移させる。

早速スクリプトを書いていきますが、先に、前回とは別のレイアウトを用意し、5灯式信号機を配置してください。
無ければ別の信号でも良いですが、今回は5灯式用のスクリプトを記述します。

レイアウトに信号(SIGNAL-A)とセンサー(名前はどうでもいいです)を配置し、以下のスクリプトを記述します。

センサーのスクリプト
画像


Var HIT
SetEventSensor 切替 HIT

BeginFunc 切替
call "SIGNAL-A" タイマー
EndFunc


信号(SIGNAL-A)のスクリプト
画像


SetSignal 6
Var TIMER

BeginFunc タイマー
KillEvent TIMER
SetSignal 1
SetEventTimer this 灯火推移 TIMER 5000
EndFunc

BeginFunc 灯火推移
Var STATUS
GetSignal STATUS

ifeq STATUS 6
KillEvent TIMER
else
add STATUS 1
endif

SetSignal STATUS
EndFunc

※例の如く赤字はグローバル変数、青字はローカル変数を表しています。

いろいろありますがとりあえずこんな感じです。
では、一つずつ解説します。

センサー
・SetEventSensor ・・・ これは既に出ていましたね。センサーを踏んだ時に指定したメソッドを実行させます。
・call ・・・これも出ていましたね。他の部品のメソッドを呼び出せます。

信号
・SetEventTimer ・・・これは新出です。
SetEventTimerは、指定した間隔で特定のメソッドを実行し続けます。
SetEventTimer [部品] [メソッド] [イベントIDを代入するグローバル変数] [間隔(ms)]

今回は、同じ部品(this)の灯火推移メソッド、グローバル変数はTIMER、間隔は5000ms、つまり、5秒間隔で実行するように設定しています。

・GetSignal ・・・ 新出です。
GetSignalは、信号の現在の表示状態を取得します。
GetSignal [代入する変数]と記述します。
今回はGetSignal STATUSとなっているのでSTATUSに現在の信号の状態が代入されます。
代入されるのは、前回SetSignalで出した数値と同じです。停止なら1、進行なら6・・・のように代入されます。

・add ・・・これも新出です。
addは特定の変数に値を加える命令です。
add [加算される変数] [加算する値]となっています。加算する値は数値でも変数でもいいです。
例:add NUM 5 、 add SUM NUM

・ifeq ~ else ~ endif ・・・これは前回登場しましたね。ifeqは次の2つの値が等しいかを調べ、等しければ直下の処理を実行する、elseが条件に該当しなかった場合、直下の処理を実行する、endifが条件分岐の終了でした。

・KillEvent ・・・新出です。
KillEventは既に実行されているイベントを終了させるための命令です。
KillEvent [イベントID]となっています。
イベントIDはイベントごとに違った値が割り当てられるので、これでイベントを特定できることができるのです。

さて、これまでの記述をまとめると、以下のようになります(センサーは省略します)。

//ここから

初期状態の信号は「進行」
「TIMER」という名前のグローバル変数を用意する


以下タイマーメソッド
イベントID「TIMER」のイベントを終了させる
信号を「赤」へ
この部品の「灯火推移」メソッドを5000ミリ秒間隔で実行する。イベントIDを代入する変数は「TIMER」
メソッドここまで


以下灯火推移メソッド
「STATUS」という名前のローカル変数を用意する
現在の信号の状況を「STATUS」に代入する

もし、「STATUS」が「進行」だったら、
イベントID「TIMER」のイベントを終了させる
そうでなければ、
「STATUS」に1を加える
条件分岐おしまい

現在の信号の状況は、「STATUS」です。
メソッドここまで


//ここまで

・・・だいたいこんな感じですかね?

あと、この構文の中でのKillEventの必要性について。
いらないように見えるKillEventですが、次の異常動作の対策になります。

・タイマーメソッド内の「KillEvent」
ここの「KillEvent」が無いと、センサーを列車が通る度にメソッドの実行間隔がおかしなことになっていきます。
これまでのタイマーイベントに加えてさらにタイマーイベントを実行する・・・何回もセンサーを通れば・・・後はご想像にお任せします・・・
あと、ここの「SetSignal 1」が無いと、すぐに信号が変わらなくなります(「SetTimerEvent」で設定したイベントの初回の実行は設定した時間後となる。ここでは5秒後)。他にもいろいろ理由はありますが省略します。

・ifeq STATUS 6の下の「KillEvent」
ここの「KillEvent」が無いと、青になってもメソッドを実行し続け、SetSignal 7などのおかしな命令を実行し続ける原因になりかねません(変数を利用しているので見えにくいエラーでもあります)。
たとえここに「KillEvent」の代わりに「SetSignal 1」を入れても、折角青になった信号が赤になり、まともな信号の動作ではなくなってしまいます。通常の信号なら青になったらそのまま通過を待つはずです。何もしていないのに突然赤になったら困ります。

まあ、実際に消して動かすのが一番早いですけどね・・・

書く気力が限界になってきたのでそろそろ終わります。


2012/09/13 追記
タイマーメソッド内のKillEventについて、上記では「センサーを列車が通過する」度に実行間隔が・・・と言っていますが、正確に表現すると、「信号が進行以外の現示で、なおかつセンサーが列車を通過した」場合に実行間隔がおかしくなるという事です。

Next→
←Prev
TOP

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 0

この記事へのコメント

この記事へのトラックバック