「ゆゆぽん☆退避/追越列車とか作っちゃうかMona-(6)−信号灯火を切り換える」
VRMスクリプト禅問答
<<前回へ
今回は課題(2)-2“信号灯火を切り換える”です。結論から言えば、SetSignal命令を使って任意の灯火色を設定するメソッドを作り、これを前回扱ったセンサーのセンサーイベントのメソッドからcallする、それだけです。
ただし、本連載で目指すところの退避/追越列車の実現には、課題(3)“編成走行位置把握”、すなわち区間閉塞の管理が不可欠であり、そのためには単に信号の灯火色が変わるだけでは駄目です。今回は、サンプルコードから示すことにします。
[信号スクリプト]
//信号灯火色管理変数
Var VarSignalColor
call this MtgSignalG
//灯火色設定メソッド
BeginFunc MtdSingalR
set VarSignalColor 1
SetSignal VarSignalColor
EndFunc
//閉塞実施メソッド
BeginFunc MtdSectionBlock
//灯火色切替メソッドを実行
call this MtdSingalR
//以下は次回以降に追記
//
EndFunc
注目いただきたい点は2つあります。
第一には、冒頭のグローバル変数VarSignalColorの宣言です。以降、灯火色切替メソッドでは、SetSignal命令に対し、直接灯火色を示す数値を与えるのではなく、一旦set命令でこのグローバル変数に数値を代入し、変数経由でSetSignal命令に値を渡しています。
このように一手間かけているのには理由があって、それは信号灯火色の外部(他のオブジェクト)からの参照を可能にしたいからです。サンプルコードのように、灯火色切替に際し、設定する色をグローバル変数に記録する手順を遵守しておけば、他オブジェクトのスクリプトから{信号名称}.VarSignalColorを参照することで、簡単に信号灯火色を知ることが出来ます。
逆にこの方法を採らない場合、他オブジェクトがこの信号の灯火色を知るには、その時点で信号側のGetSignal命令を含むメソッドをcallし、そこでグローバル変数へ灯火色を示す数値を書き出して参照する、という手間がかかります。サンプルコードのようにすればこの手間が回避できます。これは、単に手間が少ないというだけでなく、無駄な仕組みを減らすことは、すなわち、意図通りに動作しない状態=バグの発現率を下げることにつながります。
ちなみに、
第四回で示したポイントの切替については、この手法を採らず、SetPointBranch命令に直接数値を与えていますが、これは、ポイントは信号とは異なり、ユーザーがビュワー操作からも状態を切り換えることが出来るからです。このような性格の要素(他にアクティブな編成や、編成の速度などがこれに当たります)については、値が必要になった時点でGet系命令で取得する、という考え方が必要です。
第二の点は、信号灯火色切替メソッドMtdSignalRとは別に、閉塞実施メソッドMtdSectionBlockを設けていることです。編成を検知したセンサーからは、後者をcallします。MtdSectionBlockでは冒頭でMtdSignalRをcallしていますから、結果的には同じことになるはずですが、もちろん、これにも理由があります。
結論から言えば“ある瞬間に目に見える効果を示すメソッド”と“出来事の流れを制御するメソッド”は分離した方が良い、ということになります。MtdSignalRは、まさに信号の灯火色を赤に切り換える“目に見える効果を示すメソッド”です。これに対し、MtdSectionBlockは、現時点では同じ効果しか持ちませんが、次回以降追記していくことで、ここから信号が青(G現示)へと遷移していく“流れを制御するメソッド”になります。
目に見える効果を示す部分、つまりこの例における信号を赤に切り換えるメソッドですが、このメソッドは、他にも使うことがあるかも知れません。今回の全体課題から言えば、退避列車が出発する際には、追越列車が追突してこないように、追越列車側の信号を赤にする必要があります。このとき、追越列車側の信号位置を列車が通過しているはずはありませんから、少なくとも前回から解説してきた“列車を検知したら隣接する信号が赤になる”という流れとは、異なる処理であることがわかります。
一方で、信号を赤にする、という瞬間の効果は共通していますから、これは共通部品として独立したメソッドにします。これには、部品を共通化することでスクリプトを書く量を減らせる、という直接的な効果は当然として、
・重要な手順−ここではグローバル変数に一旦灯火色を示す値を収め、外部からの参照を保証すること−を間違いなく徹底する。
・目に見える効果と流れの制御を分離することで、流れ制御のスクリプトを読みやすくする。
という効果があります。特に重要なのは後者の方で、これは次回以降、すなわち区間閉塞を自動化する段で威力を発揮してきます。