现在要做旋转我为每个旋转角度都有一个单独的框架,但我更喜欢有一个我旋转的图像。我的问题是,如何在XNA / C#中进行矩阵变换,以便颜色数据的旋转方式与在屏幕上呈现精灵的方式相同?我找到了这个旧的SO question,但我真的不明白答案,我想知道代码是如何工作的,以防以后需要修改。
所需的任何和所有位置/旋转信息都存储在包含精灵的实体中,并且假设两个精灵都旋转。
到目前为止,这是我的代码:
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 :(得分:0)
您应该保持数据不变。您只需修改访问方式即可。
对于像素完美的碰撞检测,基本思想如下:你有两个精灵分别用变换矩阵m1
和m2
渲染。现在迭代精灵1的每个像素。找出这个像素所在的屏幕位置。找出位于相同(或相似)位置的精灵2的像素。
变换矩阵通常类似于
t = Matrix.CreateRotationZ(angle) * Matrix.CreateTranslation(position);
您可以使用带有矩阵的SpriteBatch.Begin()
重载来检查矩阵计算。
从精灵1的像素空间到世界空间的转换是:
worldPos = sprite1LocalPos * m1
将世界空间转换为精灵2的像素空间是:
sprite2LocalPos = worldPos * Matrix.Invert(m2)
= sprite1LocalPos * m1 * Matrix.Invert(m2)
这基本上就是你需要做的所有事情:
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;