2016-06-06 4 views
0

Прямо сейчас, чтобы сделать поворот У меня есть отдельный кадр для каждого угла поворота, но у меня есть скорее одно изображение, которое я поворачиваю. Мой вопрос: как мне преобразовать матрицу в XNA/C#, чтобы данные цвета также вращаются так же, как спрайт отображается на экране? Я нашел этот старый SO question, но я действительно не понимаю ответа, и я хотел бы знать, как работает код, если он нуждается в дальнейшем изменении.XNA: Столкновения между вращающимися спрайтами

Любая необходимая информация о местоположении и ротации сохраняется в объекте, который содержит спрайт, и предполагается, что оба спрайта вращаются.

Вот мой код до сих пор:

private static bool PixelPerfect(PhysicsEntity a, PhysicsEntity b) 
    { 
     if (!BoundingBox(a, b)) return false; 

     var colorDataA = new Color[a.Sprite.Source.Width * a.Sprite.Source.Height]; 
     var colorDataB = new Color[b.Sprite.Source.Width * b.Sprite.Source.Height]; 

     a.Sprite.Texture.GetData(0, a.Sprite.Source, colorDataA, 0, colorDataA.Length); 
     b.Sprite.Texture.GetData(0, b.Sprite.Source, colorDataB, 0, colorDataB.Length); 

     var top = (int) Math.Max(a.BoundingBox.Top, b.BoundingBox.Top); 
     var bottom = (int) Math.Min(a.BoundingBox.Bottom, b.BoundingBox.Bottom); 
     var left = (int) Math.Max(a.BoundingBox.Left, b.BoundingBox.Left); 
     var right = (int) Math.Min(a.BoundingBox.Right, b.BoundingBox.Right); 

     for (var y = top; y < bottom; y++) 
     { 
      for (var x = left; x < right; x++) 
      { 
       var colorA = colorDataA[(int) ((y - a.BoundingBox.Top) * (a.BoundingBox.Width) + (x - a.BoundingBox.Left))]; 
       var colorB = colorDataB[(int) ((y - b.BoundingBox.Top) * (a.BoundingBox.Width) + (x - a.BoundingBox.Left))]; 
       if (colorA.A == 0 || colorB.A == 0) continue; 
       a.CollisionPoint.ChangePositon(x, y); 
       b.CollisionPoint.ChangePositon(x, y); 
       return true; 
      } 
     } 
     return false; 
    } 

ответ

0

Вы должны поддерживать постоянные данные. Вы просто изменяете способ доступа к нему.

Для идеального обнаружения столкновений основная идея заключается в следующем: у вас есть два спрайта, которые визуализируются с матрицами преобразования m1 и m2 соответственно. Теперь итерация каждого пикселя спрайта 1. Узнайте, на каком месте экрана находится этот пиксель. Найдите пиксель спрайта 2, который находится в том же (или подобном) положении.

преобразования матрицы, как правило, что-то вроде

t = Matrix.CreateRotationZ(angle) * Matrix.CreateTranslation(position); 

Вы можете проверить вычисления матрицы с перегрузкой SpriteBatch.Begin(), которая принимает матрицу.

преобразования из пиксельного пространства Sprite 1 в мировом пространстве является:

worldPos = sprite1LocalPos * m1 

Преобразования формы мирового пространства для Sprite 2 в пиксельном пространстве является:

sprite2LocalPos = worldPos * Matrix.Invert(m2) 
       = sprite1LocalPos * m1 * Matrix.Invert(m2) 

И это в основном все, что вам нужно do:

Matrix transform = m1 * Matrix.Invert(m2); 
Rectangle rect = new Rectangle(0, 0, texture2.Width, texture2.Height); 
for (int x = 0; x < texture1.Width; x++) 
{ 
    for (int y = 0; y < texture1.Height; y++)  //Iterate every pixel of sprite 1 
    { 
     index = x + texture1.Width * y;    //Calculate the pixel index 
     if (data1[index].A < 10)     //If the pixel is (almost) transparent, 
      continue;        //ignore it 

     Vector2 sprite1Local = new Vector2(x, y); 
     Vector2 sprite2Local        //get the pixel of sprite 2 
      = Vector2.Transform(sprite1Local, transform); //that is at the same position 

     if(!rect.Contains((int)sprite2Local.X, (int)sprite2Local.Y)) 
                //if this is outside of the sprite, 
      continue;        //ignore it 

     index2 = (int)sprite2Local.X + (int)sprite2Local.Y * texture2.Width; 
     if(data2[index2].A>10)      //If the pixel is not transparent, 
      return true;       //there is a collision 
    } 
} 
return false; 
Смежные вопросы