1

我有一个关于 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;
    }
}
4

1 回答 1

3

这有点令人费解。两部分:

第一部分(简单快速)

第一部分(涉及 v, d1 + d2)可能令人困惑,因为不是使用框进行碰撞测试,而是使用图像的尺寸来构建边界圆。然后使用这些边界圆进行简单的碰撞测试。这是消除明显不碰撞的精灵的“快速和肮脏”测试。

“如果有(原文如此)半径之和大于它们中心之间的距离,则两个圆重叠。因此,毕达哥拉斯在以下情况下会发生碰撞:

(cx1-cx2)2 + (cy1-cy2)2 < (r1+r2)2"

请参阅此链接的“边界圈”部分和此答案脚下的第二个链接。

注释代码:

// 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% 不透明)。

In the code shown, if the pixels in both sprites are overlapping and both have alpha values of > 0.5f, the pixels are sharing the same space and represent solid geometry and are thus colliding. By doing this test, it means that transparent (read: invisible) parts of the sprite will not be considered when testing for collisions, so you can have circular sprites that do not collide at the corners etc.

Here's a link that covers this in a bit more detail.

于 2010-01-03T19:21:00.423 回答