Bagaimana cara menghitung respons tabrakan antara bola dan pesawat?

9

Saya mencoba membuat game 3D sederhana dan perlu membatasi pemain dalam batas-batas dunia game. Ketika pemain menyentuh sisi dunia saya ingin kapal pemain sedikit memantul.

Akibatnya saya mencoba untuk menjebak pemain di dalam kotak, dan menghentikan mereka lolos dari sisi ...

Saya telah berhasil mendefinisikan batas-batas gameworld sebagai kumpulan pesawat, dengan normals dan jarak dari asalnya. Pemain memiliki bola pembatas bola dan dari mengikuti situs web ini http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.php Saya telah berhasil mendeteksi tabrakan.

Saya sekarang tidak bisa mengetahui apa yang harus dilakukan ketika tabrakan terdeteksi. Yang terbaik yang bisa saya kelola adalah pemain terjebak di pesawat, melewatinya, atau memantul berulang kali dengan kecepatan sangat cepat.

Akal sehat mengatakan kepada saya bahwa saya perlu menghitung sudut pantulan dari pesawat, menggunakan normal dan menerapkannya pada kecepatan pemain, namun saya pikir saya harus terlebih dahulu melihat apakah pemain telah melalui pesawat yang sedikit saya tidak bisa bekerja.

Piku
sumber

Jawaban:

4

Anda harus menerapkan dorongan pada objek Anda, yang merupakan perubahan langsung dalam kecepatannya. Di dunia nyata, kekuatan yang kuat akan diterapkan pada objek selama waktu yang sangat singkat, membalikkan akselerasinya dan menyebabkan kecepatannya berubah. Namun, karena kita bekerja di dunia yang terpisah, kita harus sedikit menipu untuk mensimulasikan perubahan arah yang tiba-tiba ini. Untuk bola dan pesawat, itu cukup mudah. Respon tabrakan paling dasar adalah untuk mencerminkan kecepatan bola di sekitar normal pesawat, dan hasilnya adalah kecepatan baru bola. Kode semu akan terlihat seperti ini:

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected

Dari sana, Anda dapat menambahkan redaman (kalikan dengan beberapa koefisien, seperti 0,9) untuk memperhitungkan energi yang hilang karena panas atau gesekan. Jika Anda ingin melibatkan kecepatan sudut (mungkin bola Anda berputar), maka persamaannya menjadi sedikit lebih rumit.

Untuk info lebih lanjut, saya akan merujuk Anda ke artikel Chris Hecker tentang Rigid Body Dynamics . Jika Anda belum pernah mendengar tentang Chris Hecker sebelumnya, ia terkenal karena fisika permainan serta karyanya tentang generasi karakter prosedural dan animasi di Spore.

kevintodisco
sumber
4
Ini pada dasarnya adalah cara yang tepat untuk pergi, namun menghitung waktu dampak (TOI) dapat membuat segalanya lebih akurat karena framerate berfluktuasi atau turun. Mengetahui, berdasarkan kecepatan saat ini, berapa lama dampak yang terjadi dapat membantu Anda menghitung waktu dampak, dan menggunakannya Anda dapat memindahkan bola kembali ke posisinya pada saat tumbukan dan menyesuaikan kecepatan dari sana. Setelah menyesuaikan posisi dan kecepatan dari titik tumbukan, pada saat tumbukan, Anda kemudian bergerak di sepanjang kecepatan baru dengan jumlah waktu yang Anda kurangi untuk sampai ke TOI.
Nic Foster
OK ini sepertinya berhasil, tapi agak ... aneh. Saya pikir saya mungkin melakukan ini pada titik yang salah dalam kode saya. Haruskah saya mengulangi semua benda saya dan menguji apakah mereka akan bertabrakan sebelum saya memindahkan mereka (berdasarkan di mana mereka akan menjadi bingkai berikutnya) atau memindahkan mereka dan kemudian menguji tabrakan setelah itu?
Piku
@Piku, tidak, jangan mendeteksi apakah mereka akan bertabrakan. Jika sebuah tabrakan terjadi, ingatlah ada kemungkinan yang sangat baik bahwa kedua objek tersebut sekarang tumpang tindih jauh di luar tempat tabrakan yang sebenarnya akan terjadi. Anda pada dasarnya perlu mencari tahu di mana tabrakan terjadi seolah-olah Anda memiliki framerate tak terbatas (yang tidak Anda miliki) dan memindahkan objek kembali ke posisi di mana tabrakan awalnya terjadi. Jika Anda tidak memisahkan objek seperti ini, Anda akan terus bereaksi terhadap benturan yang sama dan objek tersebut akan macet.
Jonathan Dickinson
@Piku dan untuk melakukan itu kami mencari tahu waktu di masa lalu di mana tabrakan terjadi (disebut TOI / waktu dampak). Setelah kita memiliki itu kita dapat menggunakan kecepatan objek untuk memindahkannya kembali ( distance = speed * time, biasanya dengan jarak ekstra kecil untuk menghindari kesalahan) dan kemudian memperbarui kecepatannya ke apa hasil tabrakan.
Jonathan Dickinson
@Piku juga kita tidak tahu di mana kita akan berada di frame berikutnya (saya belum pernah melihat itu dilakukan secara pribadi), tetapi, secara umum, kita melakukan deteksi dan respons tabrakan: SETELAH kita menghitung posisi baru untuk frame INI, tapi SEBELUM kami menerapkan posisi baru untuk bingkai INI.
Jonathan Dickinson
1

F = ma, atau a = F / m. Hitung titik tumbukan antara bola dan bidang. Ini biasanya Sphere center - radius * normal. Jika Anda ingin lebih akurat, hitung sejauh mana bola telah menembus pesawat, dan sesuaikan perhitungan Anda. Ini sebagian besar tentu saja opsional, kecuali jika Anda ingin fisika benar-benar akurat. Sekarang hitung kecepatan relatif sepanjang normal. Untuk bidang statis ini adalah: Vball Dot N. Lalu Multiply VballDotN dengan -1, dan kalikan dengan massa. Dalam fisika pada tahap ini Anda juga akan mengalikannya dengan koefisien restitusi (faktor bouncing). Lipat gandakan skalar ini dengan N dan Anda punya kekuatan.

Saat menyesuaikan Vball, bagilah gaya dengan massa lagi dan Anda memiliki akselerasi akhir, jadi tambahkan saja ini pada kecepatan dan Anda memiliki kecepatan tabrakan pos akhir.

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());

Metode ini akurat untuk formula respons tabrakan. Jika Anda ingin lebih akurat, Anda harus mempertimbangkan gesekan, yang akan menyebabkan bola berputar, tetapi saya tidak tahu apakah Anda menginginkannya dalam permainan Anda. Jika Anda melakukannya, ini adalah bagaimana Anda menghitung gaya tangensial:

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));

Pastikan untuk menghitung Ft sebelum menerapkan efek linear apa pun, atau friksi tidak akan akurat.

Ian Young
sumber
Tidakkah seharusnya baris 3 menjadi vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;:?
Shital Shah
Memang ya, saya melewatkan bagian itu. Terima kasih telah menunjukkannya.
Ian Young
0

Saya menyarankan Anda menghitung jarak dari pesawat terlebih dahulu; dan kemudian ketika jarak <= ke jari-jari melakukan reaksi tabrakan.

Anda kemudian dapat mengubah ini untuk menghitung jarak dan jika jaraknya kurang dari jari-jari (yang berarti objek tumpang tindih) menggeser posisi bola dan kemudian melakukan reaksi tabrakan.

Langit merah
sumber