![]() |
![]() |
この文章を書いた時点でのVRM4のバージョンは「4.0.0.4」です。これ以前のバージョンではうまく動作しません。また、今後のバージョンアップによって仕様が変更される可能性もあります。 |
車両に関する制御ですが、手始めにVRM3にあった「キーボードで編成を直接選択する」をやっておきます。既に誰かが作っていると思いますが、ここは自分流で。
例によって、原因と結果を分け、編成(結果)側は汎用性があるコードにします。
//Train Side VarTrain ac BeginFunc active get ac "TE1MAX" SetActiveTrain ac EndFunc |
編成エディターの「スクリプトエディター」に書きます。「TE1MAX」というのは自分自身の名前ですので、「SetActiveTrain this」とか出来ると思ったのですが、ちょっと甘かったようです。レイアウトに設置した編成ごとに、それぞれ名前を変えてスクリプトを書きます。ここでは、「TE751」「TE253」「TE1MAX」の3編成あるとします。
//Main Var cID1 Var cID2 Var cID3 SetEventKey this Tactive1 cID1 1 SetEventKey this Tactive2 cID2 2 SetEventKey this Tactive3 cID2 3 BeginFunc Tactive1 call "TE751" active EndFunc BeginFunc Tactive2 call "TE253" active EndFunc BeginFunc Tactive3 call "TE1MAX" active EndFunc |
メニューのスクリプトエディター(メインと呼ぶことにします)に上記を書きます。ここでは、キーボードの「1」「2」「3」で、編成を選択できるようにしました。重ねて言いますが、原因と結果を分けて書くことが重要です。例えば、「1」「2」「3」キーは他で使っているので「a」「b」「c」にしたい、という場合も、このメイン側をまとめて書き換えるだけで済みます。また、SetEventKeyはメイン側にまとめて書いた方が、何のキーを既に使っているのか一目瞭然って訳です。
それでは、本番です。車両の室内灯やヘッドライトを制御してみましょう。「非制御編」で登場した SetRoomlightや SetPantographなどを使いますが、車両によって、ヘッドライトのあるなし、パンタグラフのあるなしと様々ですので、車両に合わせて書く必要があります。ここでは、2つほど例を載せておきます。編成エディターの車両ごとに「右クリック→スクリプト編集」で入力していきます。
//先頭・最後尾車 BeginFunc roomON Var r set r 1 SetRoomlight r SetSignlight r EndFunc BeginFunc roomOFF Var r set r 0 SetRoomlight r SetSignlight r EndFunc BeginFunc HeadON Var r set r 1 SetHeadlight r set r 0 SetTaillight r EndFunc BeginFunc TailON Var r set r 0 SetHeadlight r set r 1 SetTaillight r EndFunc BeginFunc PantOFF Var r set r 0 SetHeadlight r SetTaillight r SetRoomlight r SetSignlight r EndFunc |
//中間・パンタ車 BeginFunc roomON Var r set r 1 SetRoomlight r SetSignlight r EndFunc BeginFunc roomOFF Var r set r 0 SetRoomlight r SetSignlight r EndFunc BeginFunc PantON Var r set r 1 SetPantograph 0 r EndFunc BeginFunc PantOFF Var r set r 0 SetPantograph 0 r SetPantograph 0 r SetRoomlight r SetSignlight r EndFunc |
ちょっと長いですが、もうこのくらいではビビらないですよね。基本的には同じような内容の繰り返しです。室内灯(SetRoomlight)と方向幕(SetSignlight)は、同時にオンオフしています。どちらか一方だけ点いているという場合は少ないと考えたからです。ヘッドライト(SetHeadlight)とテールライト(SetTaillight)も両方同時に点くことはないので、一方を点灯させたらもう一方はオフにするようにしています。さらに、パンタグラフ(SetPantograph)を下ろしたら電源が切れる訳ですから、室内灯などもオフにするようにしています。このため、パンタを持たない車両にも「PantOFF」を書いて、パンタ下降命令が来たら、照明をすべてオフにする処理を行っています。「PantOFF」は車両のすべての照明を切る命令と思って頂いた方が分かりやすいと思います。
注:上記は車両に関するブラックボックス的処理ですので、室内灯・方向幕・パンタグラフなどごとにオンオフするメソッドを作っておいて、室内灯と方向幕を同時に点けるという処理は、それを呼び出す側で処理した方がベターです。が、繁雑になると思ったので上記のような処理にしましたが、却って分かりにくくなったかもです。
注:ポイント制御でやったように、現在の状況をゲットして‥‥‥というのはやっていません。すでに、室内灯が点いているのに重ねてSetRoomlightでオンしても問題ないと考えたので割愛しました。実際、問題はないようです。
//main Var sID1 Var sID2 Var sID3 VarCar c Var Spant Var Slight Var Shead SetEventKey this Mpant sID1 1 SetEventKey this Mlight sID2 2 SetEventKey this Mhead sID3 3 set Spant 1 set Slight 1 set Shead 0 BeginFunc Mpant if Spant set Spant 0 set Slight 0 getcar c "TE253" 0 call c PantOFF getcar c "TE253" 1 call c PantOFF getcar c "TE253" 2 call c PantOFF else set Spant 1 getcar c "TE253" 1 call c PantON endif EndFunc BeginFunc Mlight if Slight set Slight 0 getcar c "TE253" 0 call c roomOFF getcar c "TE253" 1 call c roomOFF getcar c "TE253" 2 call c roomOFF else set Slight 1 getcar c "TE253" 0 call c roomON getcar c "TE253" 1 call c roomON getcar c "TE253" 2 call c roomON endif EndFunc BeginFunc Mhead if Shead set Shead 0 getcar c "TE253" 0 call c HeadON getcar c "TE253" 2 call c TailON else set Shead 1 getcar c "TE253" 0 call c TailON getcar c "TE253" 2 call c HeadON endif EndFunc |
メイン側はなんでもいいのですが、ここでは、1つのキーでオンオフを切替える、即ち、
1=パンタの上下
2=室内灯のオンオフ
3=ヘッドライト/テールライトの切替え
としました。もちろん、「1=パンタ上昇、2=パンタ下降」などとすることも出来ます。 1つのキーでオンオフを切替えますので、現在の状態を覚えておく必要があり、その役目を「Spant」「Slight」「Shead」というグローバル変数(コモン・共通変数)に負わせました(安易な方法ですので、変数の内容と実際の状態が食い違うという危険性があります)。
せめてもの償いに、「set Spant 1」「set Slight 1」「set Shead 0」という初期化を行っています。例えば、パンタグラフ(Spant)は初期状態で開いていますので、「1」をセットしておきます(「BeginFunc〜EndFunc」の外側はビューアー起動時に一度だけ実行されますので、初期化ルーチンはそこに書きます)。‥‥‥やっぱり、分かりにくくなってしまいましたね。一応、これで編成全部の車両の室内灯を一括してオンオフする、などの操作ができます。
注:実はこのプログラムでは、パンタを下ろした状態でも室内灯が点いてしまいます。パンタを下ろした状態では「roomON」などは無視するという処理を加えないといけないですが、繁雑になるので割愛しました。というか、うまく書けなかったので、プログラムの得意な人、お願いします(^^;
なんか面白くないので、最後にちょっと変わったことをやってみます。
なんか横向いていますけど、上図は引き込み線のつもりで、ここに列車が進入したということは留置するってことですので、車止めにぶつかる前に「自動で停止し照明を全部オフにする」ことにします。また、いきなり停止するのは不自然ですので、ある程度減速してから停止することにします。
まず、編成に減速・停止するメソッドを書きます(「編成エディタ」→「スクリプトエディター」)。
//Train BeginFunc T_teisi Var v set v 0 SetVoltage v EndFunc BeginFunc T_gensoku Var f Var t setf f 0.3 set t 1000 SetTimerVoltage f t EndFunc BeginFunc T_turn Var v GetCurrentSpeed v ifzero v Turn endif EndFunc BeginFunc T_horn PlayHorn EndFunc |
ついでに方向転換するメソッドと警笛を鳴らすメソッドを書いておきました。こうやってなるべく汎用性のある処理を書いておくと、後々いろいろな用途に使えます。取り敢えず書いておいて結果的に使わなかったでも構いません。 なお、編成を停止するのは、SetVoltageで電圧を0にします(Nゲージの感覚ですね)。減速の場合は徐々に減速させるため、SetTimerVoltageを使っています。また、方向転換(Turn)は現在のスピードが"0"の場合のみ出来るとして、GetCurrentSpeedで現在速度を読み取っています。各命令の詳細はマニュアルを参照してください。
では、レール上の適切な場所にセンサを用意して、それに対するスクリプトを書きます。まず、退避線に入った辺りに減速用のセンサを置きます。
//Sensor Sub01 Var snsID1 VarTrain SnsTrain SetEventSensor S_gensoku snsID1 BeginFunc S_gensoku GetSenseTrain SnsTrain call SnsTrain T_gensoku EndFunc |
これは、簡単ですね。センサで検出した編成の「T_gensoku」メソッドを呼び出しているだけです。センサが、自分が検出した列車に対して『お前、危ないから減速せなあかんぞ』と命令を出している訳です。
車止めの直前には、第2のセンサを置き、こっちはフルストップさせるスクリプトを書きます。
//Sensor Sub02 Var snsID2 VarTrain SnsTrain VarCar c1 SetEventSensor S_teisi snsID2 BeginFunc S_teisi GetSenseTrain SnsTrain call SnsTrain T_teisi getcar c1 SnsTrain 0 call c1 PantOFF getcar c1 SnsTrain 1 call c1 PantOFF getcar c1 SnsTrain 2 call c1 PantOFF // call SnsTrain T_turn EndFunc |
これも、センサが検出した編成に対していろいろ命令を出してします。「SnsTrain」に対して「T_teisi」命令を出したあと、今度は各車両に対して照明オフ(PantOFF)命令を出しています。これは、各車両に対する命令ですので、getcarで各車両をゲットしています。この場合、3両編成なので上記のようになりますが、対象となる列車の編成状況によって処理を変えないといけないので、ちょっと汎用性に欠けます(注)。
注:BASICでいう FOR〜NEXT命令があればいいのですけどね。あと、編成の車両数をgetする命令も必要かも。
注:照明を消した後、自動で方向転換するなら、プログラム下から2行目のコメント(//)を外せばOKです。また、退避線から出発することについては考慮していません。照明を手動で点けないといけないのはいいですが、出発後、減速センサーの上に達すると速度が勝手に最高速度の30%になってしまいます‥‥‥ま、それも愛敬ですが。センサをさらに追加して、列車がどっちから来たかを判定すれば、対処できないことはないですけど‥‥‥。
ここまで出来れば、もう何でも出来ます。例えば、
・ループを3周したあと、引き込み線に入って停止・照明を切る。
・駅で自動で停止・発車させる。
減速の方法も、例では、1秒かけて最高速度の30%(130km/hの場合39km/h)にしていますが、1秒というのはちょっと急過ぎるかもです。また、39km/h未満で進入した場合、加速することになってしまいます。この辺はいくらでも工夫できると思いますので、各人のコダワリを見せたいところですね。
なんでも出来ると書きましたが、「原因」となる事象が限定されています。第0号の段階では、
・キーボードのキーを押す(SetEventKey)
・センサが編成を検出する(SetEventSensor)
・一定時間後、または、一定時間周期でイベントを発生させる(SetEventTime、SetEventTimer)
しかありません。列車の速度が"0"より大きくなったら(列車が走り出したら)、ヘッドライトを点ける、なんてのは出来そうで(直接的には)出来ません。SetEventTimerで定期的に速度を監視する方法もありますが、処理が重くなりそうです。