Saya tidak terbiasa dengan Android jadi saya tidak tahu alat apa yang Anda miliki, tetapi saya dapat memberi tahu Anda cara untuk menerapkannya secara umum. Betapa mudahnya itu tergantung pada apa yang disediakan Android untuk Anda. Anda akan membutuhkan matriks atau setidaknya mereka akan menyederhanakan banyak perhitungan.
Sebagai permulaan, lakukan tabrakan kotak pembatas dan segera kembali jika mereka tidak bertabrakan untuk menghindari perhitungan lebih lanjut. Itu logis karena jika kotak pembatas tidak bertabrakan, dijamin tidak ada piksel yang akan bertabrakan juga.
Setelah itu, jika diperlukan pemeriksaan tabrakan piksel sempurna, maka poin terpenting adalah Anda harus melakukan pemeriksaan itu di ruang yang sama . Ini dapat dilakukan dengan mengambil setiap piksel dari sprite A, menerapkan serangkaian transformasi untuk membawanya ke ruang lokal sprite B, dan kemudian memeriksa apakah itu bertabrakan dengan piksel apa pun pada posisi tersebut pada sprite B. Tumbukan terjadi ketika kedua piksel diperiksa buram.
Jadi, hal pertama yang Anda butuhkan adalah membuat matriks dunia untuk masing-masing sprite. Mungkin ada tutorial online yang mengajarkan Anda cara membuatnya, tetapi pada dasarnya harus merupakan gabungan dari beberapa matriks sederhana dengan urutan sebagai berikut:
Translation(-Origin) * Scale * Rotation * Translation(Position)
Kegunaan dari matriks ini adalah dengan mengalikan titik di ruang lokal - dan misalnya jika Anda mendapatkan piksel menggunakan metode seperti bitmap.getPixelAt(10,20)
10,20 didefinisikan dalam ruang lokal - dengan matriks dunia yang sesuai akan memindahkannya ke ruang dunia:
LocalA * WorldMatrixA -> World
LocalB * WorldMatrixB -> World
Dan jika Anda membalikkan matriks Anda juga dapat pergi ke arah yang berlawanan yaitu mengubah titik dari ruang dunia ke masing-masing ruang lokal sprite tergantung pada matriks yang Anda gunakan:
World * InverseWorldMatrixA -> LocalA
World * InverseWorldMatrixB -> LocalB
Jadi untuk memindahkan titik dari ruang lokal sprite A ke ruang lokal sprite B , Anda pertama-tama mengubahnya dengan menggunakan matriks dunia sprite A, untuk membawanya ke ruang dunia, dan kemudian menggunakan matriks dunia terbalik sprite B , untuk memasukkannya ke dalam ruang lokal sprite B:
LocalA * WorldMatrixA -> World * InverseWorldMatrixB -> LocalB
Setelah transformasi, Anda memeriksa apakah titik baru berada dalam batas sprite B, dan jika ya, Anda memeriksa piksel di lokasi tersebut seperti yang Anda lakukan untuk sprite A. Jadi seluruh proses menjadi seperti ini (dalam kodesemu dan tidak teruji) :
bool PixelCollision(Sprite a, Sprite B)
{
// Go over each pixel in A
for(i=0; i<a.Width; ++i)
{
for(j=0; j<a.Height; ++j)
{
// Check if pixel is solid in sprite A
bool solidA = a.getPixelAt(i,j).Alpha > 0;
// Calculate where that pixel lies within sprite B's bounds
Vector3 positionB = new Vector3(i,j,0) * a.WorldMatrix * b.InverseWorldMatrix;
// If it's outside bounds skip to the next pixel
if(positionB.X<0 || positionB.Y<0 ||
positionB.X>=b.Width || positionB.Y>=b.Height) continue;
// Check if pixel is solid in sprite B
bool solidB = b.getPixelAt(positionB.X, positionB.Y).Alpha > 0;
// If both are solid then report collision
if(solidA && solidB) return true;
}
}
return false;
}
Sementara jawaban David Gouveia kedengarannya benar, itu bukan solusi terbaik dari sudut pandang kinerja. Ada beberapa optimasi penting yang perlu Anda lakukan:
memilah dan menghindari pemeriksaan yang tidak perlu dengan memeriksa terlebih dahulu dengan tabrakan lingkaran sederhana: untuk mendapatkan pusat dan jari-jari sprite Anda dalam rotasi apa pun, dapatkan koordinat minimum dan maksimum x dan y dari semua 4 (sudah diputar) simpul: kemudian Anda dapat membuat lingkaran yang menutup sprite dengan:
center = max_x-min_x / 2, max_y-min_y / 2
radius = max (max_x-min_x, max_y-min_y)
Sekarang Anda seharusnya tidak memiliki terlalu banyak kandidat untuk diperiksa dengan rasterisasi gambar yang sudah diubah (diputar) pada dasarnya dengan menggunakan algoritma texturemapping sederhana . Pada dasarnya Anda melacak 4 baris per sprite raster: 2 baris dari vertex ke verteks berikutnya dari kotak Anda yang diputar (b dan c) 2 baris masuk dalam "ruang bitmap" dari vertex u1 / v1 ke simpul berikutnya u2 / v2 dan u3 / v3: Catatan: Saya mencari di Google gambar ini dan itu menunjukkan segitiga, kotak Anda hanya dua segitiga. Sangat penting bagi algoritma ini untuk menggambar garis- garis horizontal (itu sebabnya disebut " rasterizer ") untuk menghindari "lubang" di dalam bitmap karena kesalahan pembulatan. Dengan menghitung garis dengan algoritma bresenham, Anda perlu untuk setiap pixel hanya 4 tambahan dan 4 membandingkan (dan kadang-kadang dua tambahan tambahan, tergantung pada kemiringan) Apa yang Anda lakukan adalah Anda menulis texturemapper poligon Anda sendiri, namun tanpa koreksi 3d yang mahal (dan sulit dioptimalkan).
Anda dapat dengan mudah mengurangi resolusi bitmap tabrakan (misalnya dengan faktor 2) dan menghemat lebih banyak waktu. pemeriksaan tabrakan pada setengah dari resolusi shouild menjadi tidak terlalu mencolok.
Jika Anda menggunakan akselerasi grafik, Anda dapat menggunakan semacam cek Buffer yang dipercepat HW (stensil?) Untuk menghindari pengkodean rasterizer sendiri.
Masalah utama adalah: Java tidak terlalu cepat dalam mengakses data bitmap yang disimpan dalam array 2D. Saya akan merekomendasikan untuk menyimpan data dalam array 1 dimensi untuk menghindari setidaknya 1 indexOutOfBounds memeriksa setiap akses. Juga gunakan dimensi power-of-2 (seperti 64x64, 128x128, dll. Dengan ini Anda dapat menghitung offset melalui bitshifting dan bukan multiplikasi). Anda juga dapat mengoptimalkan akses tekstur kedua untuk melakukannya hanya jika yang pertama memiliki nilai! = 0 (transparan)
Semua masalah ini diselesaikan dalam mesin render perangkat lunak, mungkin berguna untuk melihat kode sumber
sumber