踏切をセンサーで作動させてみる(上り線のみの場合)

今回は上り列車しか来ない踏切を作っていきます。イメージとしては下の地図のような踏切です。

−yahooより加工−

上の地図は中央西線の美乃坂本−中津川間のもので、ここの一部区間は上下線が離れます。
よって、赤丸がうってあるところは名古屋行きの列車しか来ないのです。

今回は初回ですので、最も製作が簡単なこのタイプの踏切から作っていきます。

まず、車輌、遮断機(警報機はあとで追加します、TOMIX製は本体A・Bを使用)、センサー2つを用意して下さい。

なお、センサーは線路1つにつき1個のみ配置して下さい。1本のレールに2つのセンサーをのせるとセンサーが上手く動いてくれません。

今回のスクリプトの目標は、

「左のセンサーを列車が通過したら遮断機を閉める」

「右のセンサーを列車が通過したら遮断機を開ける」

です。

この2つのスクリプトを作れば踏切をセンサーで作動させられるわけです。

それではまず、 「左のセンサーを列車が通過したら遮断機を閉める」

というスクリプトを作っていきましょう。

まず、前回の信号機を赤に変えるスクリプトの流れですが、以下のようになっていました。

センサーの中
列車がセンサーを踏む

SetEventSensorでsnsevを発動

----snsev開始----
[SIGNAL7のcolor_redを発動させる]
----snsev終了----

信号機の中
センサーからcolor_redの発動命令が来る

color_red発動

信号機を赤信号に。

1つ目のスクリプトの最終目標は「遮断機を閉める」ですので、上記の信号機の中のスクリプトで考えてみると・・・

遮断機の中
センサーからcolor_redの発動命令が来る

color_red発動

遮断機を閉める。

となります。
しかし「遮断機を閉める」という機能の名前がcolor_redではナンセンスですのでclose(別にsimeruでもtojiruでも何でも良いです。自分の好きな名前を付けて下さい)と機能の名前(メゾット名)を変更します。

遮断機の中
センサーからcloseの発動命令が来る

close発動

遮断機を閉める。

これを踏まえるとセンサーのスクリプトの流れは自然に決まってきます

センサーの中
列車がセンサーを踏む

SetEventSensorでsnsevを発動

----snsev開始----
["遮断機"のcloseを発動させる]
----snsev終了----

"遮断機"の部分は前回解説したとおり遮断機の名前(オブジェクト名)です。 これもデフォルトの"CROSSING11"とかではなくて、cross1と名付けます(メゾット名と同じく"fumikiri"でも"syadanki"でも何でも良いです)
オブジェクト名を変更するのはデフォルトのままだと後々ややこしくなってくるためです。

なお、遮断機は2つで1セットなのでここのオブジェクト名はcross1-aとcross1-bとでもしておきます。

というわけで、このような流れのスクリプトを作っていきます。

センサーの中
列車がセンサーを踏む

SetEventSensorでsnsevを発動

----snsev開始----
[cross1-aとcross1-bにあるcloseを発動させる]
----snsev終了----

遮断機の中
センサーからcloseの発動命令が来る

close発動

遮断機を閉める。

さて、まずは遮断機から作っていきます。

2つの遮断機が同じ動作をするので、片一方のスクリプトを組めば、残りの方はコピぺでOKですね。
というわけなので適当に片一方の遮断機を選択します。


適当に選んだ方のオブジェクト名をcross1-aとします。

それからスクリプトエディターを開きます。

今回の遮断機のスクリプトの流れは、

遮断機の中
センサーからcloseの発動命令が来る

close発動

遮断機を閉める。

であり、最初の「センサーからcloseの発動命令」はセンサー側に書き込むので、遮断機のスクリプトに書き込むのは、

遮断機の中
close発動

遮断機を閉める。

以上の2つになります。

まず、遮断機を閉めるというメゾット(機能)を作ります。

踏切を閉める命令文はSetCrossingStatusを使います。
スクリプトマニュアルを開いて左のメニューの踏切欄のSetCrossingStatusという所をクリックしてみて下さい、以下のことが書いてあります。

SetCrossingStatus 変数

version 4.0.2.0

踏切の状態を設定します。

<中略>

1 踏切が開いた状態
2 踏切が閉じた状態

初回の内容から、これは

SetCrossingStatus 1 で遮断機を開ける

SetCrossingStatus 2 で遮断機が閉じる

ということですね。

それでは早速SetCrossingStatus 2を書き込んで

ビュワーを起動してみます。

ちゃんと遮断機が閉まりました。

では、この命令文を遮断機を閉めるというメゾット(機能)にするために、前回の信号機と同じようにBeginFuncとEndFuncで上下を固めてみます。
すると以下のようなスクリプトになりました。

BeginFunc

SetCrossingStatus 2

EndFunc

今回はこのメゾットにcloseという名前を付けます。BeginFuncのあとに半角スペースを挟んでclose(もしくは自分が考えたメゾット名)を入力します。

BeginFunc close

SetCrossingStatus 2

EndFunc

さて、これを書き込んで・・・

ビュワーを起動しますと・・・

遮断機は上がったままです。

さっきは閉まっていたのにどうして開いているのでしょうか?

ここでスクリプトマニュアルの言語仕様の欄の初期化という所をクリックして下さい。以下のことが書かれています。

初期化

ビュワーがレイアウトをロードした直後にすべてのスクリプトは、一度実行されます。この処理は、スクリプトの先頭からBeginFuncがあらわれるまでのメソッドの外側のコードを実行します。

<以下略>

つまり、スクリプトの頭からBeginFuncが現れるまでに書かれたスクリプトはビュワーを起動するときに実行しちゃいます。と書かれているのです。
裏を返せばBeginFuncが現れたらそれより下のスクリプトは実行されないわけです。
なのでBeginFuncより下にあるSetCrossingStatus 2は実行されず、遮断機は上がったままなのです。

それではBeginFuncより下の構文を実行させるにはどうしたらいいのか?

このとき使うのが前回出てきたcallという構文です。

つまり「call+メゾット名(BeginFuncの右側に半角スペース挟んで書いたヤツね)」でそのメゾットをやりなさいという命令文になるわけです。
しかも、このcallは違う部品のメゾット(前回で言うとセンサーが信号機のメゾットを実行するように命令しています)にも使えるという大変便利なものです。
しかし、「call+メゾット名」だけではどの部品のことかわからないので違う部品のメゾットをコールすることが出来ません。
ですので情報を一つ加えて「call+オブジェクト名(部品の名前)+メゾット名」というように"どの部品なのか"を明記します

ではこのcallはどこに書けばいいのか、それは"このタイミングでこれを実行しなさい"と指示できる部品、すなわちセンサーです。(頑張ればセンサー以外にも使えるヤツもあります)

 

 

 

ここで一度話を前回の信号機に戻します。  

 

 

センサーは"列車が通過したタイミングで○○を実行しなさい"と指示できます。
前回の例を見てみると。"列車が通過したタイミングでsnsevを実行しなさい"と指示しています。
ちょうどこの部分です。
Var evid
SetEventSensor snsev, evid

そしてsnsevの中身を見てみると・・・
BeginFunc snsev
call "SIGNAL7", color_red
EndFunc

SIGNAL7のcolor_redを実行しなさいと命令しています。

つまり、2段階に分かれて"実行しなさい"と言っているわけです。

なんで"列車が通過したタイミングでsnsevを実行しなさい"と"snsevの中でSIGNAL7のcolor_redを実行しなさい"の2段階に分けるのか、
素直に"列車が通過したタイミングでSIGNAL7のcolor_redを実行しなさい"と言えば良いじゃないかと思う方も居られると思います。

しかし、SetEventSensorがオブジェクトを指定できない構造になっていること、またSIGNAL7と一緒にSIGNAL8の信号機も赤くしたいときはこの2段階構造が便利であるのです。

例えば前回のスクリプトでSIGNAL7と一緒に他の信号機も赤くする場合

Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "SIGNAL7", color_red
call "SIGNAL8", color_red
call "SIGNAL9", color_red
call "SIGNAL10", color_red
EndFunc

と信号機のオブジェクト名をジャンジャン追加していくだけで赤色になっていく信号機を増やすことが出来るのです。

この
Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "オブジェクト名", メゾット名

EndFunc

という形は「センサーが反応したら[オブジェクト]の[メゾット]を実行する」という意味で

「センサーが反応したら○○が××する系」ならほとんどこれでOKというメチャクチャ便利なスクリプトです。
自分の中ではこの形はかなりの高頻度で使用します。


ちょいと一息。名松線  

 

 

それでは今回の遮断機を閉めるスクリプトの話に戻ります。  

 

 

今度はセンサーのスクリプトを書きます。

さっき書いた「センサーが反応したら○○が××する系」に当てはめると今回のは
「センサーが反応したら遮断機が閉じる」わけです。

言い換えると
「センサーが反応したら[遮断機]の[閉じる]を実行する」

さらに具体的な名前を当てはめると
「センサーが反応したら[cross1-a]の[close]を実行する」

という形になるのです。

それではこれをさっきのメチャクチャ便利なスクリプトに当てはめます。
Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "オブジェクト名", メゾット名

EndFunc

Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "cross1-a", close

EndFunc

これで完成!素晴らしく便利です!

というわけで早速書き込んで

ビュワーを起動すると・・・

ちゃんとセンサー通過後に遮断機が閉まります

今回のスクリプトの流れは

センサー反応→センサーのsnsev発動→cross1-aのclose発動→遮断機「閉」

という流れです。

 

 

 

さて、踏切の反対側の遮断機、すなわち適当に選んだ方の片割れも同じ動きをさせなくてはなりません。

早速スクリプトを書いていくのですが、センサー反応→センサーのsnsev発動の部分は同じなので、新たに作る必要はありません。
ということで、さっき書いた流れにcross1-bの動き組み込んだ形を書くと

センサー反応→センサーのsnsev発動→cross1-aのclose発動→遮断機「閉」
センサー反応→センサーのsnsev発動→cross1-bのclose発動→遮断機「閉」

となり、この青文字部分を作ればいいわけです。

しかもclose発動→遮断機「閉」部分は一緒なわけなので、コピぺで済みます。

それではまず、適当に選んだ方の片割れのオブジェクト名を変更します。

そして、cross1-bの中身であるclose発動→遮断機「閉」部分はcross1-aと全く一緒なのでcross1-aと同じスクリプトをコピー&ペーストします。

これで、cross1-bに関するスクリプトは完了です。続いて

snsev発動→cross1-aの・・・
snsev発動→cross1-bの・・・

ここの部分を作っていきます

先述したとおり、同じタイミングで動くオブジェクトの追加はsnsevの中に組み込みます。
Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "cross1-a", close
call "cross1-b", close
EndFunc

このスクリプトの意味は「センサーが反応したら[cross1-a]の[close]を実行する+[cross1-b]の[close]を実行する」 という意味になります。

というわけで早速書き込んでビュワーを起動します

ちゃんと列車がセンサーを通過するときに遮断機が閉じました。

これで当初の目標である 「左のセンサーを列車が通過したら遮断機を閉める」 が達成されました。

次は 「右のセンサーを列車が通過したら遮断機を開ける」 というスクリプトを組んでいきます。

まず、遮断機に"遮断機を開ける"機能を作ります。

はじめに遮断機を開ける命令文は
SetCrossingStatus 1
です。

これをcallで呼び出せるようにBeginFunc-EndFuncで上下を固めます。

ついでにメゾット名(機能の名前)はopenにしておきます。(別にメゾット名はakeruでもhirakuでも何でも良いです)

BeginFunc open

SetCrossingStatus 1

EndFunc

これを遮断機のスクリプトに書き込みます。

ついでにもう一方の遮断機にもこれを書き込んでおきます。

 

さて、次は右側のセンサーのスクリプトを書きます。

例によってメチャクチャ便利なスクリプトを使って
Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "オブジェクト名", メゾット名

EndFunc

Var evid
SetEventSensor snsev, evid

BeginFunc snsev
call "cross1-a", open
call "cross1-b", open
EndFunc

これで「センサーが反応したら[cross1-a]の[open]を実行する+[cross1-b]の[open]を実行する」というスクリプトが出来ました。

ちなみに[open]の部分はさっき遮断機に書いた
BeginFunc open

SetCrossingStatus 1

EndFunc

コレですね。

 

ちなみにIMAGIC規格には警報機が別で用意されています(TOMIXは一体)が、遮断機と同じようにやっていけばOKです。

あと、こことかこことかここで 書いてあるように、もし、コピぺ等で同じ名前のオブジェクトが2つ以上発生し、なおかつそれをcallした場合どちらのオブジェクトか解らなくなり大変宜しくない事態になってしまいます。

さて!これですべて完了です!

早速ビュワーを起動してみます。

ちゃんとセンサーに反応して遮断機が動きました!

 

しかし、当然のことながらこのように列車が踏切を通過中に開いてしまってはマズイです。

閉まりきらないうちに通過してしまうときは「閉める」と命令するセンサーを踏切から遠ざければ良いのですが、通過しきらないうちに開いてしまう場合、「開ける」と命令するセンサーは通過する編成の両数によって遠ざける位置が変わってきます。
さらに、実物の踏切は列車が通過したあとすぐに開ので、折角作るのなら是非ともコレを再現したいです。

そこで登場するのがSetSensorModeという命令文です。

スクリプトマニュアルのセンサーの欄にあるので開いて下さい。

ここで言っているのは

SetSensorMode 0 :先頭車が通過したら反応

SetSensorMode 1 :最後尾が通過したら反応

ということです。

つまり踏切のすぐ右側に「開ける」センサーを置き、SetSensorMode 1の状態にすればどんな長さの編成が来てもOKです。

というわけで右側のセンサーは最終的にこうなります。

これで列車が通過したあとに遮断機が上がります。

第2章の第1項の内容これで全部です。お疲れ様でした。

さて、今回は上り線のみの踏切という大変特殊なケースなのでこれだけでのスクリプトで良いのですが、もしこれを単線区間に設置したとします。

すると左から列車が来た場合、最初に「開ける」センサーが反応してしまいます。

次回からはこういった「こういう場合はどうするのか」ということを中心に扱っていきます。

次回は複線区間の踏切を作っていきます
次回へ>>>>


前へ戻る

inserted by FC2 system