« Re460 | Main | S Bahn »

2005/10/26

連鎖メソッド  VRMスクリプト禅問答
【怎麼生】
ポイントを4つ使ってクロスポイントを作ります。どんなスクリプトで制御するのがいいですか。
VRMovies BBS/VRM4を買った人 改め 512氏の投稿より趣意抜粋)

【説破】 4.0.2.4
「連鎖メソッド」を書いて、制御の入り口を集約するのが賢明かと思われます。


連鎖メソッド、と言うのはghostの勝手な造語です。ここでの意味は「あるメソッドを実行すると、内部で他のオブジェクトのメソッドをcallし、それが更に次へと連鎖する」といったものだと考えてください。コレなんかがその端的な例になっています。
お尋ねの件を例に考えると「4つのポイントをクロスポイント風に一気に切り替える」場合、[A]全部が正位になる/[B]全部が反位になる、しか結果はありえませんから、これを制御するのに4つのポイントのメソッドを全部呼ぶのは面倒です。
もちろん、この事象(ここでは4つのポイントの切替)をトリガするもの(センサー等)が1つなのであれば、どのようなやり方をしても大差ありません。が、実際には、例えば「あるキーを押しても同じことが起こるようにしたい」等のニーズが後から生まれてくるでしょう。であれば、ある事象については1つのメソッドをcallさえすれば発生するようにしておいた方が便利です。
そこで、4つのポイントのうちの1つを「親ポイント」、残りの3つを「子ポイント」と考えます。そして、親ポイントのスクリプトのメソッドの中に自分自身と子ポイントを切り替えるcallを書いてしまいます。こうすると外部(つまりはセンサー)からは親ポイントのメソッドを1つcallするだけですべてのポイントを一気に切り替えることができます。
[親ポイントスクリプト]
//すべてを正位切替するメソッド
BeginFunc MtdAllStraight
call this MtdStraight
call "{子ポイントの名前}" MtdStraight
//子ポイントの数だけこれを繰り返す
EndFunc
//すべてを反位切替するメソッド
BeginFunc MtdAllTurnout
call this MtdTurnout
call "{子ポイントの名前}" MtdTurnout
//子ポイントの数だけこれを繰り返す
EndFunc

[親/子ポイント共通スクリプト]
//正位切替メソッド
BeginFunc MtdStraight
SetPointBranch 0
EndFunc
//反位切替メソッド
BeginFunc MtdTurnout
SetPointBranch 1
EndFunc
親子関係となるポイントを配置し、それぞれに、たとえば親には"POINTn"、子には"POINTn-1","POINTn-2","POINTn-3"と名前をつけてください(nは任意の数字)。その上で上掲サンプルコードをポイントに組み込みます。この状態でセンサー等から call "POINTn" MtdAllStraight/Turnout としてやれば、親子計4つのポイントが一気に切り替わります。

この手法はポイントのみで終わるものではありません。もう1つサンプルを示しておくことにしましょう。
[信号スクリプト]
//連動ポイント設定
VarPoint ObjPartnerPoint
get ObjPartnerPoint "{連動するポイント名}"
//赤現示メソッド
BeginFunc MtdSignalR
SetSignal 1
call ObjPartnerPoint MtdTurnout // または MtdStraight
EndFunc
//緑現示メソッド
BeginFunc MtdSignalG
SetSignal 6
call ObjPartnerPoint MtdStraight // MtdTurnout
EndFunc
察しの良い方はお気づきかと思いますが、これは安全側線を再現するためのスクリプトです。ネットに配付するレイアウトにこの仕組みを仕込んでおけば、信号の制御さえおこなえばレイアウト作者が意図しない運転がなされた列車を本線ではない方向へと導くことで、事故を防止することが可能になります(当然、レイアウトをそのような構造に作っていれば、の話です)。

なお、連鎖メソッドをおこなう場合は「無限ループ」に注意してください。たとえば・・・
【!!以下は悪い例です!!】
[ポイント"POINT1"スクリプト]
BeginFunc BadStraight
SetPointBranch 0
call "POINT2" BadStraight
EndFunc
[ポイント"POINT2"スクリプト]
BeginFunc BadStraight
SetPointBranch 0
call "POINT1" BadStraight
EndFunc
これは最も単純化した無限ループの例です。POINT1/2、どちらのメソッドをcallしても、連鎖が止まらなくなります。PCが壊れたりすることはないと思いますが、ビュワーは異常終了/フリーズするかも知れません。連鎖メソッドを組む場合は、たとえば常に親になるオブジェクトの名前は1文字目を〜にする、等のルールを自分で定めて、無限連鎖を回避することをお奨めします。

注)本連載で示すVRM4スクリプトや物の考え方をあなたが採用した結果生じる全ての事象については、その責を負い兼ねます。私の書いたものを読むに際しては、常に「コイツは狂人で、でも一部は役に立つことも言っているかも知れない」という程度の心構えで臨んでください。
0

2005/10/27  22:31

投稿者:ghost
(誤)StdMtdStraight → (正)MtdStraight

VRMスクリプトにおいて、メソッドの名前(BeginFuncの後に続く文字列)自体に意味はありません。極端な話、a でも hehehe でもいいです。ただ、そのメソッドを実行する側(call や SetEvnet〜命令)とは必ず同じ名前でなければいけません。
オイラは必ずしも同じ機能のメソッドを同じ名前で書かないので、その点には注意してもらう必要があります。よろしく。

2005/10/27  20:36

投稿者:512
信号

VarPoint ObjPartnerPoint
get ObjPartnerPoint "POINT6"

BeginFunc MtdSignalR
SetSignal 1
call ObjPartnerPoint MtdStraight
EndFunc

BeginFunc MtdSignalG
SetSignal 6
call ObjPartnerPoint MtdTurnout
EndFunc

ポイント

BeginFunc StdMtdStraight
SetPointBranch 0
EndFunc

BeginFunc StdMtdTurnout
SetPointBranch 1
EndFunc

2005/10/27  19:38

投稿者:ghost
とりあえず、信号とポイントそれぞれに書いたスクリプトをここへ貼ってください。じゃないとわかんないので、あなたが何やってるのかが。

2005/10/27  18:57

投稿者:512
それでも同じエラーが出ますよ。

2005/10/27  17:59

投稿者:ghost
VRMがそう言うからにはメソッドMtdStraightがポイントに書かれていないのでは?
なお、このスクリプトだけ書いても何も起きませんよ。どこかから信号機のメソッドMtdSignalR/Gをcallしないと。念のため。

2005/10/27  16:24

投稿者:512
ポイントに連動する信号スクリプトを実行してみたら、
[MtdStraight] ERROR 未定義のメソッドを参照した
というエラーが出ましたが…

コメントを書く

この記事にはコメントを投稿できません




teacup.ブログ “AutoPage”
AutoPage最新お知らせ