ベクトルを使用して現実的な車の動きを作成しようとしています


12

私はこれを行う方法をゴーグルし、これを見つけましたhttp://www.helixsoft.nl/articles/circle/sincos.htm私はそれをやってみましたが、示された機能のほとんどが機能しませんでした存在しなかったからです cos関数とsin関数を見てきましたが、それらを使用する方法、またはベクトルを使用して車の動きを正しく機能させる方法を理解していません。申し訳ありませんが、コードがありません。

どんな助けも大歓迎です。

編集:

ゲームにはTLエンジンを使用しなければならないという制限があり、物理エンジンを追加することはできません。C ++でプログラムする必要があります。ここに、私が提供したリンクで行われたことを追跡しようとすることから得たもののサンプルがあります。

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);

このサイトでステアリング動作を確認してください:red3d.com/cwr/steer
MichaelHouse

あなたは、「現実的な車の動き」を定義する必要があります
はMaik Semder

1
おそらくあなたの角度はステアリングホイールから来ると思います。長さは速度の大きさでなければなりません。最後のコードスニペットがのライン上のものになることができるように:carVecloityX = length* cos(angle);carVelocityZ = length *sin(angle);、それとは別に、あなたの入力が何であるかを伝え、車がどのように振る舞うべきかしてください。現時点では、グラウンドプレーンで操縦する必要がありますが、これもまったく一般的ではありません。そこで、粗いオイラー統合ステップを作成しました
。–テオドロン

回答:


23

かなり良い車の動きを作成することはそれほど難しくありません(ただし、この記事はかなり長くなります)。車を物理的にもっともらしい動きにするには、いくつかの基本的な力を「シミュレート」する必要があります。

(すべてのコードサンプルは擬似コードです。)

加速度

まず、明らかに加速が必要です。次の行のように単純なもの:

acceleration_vector = forward_vector * acceleration_input * acceleration_factor
  • forward_vector —車と同じ方向を指すベクトル。
  • acceleration_input —入力は区間[-1、1]内になければなりません。
  • acceleration_factor —加速度の値(ピクセル/秒^ 2、またはユニットは何でも)。

操舵

ステアリングも非常に簡単です。原則として、車の前方ベクトルを回転させて、他の方向を指すようにします。

steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)

ただし、ここで問題が発生する場合があります。入力がキーボードを介して行われている場合、その値は-1または1になります。これは、車が瞬時に回転することを意味します。これは、非常に単純な線形補間(lerping)を使用して修正できます。

 amount = time_since_last_frame * steer_lerp_factor
 forward_vector = lerp(forward_vector, new_forward_vector, amount)

その量は、動きがフレームレートに依存しないように時間に依存する必要があります。量は[0、1]の間である必要があり、小さいほど、古いベクトルと新しいベクトルの間の遷移がよりスムーズになります。

(この時点では、車はそれはまだ立っていても操縦することがあります。それを防ぐために、乗算steer_angleによってcurrent_speed / max_speedどこ、max_speedあなたによって定義された定数です。)

引越し

ここで、加速度を適用し、車の速度、加速度、およびステアリングに基づいて特定のピクセル数だけ車を動かします。また、車の速度を制限して、無限に速く移動しないようにします。

current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

あなたの車は今スライドしています

私が正しい場合、あなたの車は、まるで氷の上にいるかのように曲がっているときは常にスライドしているように見えます。これは摩擦がないためです。実際の車では、横方向の摩擦が大きくなります(車輪が横に回転できないため:P)。

横速度を下げる必要があります。完全に減らさないことで、車がドリフトしているように見せることもできます。

 lateral_velocity = right_vector * dot(velocity_vector, right_vector)
 lateral_friction = -lateral_velocity * lateral_friction_factor 

摩擦について話しているので、加速を停止すると最終的に車が停止するように、速度を低下させる(摩擦の)力も必要になる場合があります。

 backwards_friction = -velocity_vector * backwards_friction_factor

車を動かすためのコードは次のようになります。

// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame


current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{ 
    velocity_vector += acceleration_vector * time_since_last_frame
}

position_vector += velocity_vector * time_since_last_frame

最後に

ステアリングにlerpingを適用する方法について説明しました。私はあなたが加速のためにそしておそらく舵角のために同じことをする必要があるかもしれないと思います(あなたは前のフレームからの値を保存し、それからlerpする必要があります)。また、車に関連するすべてのベクトル(前方、右側、上方)の長さは1でなければなりません。

また、ここで示したよりも摩擦は少し複雑です。車の停止に必要な加速度よりも長くならないように常に確認する必要があります(そうしないと、摩擦により車が反対方向に移動します)。したがって、次のようなものが必要です。

dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))

うわー、これは素晴らしい答えです!
エゾロトコ

0

あなたの質問から判断すると、私はあなたがプログラミングに比較的慣れていないことを前提としています(これは大丈夫です!)。現実的な自動車シミュレーションは物理学の最も難しい側面の1つであるため、既存のフレームワークを使用することをお勧めします。

2D / 3Dの制限については言及しなかったので、先に進んでHavok SDKをダウンロードし(非営利目的では無料)、簡単なデモを実行することをお勧めします(実際に箱から出してすぐに実行できるデモがある[getシステムでコンパイルされ、すべてのコードがそこにあります]、コンパイルするために何もする必要はありません...プロジェクトを開いてビルドを押してください)。

車の物理学の背後にあるいくつかのアイデアを理解すると(物理学の実際の実装は表示されませんが、それは隠されていますが、インターフェイスが表示されます)、より良い位置にいると思いますあなたが自分で始めたときにそれを正しくするために。

私も同様の質問を少し前に聞いた。そこにあるリンクも役立ちます。そして、ここで別のリンクです


編集を確認した後、計算された角度に応じて車の速度を変更するだけです(現実的ではありません。そのため、元の質問を変更する必要があります)。角度が(変更できない)質問の一部であり、角度を使用して新しい速度を計算する必要がある場合は、@ teodronがコメントに入力したものを使用します。

別の方法は、ベクトルのみを使用することです。ベクトルを使用した複数のアプローチがありますが、その1つを紹介します。

速度は方向*大きさです(大きさは速度で、方向は正規化されたベクトルです)。車の現在の速度と方向を計算します。方向を取得し、それにD'垂直なベクトル(それを呼び出しましょう)を追加します。これにより、車の速度が変わります。角度をいじる必要ありません(ただし、角度を使用して、垂直ベクトルの長さを決定することができます。これは、ファクター回転させることができます[以下を参照])

計算方法 D':垂直ベクトルを見つけるには、元の速度の方向を取得し、画面に向かう方向ベクトルと交差させます。ここで、ベクトルを交差する順序が垂直ベクトルの方向を決定します。次に、この垂直係数に、自動車がどれだけ速く回転するかを決定する何らかの回転係数を掛けます。


物理エンジンを使用することはできませんが、ゲームは3Dであり、変更する必要があるのは、XとZのベクトルだけです。
bobthemac

@bobthemac:これは宿題の質問ですか?「はい」の場合、質問を編集して制限を指摘し、関連するコードを投稿して、何かを構築してください。ところで、最後のリンクは、機能を理解する上であなたが探しているものかもしれません。
サマーサ

リクエストした情報を追加し、提供されたリンクを確認しましたが、まだ理解できません。
bobthemac

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