keimei main -> キハポスト@VRM -> VRM4スクリプト -> リアルタイム制御編

VRM4スクリプト(9)〜リアルタイム制御編

この文章を書いた時点でのVRM4のバージョンは「4.0.0.6」です。これ以前のバージョンでは間違いなく動作しません。また、今後のバージョンアップによって仕様が変更される可能性もあります。

●時計を作る●

SetEventTimerという命令があります。これは、一定時間ごとにメソッドを呼び出す命令です。レイアウトスクリプトで、

Var mID1
Var clock
Var one

set one 1

SetEventTimer this realtime mID1 1000

BeginFunc realtime
 add clock one
 DrawVar clock
EndFunc

とすると、 realtimeメソッドが1秒ごとに実行され、clock変数が経過秒数を示します。つまり、これはサンプリング制御、実時間制御が可能だということです。ATC編でやった、一定時間ごとに編成の位置をチェックするというのがそうですし、絶対時間制御相対時間制御、その気になれば本格的なフィードバック制御も可能かもしれません。

注:SetEventTimerでの時間は「実行しているパソコンの性能によってループ速度がことなるため、厳密に一定の時間で発生することはない」とマニュアルにある通りです。幸いうちのPCでは、上記の命令は「ほぼ1秒ごとに」実行しているようです。

注:ビューアー起動中、clockは延々と増え続けることになります。変数は整数の場合、32bit longだそうですから、2^32までカウントすると0に戻ります。が、そこまで長くビューアーを実行し続けることはないと思いますので、オーバーフローについては考えないことにします(2^32秒が何年になるか計算してみてください)。訂正:変数は符号付きなので2^31-1から-2^31‥‥‥あんまり書くと傷口を広げそうなので、まあ、とにかくでっかい数ってことで(^^;

●実時間制御●

VRMの遊び方の1つにカメラ列車とか遊覧列車とかというものがあります。これは、自動運転される列車に乗って、そこからの風景を楽しもうというものです。列車に限らず、自動車や船に乗っていることを想定したものもあります。スクリプトを使うと非常に柔軟な遊覧走行が可能になります。例えば:

・.ビューアー起動後30秒後に列車が発車
・50秒後に自動で減速、さらに、90秒後に再加速
・あるいは、見所シーンを通過する時には自動で徐行

などが考えられます。また、列車と列車をピンポイントですれ違わす、ということもやりたいですね。その場合は、

・すれ違うポイントにカメラ列車が到達するのはスタートから40秒後である
・ならば、すれ違いの相手列車を35秒後にスタートすればいいな‥‥‥
・いや、35秒後だと早すぎたので、37秒後にしてみよう‥‥‥。

ある程度、試行錯誤は必要ですが、VRM3よりはずっと簡単に出来そうです。

●駅での停車時間を制御●

さて、駅で列車を止めて指定時間後に発車していく、という処理をやってみましょう。ここでは、大まかな処理の流れを日本語で解説してみます:

レイアウトスクリプト
・ SetEventTimerで「realtime」メソッドを1秒ごとに実行
・「clock」変数に「1」を足していく:「clock」は経過秒数を表すことになる
編成スクリプト
1. 車輌制御編でやった「T_KasokuFull」「T_Teishi」などのメソッドをプログラムしておく

センサスクリプト:駅の停車させたい位置に設置
1. 編成を検出したら「T_Teishi」をcallし、編成を停車させる
2. レイアウトの「Eki」変数(フラグ)を「1」にする
3. レイアウトの「clock」変数に「0」を代入

レイアウトスクリプト
・以下は「Eki」フラグが「1」の場合に実行
0. 「clock」変数に「1」を足していく
1.「clock」が停車時間(例:15)以上ならば、
   1-1.編成の「T_KasokuFull」を呼出し、列車を発車させる
   1-2. 「Eki」フラグを「0」にする

こんな説明で分かるでしょうか?要は、clock変数が15増えたら=15秒経過したら列車を発車させるってことです。

●相対時間制御●

リアルタイム制御を利用すると様々なことが出来そうですが、ここでは、ちょっと毛色の変ったことをしてみます。

列車の(およその)現在位置はATC編でやったようにすれば分かります。スピードは、上記に従って1秒ごとにゲットすればいいですね。では、加減速は?‥‥‥これは、前回のスピードと比べれば分かります。

Now_Speed:今回の速度
Pre_Speed:前回の速度

1.今回の速度をゲット(Now_Speedに代入)
2.今回(Now_Speed)と前回(Pre_Speed)を比較→各処理
3.今回(Now_Speed)を前回(Pre_Speed)に代入

リアルタイム制御に慣れた人なら誰でも思い付く処理ですね。例えば、今回が前回より大きければ加速していることになりますし、今回が前回より20km/h以上小さいと、それは急ブレーキってことです。これにより、人間が運転している列車がどういう挙動を示しているのか、スクリプトが把握できるってことです。これを利用したのがゲーム「Eki de Stop」です。

★「Eki de Stop」の遊び方★

あなたは列車の運転手です。あなたの列車をうまく運転して、駅でピタリと停車させてください、というゲームです。まあ、「電□でG○!」を思って頂ければいいかと。人間が運転する列車をスクリプトが評価するという生意気なゲームです。

ビューアーを起動して、列車を少し走らせると勝手に最高スピードになります。そうしたらゲームスタートです。ループの半周先に駅があります。第0号では停止標などはありませんから所定の地面に「STOP」と書いてありますので、その位置で列車を止めてください。もし、手前で停車してしまったり、オーバーランした場合は「ゲームオーバー」です。もちろん、急ブレーキは厳禁ですし、一旦減速してからの再加速も減点対象です。

取り敢えず作ってみたって感じで、細かい配慮などはされていませんが、ご自分でルールを追加したり厳密さを追求したりして頂いても結構です。もちろん、このゲームが第三者に与える影響については一切保証しませんので。

▼ダウンロード(EkiDeStop.lzh:319kB)