我在C#游戏编程中有关于精灵碰撞的C#代码段代码,希望大家帮我澄清一下。
我不理解方法IsCollided,尤其是d1和d2的计算,以确定精灵是否碰撞,在这种情况下Matrix Invert()和Multiphy的含义和用法以及Color alpha组件的使用确定2个精灵的碰撞。
非常感谢。
public struct Vector
{
public double X;
public double Y;
public Vector(double x, double y)
{
X = x;
Y = y;
}
public static Vector operator -(Vector v, Vector v2)
{
return new Vector(v.X-v2.X, v.Y-v2.Y);
}
public double Length
{
get
{
return Math.Sqrt(X * X + Y * Y);
}
}
}
public class Sprite
{
public Vector Position;
protected Image _Image;
protected Bitmap _Bitmap;
protected string _ImageFileName = "";
public string ImageFileName
{
get { return _ImageFileName; }
set
{
_ImageFileName = value;
_Image = Image.FromFile(value);
_Bitmap = new Bitmap(value);
}
}
public Matrix Transform
{
get
{
Vector v = Position;
if (null != _Image)
v -= new Vector(_Image.Size) / 2;
Matrix m = new Matrix();
m.RotateAt(50.0F, new PointF(10.0F, 100.0F));
m.Translate((float)v.X, (float)v.Y);
return m;
}
}
public bool IsCollided(Sprite s2)
{
Vector v = this.Position - s2.Position;
double d1 = Math.Sqrt(_Image.Width * _Image.Width + _Image.Height * _Image.Height)/2;
double d2 = Math.Sqrt(s2._Image.Width * s2._Image.Width + s2._Image.Height * s2._Image.Height)/2;
if (v.Length > d1 + d2)
return false;
Bitmap b = new Bitmap(_Image.Width, _Image.Height);
Graphics g = Graphics.FromImage(b);
Matrix m = s2.Transform;
Matrix m2 = Transform;
m2.Invert();
Matrix m3 = m2;
m3.Multiply(m);
g.Transform = m3;
Vector2F v2 = new Vector2F(0,0);
g.DrawImage(s2._Image, v2);
for (int x = 0; x < b.Width; ++x)
for (int y = 0; y < b.Height; ++y)
{
Color c1 = _Bitmap.GetPixel(x, y);
Color c2 = b.GetPixel(x, y);
if (c1.A > 0.5 && c2.A > 0.5)
return true;
}
return false;
}
}
答案 0 :(得分:3)
这有点令人费解。这两部分:
第一部分(简单和快速)
第一部分(涉及v,d1 + d2)可能令人困惑,因为不是使用框进行碰撞测试,而是使用图像的尺寸来构造边界圆。然后使用这些边界圆进行简单的碰撞测试。这是“快速n脏”测试,可以消除明显没有碰撞的精灵。
“如果那里(原文如此)半径的总和大于它们的中心之间的距离,则两个圆圈重叠。因此,毕达哥拉斯在以下情况下发生碰撞:
(cx1-cx2)2 +(cy1-cy2)2&lt; (R1 + R2)2"
请参阅此答案脚下的"Bounding Circles" section of this link和第二个链接。
评论代码:
// Get the vector between the two sprite centres
Vector v = this.Position - s2.Position;
// get the radius of a circle that will fit the first sprite
double d1 = Math.Sqrt(_Image.Width * _Image.Width + _Image.Height * _Image.Height)/2;
// get the radius of a circle that will fit the second sprite
double d2 = Math.Sqrt(s2._Image.Width * s2._Image.Width + s2._Image.Height * s2._Image.Height)/2;
// if the distance between the sprites is larger than the radiuses(radii?) of the circles, they do not collide
if (v.Length > d1 + d2)
return false;
注意:您可能需要考虑使用轴向对齐的边界框测试而不是圆圈。如果你有宽度和长度不同的矩形,它将是一个更有效/准确的第一次测试。
第二部分(较慢)
我没有时间检查代码100%,但第二部分 - 确定两个精灵可能在第一步中发生碰撞 - 正在执行更复杂的碰撞测试。它使用精灵的图像源执行每像素碰撞测试 - 特别是它的alpha通道。在游戏中,alpha通道通常用于存储透明度的表示。值越大,图像越不透明(因此0将是100%透明,1.0f将是100%不透明)。
在显示的代码中,如果两个精灵中的像素重叠并且两者都具有>>的alpha值。 0.5f,像素共享相同的空间并表示实体几何,因此发生碰撞。通过这个测试,这意味着在测试碰撞时不会考虑精灵的透明(读取:不可见)部分,因此你可以使用不会在角落碰撞的圆形精灵等。