AKAGI Rails

鉄道模型シミュレーターで遊んでいたはずが、気づいたらPythonなども。

時限式信号機をATENXAで

怎麼生

ATENXA踏切が使えるようになり次は信号機を実装してほしいです。かといって閉塞の設定は面倒くさいので,TOMIXの信号機のように,列車通過で青→赤にしたあとは時限式で順に黄→青になってくれればいいです。なんとかなりませんか。

f:id:AKAGI-vrmstation:20210730233710p:plain

説破

時限式信号機はATENXA式イベントシステムで簡単に実装することができます。Python言語の便利なところを活用して,スクリプトを書くのはセンサーだけで,信号機はノータッチで済む方法をご紹介します。

ここでは,自動センサー1つではダイアログ設定のみでの実現が難しい,

  • 編成の先頭が通過すると赤にする
  • 先頭の最後尾が通過してからx秒で黄,y秒で青にする

というギミックを実装し,多少自分でスクリプトを書く努力が報われるようにしてみます。

ATENXA式イベントシステムとは

イベントハンドラと言われても正直良くわからない」「SetEventAfterを活用しようと思ったがいろんな処理がごっちゃになって挫折した」という方のために,もっと簡単に時間系イベントを取り扱えるようにしたシステムです。atenxa.richeventモジュールを読み込んで,レイアウトスクリプトでセットアップすると使えるようになります。

今回使うのは,AfterEvent(一定時間後に一度だけ発生するイベント)です。

atenxaのセットアップ(レイアウト)

通常の手順でATENXA式イベントシステムを有効にするには,レイアウトスクリプトrichevent関数を記述しておくことが必要です。

#LAYOUT
import vrmapi

# レイアウトと同じ場所のatenxaパッケージをimportするためにこの2行を書く
import os, sys
sys.path.insert(0, vrmapi.SYSTEM().GetLayoutDir())

from atenxa.richevent import richevent # 有効化コマンドをインポートした

def vrmevent(obj,ev,param):
    richevent(obj,ev,param) # ATENXA式イベントシステムを有効化
    if ev == 'init':
        pass
        # 以下省略

atenxaのインストールと基本的なimportの方法が初めての方は,ここここを読んでみるとよくわかります。たぶん。

信号機とセンサーの配置

f:id:AKAGI-vrmstation:20210730233535p:plain

f:id:AKAGI-vrmstation:20210730233538p:plain

図のように信号機とセンサーをペアで配置します。このとき,①信号機のデータ名(RAILSIGNAL_xxx)を覚えておきます。また,②初期設定だと赤信号になっていて雰囲気が出ないので,初期を青信号にします。

センサーのスクリプトを設定

#OBJID=515
import vrmapi
from atenxa.richevent import AfterEvent #AfterEventを読み込み

def vrmevent_515(obj,ev,param):
    if ev == 'catch':
        # センサー通過時の動作
        pairsignal = vrmapi.LAYOUT().GetSignal("RAILSIGNAL_516") # ペアの信号のデータ名を設定
        d = obj.GetDict()
        if param['tire'] == 1:
            # 先頭台車の検出時
            # 既存のタイマーイベントを削除
            try:
                d["ev_up3"].kill()
            except KeyError:
                pass
            try:
                d["ev_up6"].kill()
            except KeyError:
                pass
            # 即時信号を停止現示に
            pairsignal.SetStat(0, 1)
        else:
            # 後尾台車の検出時
            # 5秒後に注意現示
            d["ev_up3"] = AfterEvent(5, pairsignal.SetStat, args=(0, 3))
            # 10秒後に進行現示
            d["ev_up6"] = AfterEvent(10, pairsignal.SetStat, args=(0, 6))
        
    elif ev == 'init':
        # 起動時の初期設定
        # 前後台車の両方を検知
        obj.SetSNSMode(2)

設定は以上です。信号機にスクリプトを書き込む必要がないのが非常に簡単です。 同じネタをバージョン4/5時代にやった場合,信号とセンサーにそれぞれスクリプトを書き込む必要がありました。

なお,こちらのサンプルは3現示式信号機に対するものですが,現示パターンが増えた場合は,既存のタイマーイベントを削除する部分と,後尾台車の検出時にAfterEventを定義するところの2箇所にそれらしいコードを増やせばOKです。

著語

pythonに限らずプログラムに明るくない方はセンサーのプログラムは一見見にくいかと思われますが,まず#起動時の初期設定を見てから,#先頭台車の検出時のうち#既存のタイマーイベントを削除の部分を一旦読み飛ばして#即時信号を停止現示にへ進み,そのあと#後尾台車の検出時を読むとプログラムの流れが分かりやすくなるでしょう。

ATENXA式イベントシステムは,このように,ユーザーが各自で好きなギミックを実装したいときにも使えるものですが,もともと,ATENXA内部で使う性格の強いものです。ATENXA自動踏切の内部でも使用しています。アドバンストな使い方の参考になるかもしれません。

あと什麼生・説破というのは当然あの人のパクリです。