Saya mencari untuk membuat gerakan mobil yang realistis menggunakan vektor

12

Saya sudah goggle bagaimana melakukan ini dan menemukan ini http://www.helixsoft.nl/articles/circle/sincos.htm Saya sudah mencobanya tetapi sebagian besar fungsi yang ditampilkan tidak berfungsi, saya baru saja mendapatkan kesalahan karena mereka tidak ada. Saya telah melihat fungsi cos dan sin tetapi tidak mengerti bagaimana menggunakannya atau bagaimana membuat gerakan mobil bekerja dengan benar menggunakan vektor. Saya tidak punya kode karena saya tidak yakin apa yang harus saya lakukan maaf.

Bantuan apa pun dihargai.

EDIT:

Saya memiliki batasan bahwa saya harus menggunakan mesin TL untuk permainan saya, saya tidak diizinkan untuk menambahkan mesin fisika apa pun. Itu harus diprogram dalam c ++. Berikut adalah contoh dari apa yang saya dapatkan dari mencoba mengikuti apa yang dilakukan di tautan yang saya berikan.

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);
bobthemac
sumber
Lihat situs ini untuk mengetahui perilaku mengemudi: red3d.com/cwr/steer
MichaelHouse
Anda perlu mendefinisikan "pergerakan mobil realistis"
Maik Semder
1
Saya berasumsi sudut Anda berasal dari setir, mungkin. Panjangnya harus sebesar kecepatan Anda. Jadi potongan kode terakhir bisa menjadi sesuatu di baris: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, selain itu, tolong katakan apa masukan Anda dan bagaimana mobil harus bersikap. Saat ini, ia harus mengarah di pesawat tanah, tapi sekali lagi, ini sama sekali tidak umum. Di sana Anda baru saja membuat kami dari langkah integrasi Euler yang kasar ..
teodron

Jawaban:

23

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_angledengan current_speed / max_speed, di mana max_speedkonstanta 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))
Paul Manta
sumber
Wow, ini jawaban yang bagus!
ezolotko
0

Menilai dari pertanyaan Anda, saya akan menganggap Anda relatif baru untuk pemrograman (yang merupakan a-ok btw!). Saya akan menyarankan untuk menggunakan kerangka kerja yang ada karena simulasi mobil realistis adalah salah satu aspek paling sulit dari fisika untuk diperbaiki.

Anda tidak menyebutkan batasan 2D / 3D jadi saya akan melanjutkan dan menyarankan Anda mengunduh Havok SDK (gratis untuk penggunaan non-komersial) dan mendapatkan demo sederhana dan berjalan (mereka sebenarnya memiliki demo yang kehabisan kotak [dapatkan dikompilasi di sistem Anda, semua kode ada], Anda tidak perlu melakukan apa pun untuk membuatnya dikompilasi ... buka saja proyek dan tekan build).

Setelah Anda mengetahui beberapa aspek di balik layar dari fisika mobil (meskipun Anda tidak akan melihat implementasi sebenarnya dari fisika, yang tersembunyi, Anda akan dapat melihat antarmuka), saya yakin Anda akan berada dalam posisi yang lebih baik untuk melakukannya dengan benar ketika Anda memulai sendiri.

Saya juga mengajukan pertanyaan serupa belum lama ini. Tautan di sana dapat membantu juga. Dan inilah tautan lain .


Setelah melihat hasil edit Anda, tampaknya Anda mencari untuk hanya mengubah kecepatan mobil tergantung pada sudut yang dihitung (itu tidak realistis, jadi Anda harus mengubah pertanyaan asli untuk mencerminkan itu). Jika sudut adalah bagian dari pertanyaan (bahwa Anda tidak dapat mengubah) dan Anda harus menggunakan sudut untuk menghitung kecepatan baru, maka pergi dengan apa yang @teodron masukkan ke dalam komentar.

Cara lain adalah dengan menggunakan vektor saja. Ada beberapa pendekatan menggunakan vektor, saya akan menyajikannya.

Kecepatan adalah arah * besarnya (di mana besarnya adalah kecepatan dan arah adalah vektor yang dinormalisasi). Hitung kecepatan dan arah mobil saat ini. Ambil arah dan tambahkan vektor (sebut saja D') ke yang tegak lurus terhadapnya. Ini akan mengubah kecepatan mobil. Tidak ada sudut untuk dipusingkan (meskipun Anda dapat menggunakan sudut untuk menentukan panjang vektor tegak lurus yang bisa Anda ubah faktor [lihat di bawah])

Cara menghitungD' : Untuk menemukan vektor tegak lurus, ambil arah kecepatan aslinya, silangkan dengan vektor arah yang menuju ke layar tempat urutan Anda melintasi vektor dalam menentukan arah vektor tegak lurus tersebut. Kemudian gandakan faktor perpedicular ini dengan beberapa turn factor yang menentukan seberapa cepat mobil itu berputar.

Samaursa
sumber
Saya akan tetapi saya tidak diizinkan untuk menggunakan mesin fisika, permainan adalah 3D dan semua yang saya perlu ubah adalah vektor X dan Z Saya hanya perlu mencari tahu apa itu.
bobthemac
@ bobthemac: Apakah ini pertanyaan pekerjaan rumah? Jika ya, edit pertanyaan Anda untuk menunjukkan batasan yang Anda miliki dan mungkin memposting beberapa kode yang relevan sehingga kami memiliki sesuatu untuk dikembangkan. Btw, tautan terakhir mungkin adalah apa yang Anda cari dalam hal memahami fungsi.
Samaursa
Saya telah menambahkan informasi yang Anda minta dan melihat tautan yang disediakan tetapi masih belum memahaminya.
bobthemac
@bobthemac: Lihat hasil edit saya
Samaursa