algoritma collision persegi panjang 2D sederhana yang juga menentukan sisi mana yang bertabrakan persegi panjang?

16

Saya awalnya mencoba mengimplementasikan persimpangan persegi panjang, yang berfungsi dengan baik. Namun, ketika saya harus menerapkan sistem fisika, seperti kecepatan, percepatan, dan vektor arah, saya harus menemukan cara untuk menentukan sisi mana dari persegi panjang bertabrakan. Sekarang, di sistem saya, tidak ada persegi panjang yang diputar, jadi ini menyederhanakan masalah. Namun, saya tidak dapat menemukan cara mudah untuk menentukan sisi persegi panjang mana yang bertabrakan. Saya pernah menangani masalah ini sebelumnya tetapi gagal total.

Apa yang saya lakukan di masa lalu adalah menentukan jarak antara setiap sisi persegi panjang paralel dan memeriksa apakah jaraknya dekat dengan 0 (menggunakan beberapa rentang jarak yang telah ditentukan sebelumnya) atau 0. Namun, untuk aritmatika titik apung, ini terbukti tidak stabil karena waktu yang tidak diketahui berlalu. Kadang-kadang, persegi panjang akan benar-benar berpotongan satu sama lain sebelum memenuhi kisaran yang ditentukan.

Di sisi lain, saya berpikir tentang menelurkan banyak persegi panjang, masing-masing persegi panjang untuk setiap sisi. Namun, setelah berpikir lagi, itu akan menjadi hal yang sama dengan memiliki sisi paralel dengan pengecekan jarak, hanya saja jarak itu adalah lebar dari setiap mini-rectangle.

Karena itu, ada saran untuk masalah ini?

pengguna1542
sumber
Apakah Anda menggunakan pembaruan posisi diskrit atau kontinu? (apakah Anda memperbarui kecepatan Anda dengan akselerasi sekali setiap frame dan kemudian menghitung posisi, atau menggunakan fungsi untuk memperkirakan posisi)
Casey Kuball

Jawaban:

24

Diadaptasi dari jawaban saya untuk "Sisi Mana yang Dipukul?" :

Saya menyarankan menghitung jumlah Minkowski B dan A, yang merupakan persegi panjang baru, dan memeriksa di mana pusat persegi panjang A terletak relatif pada persegi panjang baru (untuk mengetahui apakah tabrakan terjadi) dan ke diagonalnya (untuk mengetahui di mana tabrakan sedang terjadi):

float w = 0.5 * (A.width() + B.width());
float h = 0.5 * (A.height() + B.height());
float dx = A.centerX() - B.centerX();
float dy = A.centerY() - B.centerY();

if (abs(dx) <= w && abs(dy) <= h)
{
    /* collision! */
    float wy = w * dy;
    float hx = h * dx;

    if (wy > hx)
        if (wy > -hx)
            /* collision at the top */
        else
            /* on the left */
    else
        if (wy > -hx)
            /* on the right */
        else
            /* at the bottom */
}
sam hocevar
sumber
1
Saya ingin menambahkan bahwa 'atas' dan 'bawah' relatif terhadap sistem koordinat Anda. Dalam permainan saya misalnya, (0,0) ada di kiri atas, jadi mereka terbalik dari contoh Anda. Hanya sesuatu yang perlu diingat.
Neikos
solusi hebat, bekerja sangat baik untuk kebutuhan saya.
Opiatefuchs
1
Apakah ada kesalahan dengan dx menjadi 0 atau dy menjadi 0 atau keduanya? Biarkan saya beralasan ... jika dx = 0 && dy == 0, itu berarti kedua persegi panjang berada pada asal yang sama, maka algoritma mengembalikan bawah secara default? jika salah satu dari mereka adalah 0, maka hasil yang benar diharapkan. Jadi, saya pikir, algoritma ini benar kecuali untuk kasus di mana dx == 0 && dy == 0, yang seharusnya tidak ditentukan dan bukan bagian bawah. Jadi, waspadalah & terima kasih.
Prasanth
1
Sekarang, saya bertanya-tanya apa yang terjadi ketika dx == dy, w == h ... maka juga, kode memutuskan bahwa hasilnya adalah satu sisi ketika itu sebenarnya tidak ditentukan .. bayangkan dua kotak berpotongan sedemikian rupa sehingga satu pusat persegi berada di sudut kotak lain dan pusat kotak lainnya adalah di sudut kotak pertama. Di sini, sisi harus tidak pasti - tidak kanan atau bawah. Keduanya ?!
Prasanth