2007/3/10

気まぐれで“魚雷でイヤッッホォォォオオォオウ!”の当たり判定について書いてみる  VRMスクリプト禅問答
もう誰も覚えてないかも知れませんが、いつか書こうと思って忘れていたコレの当たり判定は如何にして実現されていたか、について。

クリックすると元のサイズで表示します

あのレイアウト(ゲーム?)は、単純化すると上図のような交差線路があって、“的経路”を走行する列車に“魚雷経路”を走行する列車をぶつけると得点が入る、と、まぁ、そういうモノだったワケです。

皆様ご存知の通り、VRM4では編成の連結を除けば、物体が何かに衝突するなんて事象はあり得ない(すべて通り抜ける)ワケで、んじゃ、どうやって敵戦艦(ゲーム中は電気機関車)と魚雷(同、タンクコンテナを積んだ貨車)の衝突を検知していたのか、というお話。

クリックすると元のサイズで表示します

まず、上図のように3つのセンサーを配置します。センサー@/Aは的経路に、センサーBは魚雷経路に載っています。で、図中では緑色の塗りつぶしで表現していますが、ビュワーを起動した時点で、センサー@/Aには常にセンサーイベント(編成を検知して何かをする)が設定されていますが、実はセンサーBにはイベントが設定されていません。これがミソです。

クリックすると元のサイズで表示します

ここに、右側から的経路を編成が走行してきます。センサーBにはイベントが未設定なので、仮にこの時点で魚雷経路を何か=魚雷が通過しても何も起きません。

クリックすると元のサイズで表示します

さて、的経路の編成がセンサー@を踏みました。センサー@のセンサーイベントでトリガされるメソッドには、
call センサーB LockOn
と書いてあります。センサーBのメソッドLockOnを実行しろ、の意味ですね。で、そのセンサーBのLockOnは、
Var EventID

BeginFunc LockOn
  SetEventSensor Hit EventID
EndFunc
みたいになってます。つまり、センサー@を編成が踏んだら、ここで初めてセンサーBにイベントが設定されるワケです。

クリックすると元のサイズで表示します

ここへ魚雷列車が突っ込んで来ますと、今度はセンサーBがこれを検知して、メソッドHitを実行します。言うまでもなく、メソッドHitには得点を追加したり、魚雷が命中した的列車が“沈没”するようにポイントを切り替えたりする処理が書いてあります。

あ、この時点でゲーム視点の地下に隠している編成の警笛が吹鳴され「イヤッッホォォォオオォオウ!」とかいいますね。アレ、ボクの声なんですけど(他の声も全部そうですが)。

クリックすると元のサイズで表示します

さて。もし魚雷がやって来ず、平穏無事(?)に的列車がセンサーAに辿り着いたらどうなるか。もう想像が付くかと思いますが、センサーBの以下のメソッドがcallされるワケです。
BeginFunc LockOff
  KillEvent EventID
EndFunc
これで、センサーBはイベントが解除され、元通り魚雷が通っても何もしないセンサーに戻りました。なので・・・

クリックすると元のサイズで表示します

的列車がセンサー@以前にいたとき同様に、魚雷列車はこの地点を素通りする、という仕組み。

一見、他に何の役にも立たないように見える手法ですが、要するにこれは「ある列車が特定区間内にいるときだけ発動するセンサー」の作り方です。なので、うまいこと組み込むと、あんなコトやこんなコトも出来たりするワケですが、それは読者諸兄のお楽しみにとっておきましょう。

*     *     *

ところで、的経路と魚雷経路のレールの高さにほとんど差がないので、うまいことぶつけると的列車と魚雷列車は連結してしまいます。これがシークレットボーナスで、確か30,000点です。事実上、ここでゲームオーバーを宣告されたに近いですが。

このシークレットボーナスを検知するために、的列車、魚雷列車の双方にSetEventCouple命令で連結イベントが設定されています。VRM4の連結判定は、異なるレールに載った編成間でも発動されるところを見ると、単純に編成オブジェクト(の連結器位置)間の相対距離が一定値を割り込むかどうか、みたいです。

連結が事前準備無しに発動するってことは、すべての編成オブジェクトは、自分の位置を走行に応じて更新する都度、他の編成オブジェクトとの連結は起こるか否かを計算しているはずです。停車中の編成に別の編成をぶつけた場合、一意に吸収されることから考えると、衝突判定をおこなうのは走行している編成のみなのでしょう。一見、同時に動いているように見える複数の編成ですが、実際には1つずつ移動が処理されていて、これを一気に描画するので同時に動いているように見えるに過ぎません。

従って、双方の編成が走行中であった場合、連結する側(連結後に吸収される編成)になるか、連結される側(連結後に残る編成)になるかは、自分が座標を更新して連結判定をおこなった時点で、相手が連結範囲にいたかどうか、によって決まるはずです。これは、理屈の上では予測計算可能ですが、実際にはそこに至るまでの処理の複雑さと、VRM4の動作が必ずしも時間に対して正確ではない(基準クロックに同期する処理をおこなっていない)ことから、事実上ランダムな事象として認知されることになります。また、編成速度が十分に高速であったり、フレームレートが低かったりすれば、一見、連結可能な経路上にいるように見える編成同士が連結せずにすり抜ける、という現象も起きます。

これが、すべての編成にシークレットボーナス用の連結イベントを仕込んだ理由であり、同時に、天狗亭氏がしばらくゴニョゴニョ書いておられた疑問のほんの一部(走行速度とどちらが連結時に相手を吸収するか、の関係・・・はないはず)に対する回答です。残りの部分は知りません。

っつーか、いろんなコトを一度に調べようとしていて、切り分けとして不適切(実質がどうであれ、読み手にとっては理解し辛いし説得力を欠く状態)だと思いますよ。>天狗亭殿
0

コメントを書く

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




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