Advertisement
  1. Game Development
  2. Programming

Cara Membuat Mesin Fisika 2D Kustom: Friction, Scene, dan Jump Table

Scroll to top
Read Time: 11 min
This post is part of a series called How to Create a Custom Physics Engine.
How to Create a Custom 2D Physics Engine: The Core Engine
How to Create a Custom 2D Physics Engine: Oriented Rigid Bodies

Indonesian (Bahasa Indonesia) translation by Zadip (you can also view the original English article)

Dalam dua tutorial pertama dalam seri ini, saya membahas topik Impulse Resolution dan Core Architecture. Sekarang saatnya untuk menambahkan beberapa sentuhan akhir ke mesin fisika 2D impuls berbasis kita.

Topik yang akan kita lihat di artikel ini adalah:

  • Friction
  • Scene
  • Collision Jump Table

Saya sangat merekomendasikan membaca dua artikel sebelumnya dalam seri sebelum mencoba untuk mengatasi yang satu ini. Beberapa informasi kunci dalam artikel sebelumnya dibuat di dalam artikel ini.

Catatan: Meskipun tutorial ini ditulis menggunakan C++, Anda harus dapat menggunakan teknik dan konsep yang sama di hampir semua lingkungan pengembangan game.


Video Demo

Berikut adalah demo singkat tentang apa yang kita kerjakan di bagian ini:


Friction

Friction adalah bagian dari resolusi tabrakan. Gesekan selalu menerapkan gaya pada objek dalam arah yang berlawanan dengan gerakan di mana mereka melakukan perjalanan.

Dalam kehidupan nyata, gesekan adalah interaksi yang sangat kompleks antara zat-zat yang berbeda, dan untuk memodelkannya, asumsi dan perkiraan yang luas dibuat. Asumsi-asumsi ini tersirat dalam matematika, dan biasanya sesuatu seperti "gesekan dapat didekati oleh satu vektor" - serupa dengan bagaimana dinamika tubuh kaku mensimulasikan interaksi kehidupan nyata dengan mengasumsikan tubuh dengan kepadatan seragam yang tidak dapat merusak.

Lihatlah demo video dari artikel pertama dalam seri ini:

Interaksi antara tubuh cukup menarik, dan memantul selama tabrakan terasa realistis. Namun, setelah objek mendarat di platform yang solid, mereka hanya semacam menekan dan hanyut dari tepi layar. Ini karena kurangnya simulasi friction.

Impuls, lagi?

Seperti yang Anda ingat dari artikel pertama dalam seri ini, nilai tertentu, j, mewakili besarnya dorongan yang diperlukan untuk memisahkan dua objek penetrasi selama tabrakan. Besaran ini dapat disebut sebagai jnormal atau jN karena digunakan untuk memodifikasi kecepatan sepanjang tabrakan normal.

Memasukkan respon gesekan melibatkan perhitungan besaran lain, yang disebut sebagai jtangent atau jT. Friction akan dimodelkan sebagai impuls. Besaran ini akan mengubah kecepatan suatu objek sepanjang vektor tangen negatif dari tabrakan, atau dengan kata lain sepanjang vektor gesekan. Dalam dua dimensi, pemecahan untuk vektor gesekan ini adalah masalah yang dapat dipecahkan, tetapi dalam 3D masalahnya menjadi jauh lebih rumit.

Gesekan cukup sederhana, dan kita dapat menggunakan persamaan sebelumnya untuk j, kecuali kita akan mengganti semua contoh n normal dengan vektor tangen t.

\[ Equation 1:\\
j = \frac{-(1 + e)(V^{B}-V^{A})\cdot n)}
{\frac{1}{mass^A} + \frac{1}{mass^B}}\]

Mengganti n dengan t:

\[ Equation 2:\\
j = \frac{-(1 + e)((V^{B}-V^{A})\cdot t)}
{\frac{1}{mass^A} + \frac{1}{mass^B}}\]

Meskipun hanya satu contoh n yang diganti dengan t dalam persamaan ini, setelah rotasi diperkenalkan beberapa contoh lagi harus diganti selain yang tunggal dalam pembilang Persamaan 2.

Sekarang masalah bagaimana menghitung t muncul. Vektor tangen adalah vektor tegak lurus dengan tabrakan normal yang menghadap lebih ke arah normal. Ini mungkin terdengar membingungkan - jangan khawatir, saya memiliki diagram!

Di bawah ini Anda dapat melihat vektor tangen tegak lurus dengan normal. Vektor tangen dapat menunjuk ke kiri atau kanan. Ke kiri akan "lebih jauh" dari kecepatan relatif. Namun, itu didefinisikan sebagai tegak lurus terhadap normal yang menunjuk "lebih ke arah" kecepatan relatif.

Vectors of various types within the timeframe of a collision of rigid bodies.Vectors of various types within the timeframe of a collision of rigid bodies.Vectors of various types within the timeframe of a collision of rigid bodies.
Vektor dari berbagai tipe dalam jangka waktu tabrakan benda-benda kaku.

Sebagaimana dinyatakan sebelumnya, gesekan akan menjadi vektor yang berhadapan dengan vektor singgung. Ini berarti bahwa arah di mana untuk menerapkan gesekan dapat langsung dihitung, karena vektor normal ditemukan selama deteksi tabrakan.

Mengetahui hal ini, vektor singgung adalah (di mana n adalah tabrakan normal):

\[ V^R = V^{B}-V^{A} \\
t = V^R - (V^R \cdot n) * n \]

Semua yang tersisa untuk memecahkan jt, besarnya gesekan, adalah menghitung nilai secara langsung menggunakan persamaan di atas. Ada beberapa bagian yang sangat rumit setelah nilai ini dihitung yang akan segera dibahas, jadi ini bukan hal terakhir yang diperlukan dalam resolver tabrakan kita:

Kode di atas mengikuti Persamaan 2 secara langsung. Sekali lagi, penting untuk menyadari bahwa vektor gesekan menunjuk pada arah yang berlawanan dari vektor tangen kita, dan dengan demikian kita harus menerapkan tanda negatif ketika kita menikung kecepatan relatif sepanjang garis singgung untuk menyelesaikan kecepatan relatif sepanjang vektor singgung. Tanda negatif ini membalik kecepatan singgung dan tiba-tiba menunjuk ke arah di mana gesekan harus didekati sebagai.

Hukum Coulomb's

Hukum Coulomb adalah bagian dari simulasi friksi yang sebagian besar programmer bermasalah. Saya sendiri harus sedikit belajar untuk mencari cara pemodelan yang benar. Triknya adalah hukum Coulomb adalah ketidaksetaraan.

Coulomb friction menyatakan:

\[ Equation 3: \\
F_f <= \mu F_n \]

Dengan kata lain, gaya friction selalu kurang dari atau sama dengan gaya normal dikalikan dengan beberapa μ konstan (yang nilainya tergantung pada bahan dari objek).

Gaya normal hanyalah kekuatan j besar kita dikalikan dengan tumbukan yang normal. Jadi jika jt kita yang dipecahkan (mewakili kekuatan gesekan) kurang dari μ kali gaya normal, maka kita dapat menggunakan jt magnitude sebagai friksi. Jika tidak, maka kita harus menggunakan waktu kekuatan normal µ gantinya. Ini "lain" kasus adalah bentuk menjepit friksi kami di bawah beberapa nilai maksimum, maks menjadi kali kekuatan normal μ.

Inti dari hukum Coulomb adalah untuk melakukan prosedur penjepitan ini. Penjepitan ini ternyata menjadi bagian yang paling sulit dari simulasi friksi untuk resolusi berbasis impuls untuk menemukan dokumentasi di mana saja - sampai sekarang, setidaknya! Kebanyakan kertas putih yang dapat saya temukan pada subjek, baik melewatkan gesekan sepenuhnya, atau berhenti pendek dan menerapkan prosedur penjepit yang tidak tepat (atau tidak ada). Semoga sekarang Anda memiliki penghargaan untuk memahami bahwa mendapatkan bagian ini dengan benar adalah penting.

Mari kita hentikan penjepitan semua sekaligus sebelum menjelaskan apa pun. Blok kode berikut ini adalah contoh kode sebelumnya dengan prosedur penjepitan selesai dan aplikasi impuls gesekan secara bersama-sama:

Saya memutuskan untuk menggunakan rumus ini untuk memecahkan koefisien gesekan antara dua tubuh, diberi koefisien untuk setiap tubuh:

\[ Equation 4: \\
Friction = \sqrt[]{Friction^2_A + Friction^2_B} \]

Saya benar-benar melihat orang lain melakukan ini dalam mesin fisika mereka sendiri, dan saya menyukai hasilnya. Rata-rata dari dua nilai akan bekerja dengan baik untuk menyingkirkan penggunaan akar kuadrat. Sungguh, segala bentuk pemilihan koefisien friksi akan berhasil; ini hanya apa yang saya sukai. Pilihan lain adalah menggunakan tabel pencarian di mana jenis setiap badan digunakan sebagai indeks ke dalam tabel 2D.

Adalah penting bahwa nilai absolut dari jt digunakan dalam perbandingan, karena perbandingan secara teoritis menjepit besaran mentah di bawah beberapa ambang batas. Karena j selalu positif, ia harus dibalik untuk mewakili vektor gesekan yang tepat, dalam kasus gesekan dinamis digunakan.

Friction Statis dan Dinamis

Dalam potongan kode terakhir, gesekan statis dan dinamis diperkenalkan tanpa penjelasan! Saya akan mendedikasikan seluruh bagian ini untuk menjelaskan perbedaan antara dan kebutuhan kedua jenis nilai ini.

Sesuatu yang menarik terjadi dengan friksi: ia membutuhkan "energi aktivasi" agar benda-benda mulai bergerak ketika beristirahat total. Ketika dua objek saling bergantungan dalam kehidupan nyata, dibutuhkan cukup banyak energi untuk mendorong satu dan membuatnya bergerak. Namun begitu Anda mendapatkan sesuatu yang meluncur, seringkali lebih mudah untuk tetap meluncur dari saat itu.

Ini karena cara kerja gesekan pada tingkat mikroskopis. Gambar lain membantu di sini:

Microscopic view of what causes energy of activation due to friction.Microscopic view of what causes energy of activation due to friction.Microscopic view of what causes energy of activation due to friction.
Pandangan mikroskopis tentang apa yang menyebabkan energi aktivasi karena friction.

Seperti yang Anda lihat, deformitas kecil antara permukaan benar-benar penyebab utama yang menciptakan friction di tempat pertama. Ketika satu objek beristirahat pada yang lain, deformitas mikroskopis beristirahat di antara objek, saling mengunci. Ini perlu dipatahkan atau dipisahkan agar benda-benda saling bergesekan.

Kita membutuhkan cara untuk memodelkan ini di dalam mesin. Solusi sederhana adalah menyediakan setiap jenis material dengan dua nilai gesekan: satu untuk statis dan satu untuk dinamik.

Gesekan statis digunakan untuk menjepit besarnya jt kita. Jika besarnya jt yang terpecahkan cukup rendah (di bawah ambang kita), maka kita dapat mengasumsikan objek sedang beristirahat, atau hampir sebagai istirahat dan menggunakan seluruh jt sebagai dorongan.

Pada flipside, jika jt terpecahkan kita berada di atas ambang batas, dapat diasumsikan bahwa objek tersebut telah melanggar "energi aktivasi", dan dalam situasi seperti itu, impuls gesekan lebih rendah digunakan, yang diwakili oleh koefisien gesekan yang lebih kecil. dan perhitungan impuls yang sedikit berbeda.


Scene

Dengan asumsi Anda tidak melewatkan bagian apapun dari bagian Friction, selesai dengan baik! Anda telah menyelesaikan bagian tersulit dari seluruh seri ini (menurut saya).

Kelas Scene bertindak sebagai wadah untuk segala sesuatu yang melibatkan skenario simulasi fisika. Ini panggilan dan menggunakan hasil dari setiap fase yang luas, berisi semua badan kaku, menjalankan pemeriksaan tabrakan dan resolusi panggilan. Ini juga mengintegrasikan semua objek hidup. Adegan juga berinteraksi dengan pengguna (seperti dalam programmer menggunakan mesin fisika).

Berikut ini contoh tampilan struktur adegan:

Tidak ada sesuatu yang sangat kompleks tentang kelas Scene. Idenya adalah untuk memungkinkan pengguna untuk menambah dan menghapus badan kaku dengan mudah. BodyDef adalah struktur yang menyimpan semua informasi tentang tubuh yang kaku, dan dapat digunakan untuk memungkinkan pengguna menyisipkan nilai sebagai semacam struktur konfigurasi.

Fungsi penting lainnya adalah Step(). Fungsi ini melakukan satu putaran pemeriksaan tabrakan, resolusi dan integrasi. Ini harus dipanggil dari dalam lingkaran pengatur waktu yang diuraikan dalam artikel kedua dari seri ini.

Meminta titik atau AABB melibatkan pemeriksaan untuk melihat objek mana yang benar-benar bertabrakan dengan penunjuk atau AABB di dalam adegan. Ini memudahkan logika terkait permainan untuk melihat bagaimana hal-hal ditempatkan di dunia.


Jump Table

Kita perlu cara mudah untuk memilih fungsi tabrakan yang harus dipanggil, berdasarkan tipe dua objek yang berbeda.

Dalam C++ ada dua cara utama yang saya ketahui: pengiriman ganda dan tabel melompat 2D. Dalam tes pribadi saya, saya menemukan tabel lompatan 2D ke superior, jadi saya akan membahas lebih detail tentang cara menerapkannya. Jika Anda berencana untuk menggunakan bahasa selain C atau C++, saya yakin sebuah array fungsi atau fungsi objek dapat dibangun mirip dengan tabel fungsi pointer (yang merupakan alasan lain saya memilih untuk berbicara tentang jump tables daripada opsi lain yang lebih spesifik untuk C++).

Jump tables di C atau C++ adalah tabel fungsi pointer. Indeks yang mewakili nama atau konstanta sembarang digunakan untuk mengindeks ke dalam tabel dan memanggil fungsi tertentu. Penggunaannya bisa terlihat seperti ini untuk jump table 1D:

Kode di atas benar-benar meniru apa bahasa C++ itu sendiri mengimplementasikan dengan panggilan fungsi virtual dan pewarisan. Namun, C++ hanya mengimplementasikan panggilan virtual dimensi tunggal. Meja 2D dapat dikonstruksi dengan tangan.

Berikut adalah beberapa pseudocode untuk tabel melompat 2D untuk memanggil rutinitas tabrakan:

Dan kita sudah memilikinya! Jenis sebenarnya dari masing-masing collider dapat digunakan untuk mengindeks ke dalam array 2D dan memilih fungsi untuk menyelesaikan tabrakan.

Perhatikan, bagaimanapun, bahwa AABBvsCircle dan CirclevsAABB hampir duplikat. Hal ini diperlukan! Kebutuhan normal harus dibalik untuk salah satu dari dua fungsi ini, dan itulah satu-satunya perbedaan di antara keduanya. Hal ini memungkinkan untuk resolusi tabrakan yang konsisten, tidak peduli kombinasi objek untuk menyelesaikan.


Kesimpulan

Saat ini kita telah membahas sejumlah besar topik dalam menyiapkan mesin fisika tubuh kaku khusus sepenuhnya dari awal! Resolusi tabrakan, friksi, dan arsitektur mesin adalah semua topik yang telah dibahas sejauh ini. Sebuah mesin fisika yang sangat sukses cocok untuk banyak game dua dimensi tingkat produksi dapat dibangun dengan pengetahuan yang disajikan dalam seri ini sejauh ini.

Melihat ke depan ke depan, saya berencana untuk menulis satu lagi artikel yang sepenuhnya ditujukan untuk fitur yang sangat diinginkan: rotasi dan orientasi. Berorientasi objek sangat menarik untuk menonton berinteraksi satu sama lain, dan merupakan bagian akhir yang memerlukan mesin fisika kustom kita.

Resolusi rotasi ternyata cukup sederhana, meskipun deteksi tabrakan sangat kompleks. Selamat mencoba sampai waktu berikutnya, dan tolong ajukan pertanyaan atau kirim komentar di bawah ini!

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Game Development tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.