Saya menggunakan MatterJs untuk permainan berbasis fisika dan belum menemukan solusi untuk masalah mencegah tubuh diseret paksa oleh mouse melalui badan lain. Jika Anda menyeret satu tubuh ke tubuh lain, tubuh yang diseret dapat memaksa dirinya sendiri masuk dan melalui tubuh lainnya. Saya mencari cara yang dapat diandalkan untuk mencegah mereka berpotongan. Anda dapat mengamati efek ini di demo MatterJS dengan memilih tubuh dengan mouse, dan mencoba memaksanya melalui tubuh lain. Berikut ini adalah contoh khas:
https://brm.io/matter-js/demo/#staticFriction
Sayangnya ini memecah game atau simulasi tergantung pada drag-and-drop. Saya telah mencoba banyak solusi, seperti memecahkan batasan mouse saat tabrakan terjadi, atau mengurangi kekakuan kendala, tetapi tidak ada yang bisa diandalkan.
Ada saran!
Jawaban:
Saya pikir jawaban terbaik di sini adalah perbaikan yang signifikan pada
Matter.Resolver
modul untuk menerapkan penghindaran prediktif dari konflik fisik antara setiap badan. Apa pun kekurangan itu dijamin gagal dalam keadaan tertentu. Yang dikatakan di sini adalah dua "solusi" yang, pada kenyataannya, hanyalah solusi parsial. Mereka diuraikan di bawah ini.Solusi 1 (Pembaruan)
Solusi ini memiliki beberapa keunggulan:
Gagasan di balik pendekatan ini adalah untuk menyelesaikan paradoks dari apa yang terjadi " ketika suatu kekuatan yang tak terhentikan bertemu dengan objek yang tak tergoyahkan " dengan menjadikan kekuatan itu terhenti. Ini diaktifkan oleh
Matter.Event
beforeUpdate
, yang memungkinkan kecepatan absolut dan impuls (atau lebih tepatnyapositionImpulse
, yang bukan benar-benar impuls fisik) di setiap arah untuk dibatasi ke dalam batas yang ditentukan pengguna.Dalam contoh ini saya membatasi
velocity
danpositionImpulse
dalamx
dany
untuk besarnya maksimum25.0
. Hasilnya ditunjukkan di bawah iniSeperti yang Anda lihat, sangat mungkin untuk melakukan kekerasan dalam menyeret tubuh dan mereka tidak akan melewati satu sama lain. Inilah yang membedakan pendekatan ini dari yang lain: sebagian besar solusi potensial gagal ketika pengguna cukup kasar dengan menyeret mereka.
Satu-satunya kekurangan yang saya temui dengan metode ini adalah bahwa adalah mungkin untuk menggunakan benda non-statis untuk mengenai benda non-statis yang cukup keras untuk memberikan kecepatan yang cukup ke titik di mana
Resolver
modul akan gagal mendeteksi tabrakan dan memungkinkan tubuh kedua melewati tubuh lain. (Dalam contoh gesekan statis kecepatan yang diperlukan sekitar50.0
, saya hanya berhasil melakukan ini satu kali, dan akibatnya saya tidak memiliki animasi yang menggambarkannya).Solusi 2
Ini adalah solusi tambahan, peringatan yang adil: itu tidak langsung.
Secara umum cara ini bekerja adalah untuk memeriksa apakah tubuh diseret
dragBody
,, telah bertabrakan dengan tubuh statis dan jika mouse telah bergerak terlalu jauh tanpadragBody
mengikuti. Jika mendeteksi bahwa pemisahan antara mouse dandragBody
telah menjadi terlalu besar itu menghapus pendengar acara dari dan menggantikannya dengan fungsi mousemove yang berbeda, . Fungsi ini memeriksa apakah mouse telah kembali ke jarak tertentu dari pusat tubuh. Sayangnya saya tidak bisa mendapatkan metode built-in untuk bekerja dengan baik sehingga saya harus memasukkannya secara langsung (seseorang yang lebih berpengetahuan daripada saya di Javascript harus mencari yang keluar). Akhirnya, jika suatu peristiwa terdeteksi itu beralih kembali ke pendengar normal .Matter.js
mouse.mousemove
mouse.element
mousemove()
Matter.Mouse._getRelativeMousePosition()
mouseup
mousemove
Setelah menerapkan skema switching pendengar acara, badan sekarang berperilaku lebih seperti ini
Saya telah menguji ini dengan cukup teliti, tetapi saya tidak dapat menjamin itu akan berhasil dalam setiap kasus. Ini juga mencatat bahwa
mouseup
acara tersebut tidak terdeteksi kecuali mouse berada di dalam kanvas ketika itu terjadi - tetapi ini berlaku untukmouseup
deteksi Matter.js jadi saya tidak mencoba untuk memperbaikinya.Jika kecepatannya cukup besar,
Resolver
akan gagal mendeteksi tabrakan, dan karena tidak ada pencegahan prediksi rasa konflik fisik ini, akan memungkinkan tubuh untuk melewatinya, seperti yang ditunjukkan di sini.Ini dapat diatasi dengan menggabungkan dengan Solusi 1 .
Satu catatan terakhir di sini, adalah mungkin untuk menerapkan ini hanya pada interaksi tertentu (misalnya yang antara badan statis dan non-statis). Melakukannya dilakukan dengan mengubah
ke (untuk mis. badan statis)
Solusi yang gagal
Jika ada pengguna di masa depan menemukan pertanyaan ini dan menemukan kedua solusi tidak cukup untuk kasus penggunaannya, berikut adalah beberapa solusi yang saya coba yang tidak berhasil. Panduan untuk hal-hal yang tidak boleh dilakukan.
mouse.mouseup
langsung: objek langsung dihapus.mouse.mouseup
melaluiEvent.trigger(mouseConstraint, 'mouseup', {mouse: mouse})
: ditimpa olehEngine.update
, perilaku tidak berubah.Matter.Body.setStatic(body, false)
ataubody.isStatic = false
).(0,0)
melaluisetForce
ketika mendekati konflik: objek masih bisa melewati, perlu diimplementasikanResolver
untuk benar-benar bekerja.mouse.element
ke kanvas yang berbeda melaluisetElement()
atau dengan bermutasimouse.element
secara langsung: objek segera dihapus.collisionStart
: deteksi tabrakan yang tidak konsisten masih memungkinkan melewati metode inisumber
Saya akan mengatur fitur ini dengan cara lain:
sumber
matter.js
menangani tubuh menyeret? dari sini "... seperti pegas virtual yang menempel pada mouse. Saat menyeret ... pegas terpasang [ke tubuh] dan menarik ke arah mouse ..."Resolver
untuk memutuskan apa yang harus dilakukan tentang bertabrakan - setelah memeriksa kode itu sedikit, saya berharap masih akan memutuskan untuk mengizinkan drag-through dalam banyak keadaan ..... mungkin bekerja jika Anda juga mengimplementasikan versi Anda sendirisolveVelocity
dansolvePosition
tetapi pada saat itu Anda masih melakukan secara manual apa yang Anda inginkan untuk ditangani MatterJS secara langsung ....Untuk mengontrol tabrakan saat diseret Anda perlu memanfaatkan tabrakan filter dan acara .
Buat badan dengan topeng filter tabrakan default
0x0001
. Tambahkan tangkapanstartdrag
danenddrag
acara dan atur kategori filter tabrakan tubuh yang berbeda untuk menghindari tabrakan sementara.sumber
Ini tampaknya terkait dengan masalah 672 pada halaman GitHub mereka yang tampaknya menunjukkan bahwa ini terjadi karena kurangnya Continuous Collision Detection (CCD).
Upaya untuk memperbaiki ini telah dilakukan dan kode untuk itu dapat ditemukan di sini tetapi masalah masih terbuka sehingga sepertinya Anda mungkin perlu mengedit mesin untuk membangun CCD ke dalamnya sendiri.
sumber