かなり良い車の動きを作成することはそれほど難しくありません(ただし、この記事はかなり長くなります)。車を物理的にもっともらしい動きにするには、いくつかの基本的な力を「シミュレート」する必要があります。
(すべてのコードサンプルは擬似コードです。)
加速度
まず、明らかに加速が必要です。次の行のように単純なもの:
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))