C#中的游戏编程:精灵碰撞

时间:2010-01-03 18:28:02

标签: c# sprite

我在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;
    }
}

1 个答案:

答案 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,像素共享相同的空间并表示实体几何,因此发生碰撞。通过这个测试,这意味着在测试碰撞时不会考虑精灵的透明(读取:不可见)部分,因此你可以使用不会在角落碰撞的圆形精灵等。

这是a link that covers this in a bit more detail