Я не знаком с Android, поэтому не знаю, какие инструменты есть в вашем распоряжении, но я могу рассказать вам, как реализовать это в общих чертах. Насколько это будет легко, зависит от того, что предоставляет Android. Вам понадобятся матрицы или, по крайней мере, они значительно упростят вычисления.
Для начала сделайте проверку столкновения ограничительной рамки и немедленно вернитесь, если они не сталкиваются, чтобы избежать дальнейших вычислений. Это логично, потому что, если ограничивающие рамки не сталкиваются, это гарантирует, что пиксели также не будут сталкиваться.
Впоследствии, если необходима проверка столкновения с идеальным пикселем, то наиболее важным моментом является то, что вы должны выполнить эту проверку в том же месте . Это можно сделать, взяв каждый пиксель из спрайта A, применив серию преобразований, чтобы поместить их в локальное пространство спрайта B, а затем проверьте, не сталкивается ли он с каким-либо пикселем в этой позиции на спрайте B. Столкновение происходит, когда оба пикселя проверено непрозрачно.
Итак, первое, что вам нужно, это построить мировую матрицу для каждого из спрайтов. Возможно, в Интернете есть учебники, в которых вы узнаете, как их создать, но в основном это должно быть объединение нескольких более простых матриц в следующем порядке:
Translation(-Origin) * Scale * Rotation * Translation(Position)
Полезность этой матрицы заключается в том, что путем умножения точки в локальном пространстве - и, например, если вы получаете пиксели с использованием метода, подобного bitmap.getPixelAt(10,20)
10,20, определяется в локальном пространстве - соответствующая мировая матрица переместит ее в мировое пространство:
LocalA * WorldMatrixA -> World
LocalB * WorldMatrixB -> World
И если вы инвертируете матрицы, вы также можете пойти в противоположном направлении, то есть преобразовать точки из мирового пространства в каждое из локальных пространств спрайта в зависимости от того, какую матрицу вы использовали:
World * InverseWorldMatrixA -> LocalA
World * InverseWorldMatrixB -> LocalB
Таким образом, чтобы переместить точку из локального пространства спрайта A в локальное пространство спрайта B , вы сначала трансформируете ее, используя мировую матрицу спрайта A, чтобы перевести ее в мировое пространство, а затем, используя матрицу обратного мира спрайта B , чтобы получить ее в Локальное пространство спрайта Б:
LocalA * WorldMatrixA -> World * InverseWorldMatrixB -> LocalB
После преобразования вы проверяете, попадает ли новая точка в границы спрайта B, и если это так, вы проверяете пиксель в этом месте, как вы это делали для спрайта A. Таким образом, весь процесс становится примерно таким (в псевдокоде и непроверенном) :
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;
}