Tidak sulit untuk membuat pergerakan mobil yang cukup baik (tetapi posting ini akan cukup panjang). Anda perlu "mensimulasikan" beberapa kekuatan dasar untuk membuat mobil bergerak secara fisik masuk akal.
(Semua sampel kode pseudocode.)
Percepatan
Pertama, Anda jelas membutuhkan akselerasi. Sesuatu yang sederhana seperti yang dilakukan oleh baris berikut:
acceleration_vector = forward_vector * acceleration_input * acceleration_factor
forward_vector
- Vektor menunjuk ke arah yang sama dengan mobil.
acceleration_input
- Input harus dalam interval [-1, 1].
acceleration_factor
- Nilai percepatan (piksel / detik ^ 2, atau apa pun unit Anda).
Pengemudian
Kemudi juga cukup sederhana. Pada prinsipnya, apa yang akan Anda lakukan adalah memutar vektor maju mobil agar mengarah ke beberapa arah lain.
steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)
Anda mungkin mengalami komplikasi di sini. Jika input Anda melalui keyboard, nilainya akan -1 atau 1 yang berarti mobil Anda akan berubah secara instan. Anda dapat memperbaiki ini menggunakan interpolasi linier yang sangat sederhana (lerping):
amount = time_since_last_frame * steer_lerp_factor
forward_vector = lerp(forward_vector, new_forward_vector, amount)
Jumlahnya harus tergantung pada waktu sehingga gerakan Anda tidak tergantung pada frame rate Anda. Jumlahnya harus antara [0, 1] dan semakin kecil, semakin halus transisi antara vektor lama dan baru.
(Pada titik ini Anda akan menemukan bahwa mobil akan menyetir bahkan jika itu masih berdiri. Untuk mencegahnya, kalikan steer_angle
dengan current_speed / max_speed
, di mana max_speed
konstanta ditentukan oleh Anda.)
Bergerak
Sekarang kita akan menerapkan akselerasi dan memindahkan sejumlah piksel berdasarkan kecepatan, akselerasi, dan kemudi. Kami juga ingin membatasi kecepatan mobil agar tidak berakhir dengan kecepatan tak terbatas.
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
Mobil Anda sekarang meluncur
Jika saya benar, mobil Anda sekarang akan tampak meluncur setiap kali Anda berputar seolah-olah itu di atas es. Ini karena tidak ada gesekan. Pada mobil sungguhan ada gesekan lateral yang tinggi (karena roda tidak bisa berputar ke samping: P).
Anda perlu mengurangi kecepatan lateral. Dengan tidak mengurangi sepenuhnya Anda juga dapat membuat mobil tampak melayang.
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
Karena kita berbicara tentang gesekan, Anda mungkin juga ingin memiliki kekuatan (gesekan) yang mengurangi kecepatan Anda sehingga ketika Anda berhenti berakselerasi, mobil Anda pada akhirnya akan berhenti.
backwards_friction = -velocity_vector * backwards_friction_factor
Kode Anda untuk memindahkan mobil sekarang akan terlihat seperti ini:
// 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
Catatan penutup
Saya menyebutkan bagaimana Anda harus menerapkan lerping ke kemudi; Saya pikir Anda mungkin perlu melakukan hal yang sama untuk akselerasi dan mungkin untuk sudut steer juga (Anda harus menyimpan nilai-nilai mereka dari frame sebelumnya dan lerp dari itu). Juga semua vektor relatif terhadap mobil (maju, kanan, atas) harus panjang 1.
Juga, gesekan sedikit lebih rumit daripada yang saya tunjukkan di sini. Anda harus selalu memastikan bahwa panjangnya tidak pernah lebih besar dari akselerasi yang diperlukan untuk membuat mobil berhenti (jika tidak gesekan akan membuat mobil bergerak ke arah yang berlawanan). Jadi, Anda harus memiliki sesuatu seperti:
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))