我一直在为学校项目开发自己的物理引擎,最近遇到了一个问题:大精灵上的每像素碰撞使我的 FPS 下降很多。
这是我的像素碰撞代码。在输入以下代码之前,我使用
Intersects()
来查看它们的边界框是否发生碰撞。
private bool PerPixelCollision(IObject a, IObject b)
{
Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height];
a.Texture.GetData(bitsA);
Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height];
b.Texture.GetData(bitsB);
// Calculate the intersecting rectangle
int x1 = Math.Max(a.Bounds.X, b.Bounds.X);
int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, b.Bounds.X + b.Bounds.Width);
int y1 = Math.Max(a.Bounds.Y, b.Bounds.Y);
int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, b.Bounds.Y + b.Bounds.Height);
Color c;
Color d;
// For each single pixel in the intersecting rectangle
for (int y = y1; y < y2; ++y)
{
for (int x = x1; x < x2; ++x)
{
// Get the color from each texture
c = bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y) * a.Texture.Width];
d = bitsB[(x - b.Bounds.X) + (y - b.Bounds.Y) * b.Texture.Width];
if (c.A != 0 && d.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision
{
return true;
}
}
}
// If no collision occurred by now, we're clear.
return false;
}
在我用来测试的示例中,我将 4 个精灵放入另一个代表地板 (736x79) 的精灵中。当我将代表地板的精灵更改为更大的精灵 (3600x270) 时,FPS 会下降。我知道问题出在像素碰撞中,因为我正在使用分析器。
有人知道如何优化碰撞吗?
PS:抱歉,如果我对我的问题不够清楚。我的英语不太好。
编辑:第一个问题是通过使用@pinckerman提供的解决方案解决的,但我发现了另一个与像素碰撞检测相关的问题。 当精灵与纹理的透明部分碰撞时,我们得到相交的部分并检查该部分的所有像素。问题是:当透明部分足够大以覆盖整个精灵时,我检查该精灵的整个纹理(当前使用 50x50 纹理,即 2500 像素)。有什么方法可以不检查整个纹理吗?
谢谢
我很确定您的 FPS 下降如此之多是因为您正在这样做:
Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height];
a.Texture.GetData(bitsA);
Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height];
b.Texture.GetData(bitsB);
在方法的开头。
我想你在每个
PerPixelCollision
循环中调用你的 Update
并且在每个游戏周期创建和复制数百万个值并不是一件非常有效的事情。
一个大精灵会创建一个巨大的
Color[]
数组:数组越大,此方法就越慢。
编辑:
对于你的第二个问题,我认为,如果你事先不知道“大”纹理的透明区域在哪里,无论如何你都必须检查整个精灵。
如果你的精灵不是太大,那对性能来说并不是很大的浪费。
PS:我看到你自己得到了相交
Rectangle
,也许你会发现有用的这个方法。