【问题标题】:XNA: Collisions between rotating spritesXNA:旋转精灵之间的碰撞
【发布时间】:2016-06-06 16:15:27
【问题描述】:

现在要进行旋转,每个旋转角度都有一个单独的框架,但我更愿意旋转一个图像。我的问题是,如何在 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;
    }

【问题讨论】:

    标签: c# xna collision-detection


    【解决方案1】:

    您应该保持数据不变。您只需修改访问它的方式。

    对于像素完美碰撞检测,基本思想如下:您有两个精灵,分别使用变换矩阵m1m2 渲染。现在迭代精灵 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;
    

    【讨论】:

      猜你喜欢
      • 2021-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多