レースゲームの参加者の位置をどのように決定しますか?


9

記録のために、私は現在、レーシングゲームをまったく実装していませんが、この問題が頭に浮かんだだけで、気になります。

では、どのレースの参加者が現在最初の参加者であるかを知るにはどうすればよいでしょうか?フィニッシュラインまでの距離で並べ替えるのは簡単なことではありません。これは、ほとんどのコースでは非常に不正確だからです。ルートを直線セグメントに分割するような方法を考えました。それぞれのセグメントには方向ベクトルがあります。次に、ゲームは、そのベクトルに自分の位置を投影し、どちらが先かをチェックすることによって、誰かが他の誰かを追い越したかどうかをチェックします。位置が変更された場合、ゲームはそれらを適切に増減します。しかし、それは少し複雑すぎるようです。

誰かが確立された方法を知っているか、いくつかを実装した経験がありますか?

回答:


12

Shawn Hargreavesが、MotoGPが特別なトラック相対位置システムをどのように使用したかを説明します。垂直y位置を無視して、x / zデカルト座標はトラック相対システムに変換されます。これは、レーシングゲーム(AIなど)の参加者の相対位置を含む計算に多くの利点をもたらしました。

一般的な単純化は、3Dを2Dに折りたたむことです。レンダリングと物理は真に3Dである場合でも、意思決定ロジックは3つの軸すべてを同等に扱う必要はありません。MotoGPトラックには丘が少ないため、AIはyコンポーネントを無視できました。

次に、x / zデカルト座標からトラック相対システムに切り替えました。位置は、次の2つの値で表されました。

int距離= 16.16固定小数点形式で保存された、トラックの周囲の距離

  • 0 =開始行
  • 0x8000 =中間点
  • 0x10000 =最初にループバック
  • 0x1C000 = 2周目の4分の3

フロートクロス=トラックを横切る距離0 =中心線上

  • -1 =レーシングサーフェスの左端
  • 1 =レーシングサーフェスの右端

これと、物理コードおよびレンダリングコードで使用されるデカルト座標を変換するために、レーシングサーフェスの形状を定義するセグメントのリストを保存しました。struct TrackSegment {Vector CenterPoint; float DistanceToLeftEdge; float DistanceToRightEdge; }

元々トラックが作成されたベジェ曲線をテッセレーションすることにより、トラックの周りに等間隔に配置されたこれらの構造を数百作成しました。これにより、必要な座標変換関数を記述するのに十分な情報が得られました。

トラック相対座標を使用すると、多くの便利な計算が簡単になります。

if (abs(cross) > 1)
    // You are off the track and should steer back toward the center line


if (this.distance > other.distance)
    // You are ahead of the other player (even though you may be
    // physically behind in 3D space if you have lapped them)


short difference = (short)(this.distance - other.distance);

if (abs(difference) < threshold)
    // These two bikes are physically close together,
    // so we should run obstacle avoidance checks

固定小数点データ形式のため、距離カウンターを32ビットから16ビットにキャストすることは、ラップ数を破棄する簡単な方法でした。そのため、2つのバイクが異なるラップにある場合、どちらの計算が適切かを知りたいのではなく、どの計算を選択するかを選択できました。物理的な空間で接近していた。2の賛辞の魔法のおかげで、違いを符号付き16ビットとして扱うと、どちらの自転車が前にあるかに関係なく、最短距離が得られます(ループレーストラックなどのモジュロ演算システムでは、2つの可能な距離があることに注意してください。トラックのいずれかの方向)。これは、2台のバイクがスタートラインの反対側にある場合でも機能します。この状況では、他のほとんどの座標系でエラーが発生しやすい特殊なケースのロジックが必要になります。

この仮想ゲームプレイ領域を平らにしてまっすぐにすることで、「私はレーシングラインにいますか?」または「私はこの他の自転車の後ろに速く来ています。左または右に追い越すための余地はありますか?」これは、完全な3Dワールド空間に実装するのが難しいでしょう。左側を通過することを決定したら、結果のトラック相対座標をワールド空間に変換します。その時点でトラックの曲率が考慮され、選択した目標を達成するためにどのように操縦すべきかを示します。


非常に素晴らしい!どうもありがとう。また、適切なタグを追加していただきありがとうございます。評判がよくなかったのでそうすることができませんでした。乾杯。
MarcMüller、

3

道路は一般的にスプラインを使用して構築されているため、道路のすべてのエッジに対応するスプライン位置があり、これを使用して、現在の値を(およそ、またはさらに細かく分割すると細かく)決定できると思います各車のスプライン位置、つまり誰がリードしています。つまり、多かれ少なかれ、スプラインを使用して、あなたが提案する方法です。


3

あなたは多かれ少なかれあなた自身の質問に答えたと思います。トラックをセグメントに分割し、各自動車がどのセグメントにあるかを追跡し、自動車を適切なセグメントの中央を通る線に投影します(数学的には単純なドット積なので、まったく複雑ではありません)。各車に「距離」を与えるのは非常に簡単で、位置を並べ替えることができます。

セグメントはあなたにいくつかの追加の利点を与えます-あなたは車がコーナーをカットしない(または一般に近道をとらない)、後退する、または他のチートをしないようにすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.