Saya menerapkan rutin deteksi tabrakan sederhana menggunakan AABB antara sprite permainan utama saya dan berbagai platform (Silakan lihat kode di bawah). Ini bekerja dengan baik, tetapi saya sekarang memperkenalkan gravitasi untuk membuat karakter saya jatuh dan itu menunjukkan beberapa masalah dengan rutin CD saya.
Saya pikir inti masalahnya adalah bahwa rutin CD saya memindahkan sprite kembali sepanjang sumbu di mana ia telah menembus jumlah paling sedikit ke dalam sprite lainnya. Jadi, jika lebih banyak di sumbu Y daripada X, maka itu akan memindahkannya kembali di sepanjang X Axis.
Namun, sekarang sprite (pahlawan) saya sekarang jatuh pada kecepatan 30 piksel per bingkai (Ini adalah layar tinggi 1504 - saya perlu turun secepat ini karena saya ingin mencoba mensimulasikan gravitasi 'normal', setiap lambat hanya terlihat aneh ) Saya mendapatkan masalah ini. Saya akan mencoba untuk menunjukkan apa yang terjadi (dan apa yang saya pikir menyebabkannya - walaupun saya tidak yakin) dengan beberapa gambar: (Kode di bawah gambar).
Saya akan sangat menghargai beberapa saran tentang cara mengatasi masalah ini.
Untuk klarifikasi, pada gambar kanan di atas, ketika saya mengatakan posisi dikoreksi 'salah' itu mungkin agak menyesatkan. Kode itu sendiri bekerja dengan benar untuk bagaimana itu ditulis, atau dengan kata lain, algoritma itu sendiri jika berperilaku seperti yang saya harapkan, tapi saya perlu mengubah perilakunya untuk menghentikan masalah ini terjadi, harapan yang mengklarifikasi komentar saya dalam gambar .
Kode Saya
public boolean heroWithPlatforms(){
//Set Hero center for this frame
heroCenterX = hero.xScreen+(hero.quadWidth/2);
heroCenterY = hero.yScreen+(hero.quadHeight/2);
//Iterate through all platforms to check for collisions
for(x=0;x<platformCoords.length;x+=2){
//Set platform Center for this iteration
platformCenterX = platformCoords[x]+(platforms.quadWidth/2);
platformCenterY = platformCoords[x+1]+(platforms.quadHeight/2);
// the Dif variables are the difference (absolute value)
// of the center of the two sprites being compared (one for X axis difference
//and on for the Y axis difference)
difX = Math.abs(heroCenterX-platformCenterX);
difY = Math.abs(heroCenterY-platformCenterY);
//If 1
//Check the difference between the 2 centers and compare it to the vector (the sum of
//the two sprite's widths/2. If it is smaller, then the sprites are pverlapping along
//the X axis and we can now proceed to check the Y axis
if (difX<vecXPlatform){
//If 2
//Same as above but for the Y axis, if this is also true, then we have a collision
if(difY<vecYPlatform){
//we now know sprites are colliding, so we now need to know exactly by how much
//penX will hold the value equal to the amount one sprite (hero, in this case)
//has overlapped with the other sprite (the platform)
penX = vecXPlatform-difX;
penY = vecYPlatform-difY;
//One sprite has penetrated into the other, mostly in the Y axis, so move sprite
//back on the X Axis
if (penX < penY){hero.xScreen-=penX*(heroCenterX-platformCenterX>=0 ? -1 : 1);}
//Sprite has penetrated into the other, mostly in the X asis, so move sprite
//back on the Y Axis
else if (penY < penX) {hero.yScreen-=penY*(heroCenterY-platformCenterY>=0 ? -1 : 1);}
return true;
}//Close 'If' 2
} //Close 'If' 1
}
//Otherwise, no collision
return false;
}
sumber
//One sprite has penetrated into the other, mostly in the Y axis, so move sprite //back on the X Axis
Jawaban:
selama percobaan saya dengan kanvas HTML5 dan AABB saya menemukan apa yang Anda alami. Ini memang terjadi ketika saya mencoba membuat platform dari kotak yang berdekatan berukuran 32x32 piksel.
Solusi yang saya coba berdasarkan urutan pilihan pribadi saya
1 - Bagi gerakan dengan sumbu
Saya saat ini, dan saya pikir saya akan melanjutkan permainan saya dengannya. Tetapi pastikan untuk memeriksa apa yang saya sebut Phantom AABB jika Anda membutuhkan solusi cepat tanpa harus banyak memodifikasi desain Anda saat ini.
Dunia gim saya memiliki fisika yang sangat sederhana. Tidak ada konsep gaya (belum), hanya perpindahan. Gravitasi adalah perpindahan konstan ke bawah. Belum ada akselerasi.
Perpindahan diterapkan oleh sumbu. Dan dalam hal ini termasuk solusi pertama ini.
Setiap bingkai game:
move_x diatur sesuai dengan pemrosesan input, jika tidak tombol panah ditekan maka move_x = 0. Nilai di bawah nol berarti kiri, jika tidak ke kanan.
Memproses semua sprite bergerak lain dan memutuskan nilai komponen "bergerak" mereka, mereka juga memiliki komponen "bergerak".
Catatan: setelah deteksi dan respons tabrakan, komponen pemindahan harus diatur ke nol, baik properti x dan y, karena centang selanjutnya gravitasi akan ditambahkan lagi. Jika Anda tidak mengatur ulang, Anda akan mengakhiri dengan gerakan. Dua kali gravitasi yang diinginkan, dan pada centang berikutnya akan tiga kali.
Lalu masukkan kode penempatan dan deteksi tabrakan.
Komponen pemindahan tidak benar-benar posisi sprite saat ini. Sprite belum bergerak bahkan jika move.x atau y berubah. Komponen "move" adalah cara untuk menghemat perpindahan yang akan diterapkan ke posisi sprite di bagian loop permainan yang benar.
Proses dulu sumbu y (move.y). Terapkan move.y ke sprite.position.y. Kemudian terapkan metode AABB untuk melihat apakah sprite bergerak yang sedang diproses tumpang tindih dengan platform AABB (Anda sudah mengerti bagaimana melakukan ini). Jika tumpang tindih maka pindahkan sprite kembali pada sumbu y dengan menerapkan penetrasi. Y. Ya, berlawanan dengan jawaban saya yang lain, sekarang metode evolved ini mengabaikan penetrasi. X, untuk langkah proses ini. Dan kami menggunakan penetrasi. Bahkan walaupun itu lebih besar dari penetrasi. X, kami bahkan tidak memeriksanya.
Kemudian proses sumbu x (move.x). Terapkan bergerak.x ke sprite.position.x. Dan lakukan yang sebaliknya dari sebelumnya. Anda akan memindahkan sprite hanya pada sumbu horizontal kali ini dengan menerapkan penetrasi.x. Seperti sebelumnya, Anda tidak peduli apakah penetrasi.x kurang atau lebih besar dari penetrasi.
Konsep di sini, adalah bahwa jika sprite tidak bergerak, dan pada awalnya tidak bertabrakan, maka akan tetap seperti itu di frame berikutnya (sprite.moves.x dan y adalah nol). Kasus khusus di mana objek permainan lain secara ajaib berpindah ke posisi yang tumpang tindih dengan sprite mulai diproses adalah sesuatu yang akan saya tangani nanti.
Ketika sprite mulai bergerak. Jika hanya bergerak di sumbu x, maka kami hanya tertarik jika menembus sesuatu di sebelah kiri atau kanan. Karena sprite tidak bergerak ke bawah, dan kami tahu ini karena properti y dari komponen pemindahan adalah nol, kami bahkan tidak memeriksa nilai yang dihitung untuk penetrasi. Jika penetrasi ada dalam sumbu gerakan, kami menerapkan koreksi, jika tidak kami hanya membiarkan sprite bergerak.
Bagaimana dengan perpindahan diagonal, tidak harus dalam sudut 45 derajat?
Sistem yang diusulkan dapat menanganinya. Anda hanya perlu memproses setiap sumbu secara terpisah. Selama simulasi Anda. Kekuatan yang berbeda diterapkan pada sprite. Bahkan jika mesin Anda belum memahami kekuatan. Gaya-gaya ini diterjemahkan menjadi perpindahan sewenang-wenang dalam bidang 2D, perpindahan ini adalah vektor 2D ke segala arah dan dengan panjang apa pun. Dari vektor ini Anda dapat mengekstrak sumbu y dan sumbu x.
Apa yang harus dilakukan jika vektor perpindahan terlalu besar?
Anda tidak menginginkan ini:
Saat langkah baru kami menerapkan proses logika, sumbu pertama dan kemudian yang lain, perpindahan besar mungkin berakhir dilihat oleh kode tabrakan seperti L besar, ini tidak akan mendeteksi dengan benar tabrakan dengan objek yang memotong vektor perpindahan Anda.
Solusinya adalah membagi perpindahan besar dalam langkah-langkah kecil, idealnya lebar atau tinggi sprite Anda, atau setengah lebar atau tinggi sprite Anda. Untuk mendapatkan sesuatu seperti ini:
Bagaimana dengan teleporting sprite?
Jika Anda menyatakan teleportasi sebagai perpindahan besar, menggunakan komponen gerakan yang sama dengan gerakan normal, maka tidak ada masalah. Jika tidak, maka Anda harus memikirkan cara untuk menandai sprite teleportasi untuk diproses oleh kode tumbukan (menambahkan ke daftar yang didedikasikan untuk tujuan ini?), Selama kode respons Anda dapat langsung memindahkan sprite berdiri yang ada di cara ketika teleportasi terjadi.
2 - Phantom AABB
Memiliki AABB sekunder untuk setiap sprite yang dipengaruhi oleh gravitasi yang dimulai dari dasar sprite, memiliki lebar spab AABB yang sama, dan tinggi 1 piksel.
Idenya di sini adalah bahwa AABB hantu ini selalu bertabrakan dengan platform di bawah sprite. Hanya ketika AABB phantom ini tidak tumpang tindih, gravitasi apa pun diizinkan untuk diterapkan pada sprite.
Anda tidak perlu menghitung vektor penetrasi untuk phabom AABB dan platform. Anda hanya tertarik pada uji tabrakan sederhana, jika tumpang tindih platform, gravitasi tidak dapat diterapkan. Sprite Anda dapat memiliki properti boolean yang memberi tahu apakah itu lebih dari platform atau di udara. Anda berada di udara ketika hantu AABB Anda tidak bertabrakan dengan platform di bawah pemain.
Ini:
Menjadi sesuatu seperti ini:
Sangat sederhana dan andal.
Anda membiarkan implementasi AABB Anda apa adanya.
Hantu AABB mungkin memiliki loop khusus yang memprosesnya, yang hanya memeriksa tabrakan sederhana, dan jangan buang waktu menghitung vektor penetrasi. Pengulangan ini harus sebelum kode tumbukan dan respons normal. Anda dapat menerapkan gravitasi selama loop ini, untuk sprite di udara menerapkan gravitasi. Jika phantom AABB itu sendiri adalah kelas atau struktur, itu mungkin memiliki referensi ke sprite miliknya.
Ini sangat mirip dengan solusi yang diusulkan lainnya di mana Anda memeriksa apakah pemain Anda melompat. Saya memberikan cara yang mungkin untuk mendeteksi jika pemain memiliki kaki di atas platform.
sumber
Saya akan menggabungkan ubin platform ke dalam entitas platform tunggal.
Misalnya, Anda mengambil 3 ubin dari gambar dan menggabungkannya menjadi satu kesatuan, entitas Anda akan memiliki kotak tabrakan:
Menggunakan itu untuk tabrakan akan memberi Anda y sebagai sumbu penetrasi paling sedikit di sebagian besar platform sambil tetap memungkinkan Anda untuk memiliki ubin khusus di dalam platform.
sumber
Masalah seperti ini biasa terjadi dengan metode pendeteksian tabrakan baru.
Saya tidak tahu terlalu banyak tentang pengaturan tabrakan Anda saat ini, tetapi begini caranya:
Pertama, buat variabel-variabel ini:
Kedua, buat penghitung waktu untuk menghitung delta untuk memengaruhi kecepatan objek.
Ketiga, lakukan ini:
Jika Anda melakukan ini, seharusnya tidak ada masalah. Semoga ini membantu!
sumber