2006/8/30
駅に止まったときだけ“何か”が怒る VRMスクリプト禅問答
(前略)に関してお節介を焼いてみよう、と発作的に思い立った。音源の制御自体は(少なくとも、この記事を読んで自分でスクリプトを書こうと思う人にとっては)特別に難しいことではないので、ここでは以下のことを実現する方法について書くことにする。
発車チャイムやドアの開閉音はSetEventZeroSpeedとSetEventAfterを使えば、駅に停車するたびに鳴らせますね。
Posted by 45-50s at 2006年08月28日 17:45
(前略)
駅に到着した事を認識するのはセンサーなのか、その他の部品なのかは問題ですが、時間指定をすれば、いちいちキーを押さなくても済みますね。
(後略)
Posted by KSMaster at 2006年08月28日 21:45
KSMaster's blog/快速天王寺行き発車! コメント欄より
(1) 編成が停車して指定時間後に「何か」が起きるようにしたい。
(2) ただし、「何か」が起きるのは駅構内の所定の位置に停車したときだけにしたい。つまり、本線上で停車しても「何か」は起きない。
さて、上記(1)(2)、特に(2)を実現するにあたっては、KSMaster氏が書いているように「駅に到着した事を認識する」ことが必要である。これをどうするかだが、次のように考えてみた。
・2つのセンサー[センサーA]と[センサーB]を用意する。
・[センサーA]は「これ以上手前に止まったら駅停車とはみなさない」地点に置く。列車が(どんな速度であろうと)ここを通過したとすれば、それは駅停車の「可能性が生じた」ことを意味する。
・[センサーB」は「これを越えて止まったら駅停車とはみなさない」地点に置く。つまりオーバーランの限界点。ここを通過したとすれば、それは駅停車の「可能性がなくなった」ことを意味する。
[センサーAスクリプト]と、こんな感じ。例によって出先で書いているのでバグってたらゴメン。
Var SensorEventID
SetEventSensor 編成検知 SensorEventID
BeginFunc 編成検知
VarTrain ObjTrain
GetSenseTrain ObjTrain
call ObjTrain 駅停車準備
EndFunc
[センサーBスクリプト]
Var SensorEventID
SetEventSensor 編成検知 SensorEventID
BeginFunc 編成検知
VarTrain ObjTrain
GetSenseTrain ObjTrain
call ObjTrain 駅停車準備取消
EndFunc
[編成スクリプト]
Var StopEventID
Vat AfterEventID
BeginFunc 駅停車準備
SetEventZeroSpeed 停車完了 StopEventID
EndFunc
BeginFunc 駅停車準備取消
KillEvent StopEventID
EndFunc
BeginFunc 停車完了
SetEventAfter {オブジェクト} {何かをするメソッド} AfterEventID {経過時間}
EndFunc
センサーA/Bのスクリプトは至極簡単で、それぞれ検知した(センサーの上を通った)編成のメソッド駅停車準備/駅停車準備取消をcallするだけ。これが前述した、駅停車の「可能性が生じた」「可能性がなくなった」に対応している。
編成スクリプト側の当該のメソッドは、変数StopEventIDを使う表裏の処理になる。つまり、駅停車準備ではSetEventZeroSpeed命令によって停車時に発生するイベントを設定し、駅停車準備取消ではKillEvent命令でこれを無効化している。つまり、センサーAを通過した列車が、センサーBに至る前に停車すればメソッド「停車完了」が実行れるが、センサーBを通過してしまうとこのイベントが解除されてしまうので、メソッド「停車完了」は実行されない。言うまでもなくこれが、本線上で停車しても「何か」は起きない、に対応している。
メソッド「停車完了」では、停車してすぐにドアが開いたりその他のことが起きるのはアレゲなので、SetEventAfter命令で指定時間待ってから「何か」を起こすようにしている(これは必須ではない)。{オブジェクト}{何かをするメソッド}を、あなたが起こしたい「何か」を実現するそれに書き換えれば実装完了。
この方法のメリットは、編成がその駅に停車するのか通過するのかを、まったく意識する必要がない点にある。逆に言うと、この方法であれば、編成の走行自体をまったく別の方法(たとえば拙作gws/1.0自動運転スクロールなど)で自動化していたとしても、変数名・メソッド名が衝突しない限りはお互いに影響することなく合わせての組み込みが可能だ。
ここに示したのは基本的な骨組みだけで、もう少し改良の余地はある。たとえば、メソッド「停車完了」が実行されてからユーザーが手動操作で編成を出発させると、列車が動きながらドアが開く音がする、という危険な状態に陥る。これを防ぐには、列車の出発に連動して変数AfterEventIDをKillEventするとか、あるいは、SetEventZeroSpeedと同時にSetFixVolumeModeで出発を封じるといった対策が必要。
また、StopEventIDをKillEventすると同時に、別のメソッドを実行するSetEventZeroSpeedを仕掛けてやれば、駅以外のあらぬ位置に停車した際に“どこに止めてんだと、ゴルァ!”と怒ることだって出来る。っつーか、こっちの方が正しいな、メッセージとしては。
