C# XNA二维框轮廓/边界框?

C# XNA二维框轮廓/边界框?,c#,xna,2d,C#,Xna,2d,如何计算精灵的最远边缘以创建 有原点的变形精灵周围的矩形轮廓 我想实现这样的目标 其中,红色框为轮廓,黑色框为轮廓 变形精灵。长方体需要基于角点展开-仅此而已 一个包围盒真的 我试过各种类似的方程来求一个物体的坐标 变形精灵: Transformed.X = pos.X * (float)Math.Cos(angle) - pos.Y * (float)Math.Sin(angle); Transformed.Y = pos.X * (float)Math.Sin(angle) + pos.Y

如何计算精灵的最远边缘以创建 有原点的变形精灵周围的矩形轮廓

我想实现这样的目标 其中,红色框为轮廓,黑色框为轮廓 变形精灵。长方体需要基于角点展开-仅此而已 一个包围盒真的

我试过各种类似的方程来求一个物体的坐标 变形精灵:

Transformed.X = pos.X * (float)Math.Cos(angle) - pos.Y * (float)Math.Sin(angle);
Transformed.Y = pos.X * (float)Math.Sin(angle) + pos.Y * (float)Math.Cos(angle);
但我似乎不能让它工作。有什么办法可以做到这一点吗

任何帮助都将不胜感激

胡安

多亏了曾乔维,我才得以解决我的问题。以下是我使用的代码:

起始变量

Vector2 TransformPos = Vector2.Zero;
Vector2 TransformPos2 = Vector2.Zero;
float[] px = new float[2];
float[] py = new float[2];
float[] pxl = new float[2];
float[] pyl = new float[2];
float ox;
float oy;
更新方法

    // Vars
    ox = pos.X;
    oy = pos.Y;

    // top left
    pxl[0] = pos.X - Origin.X;
    pyl[0] = pos.Y - Origin.Y;
    // bottom left
    pxl[1] = pos.X - Origin.X;
    pyl[1] = pos.Y + Origin.Y;
    // top right
    px[0] = pos.X + Origin.X;
    py[0] = pos.Y - Origin.Y;
    // bottom right
    px[1] = pos.X + Origin.X;
    py[1] = pos.Y + Origin.Y;

    if (rot <= MathHelper.ToRadians(90) && rot >= MathHelper.ToRadians(0))
    {
        TransformPos.X = (float)Math.Cos(rot) * (pxl.Min() - ox) - (float)Math.Sin(rot) * (pyl.Max() - oy) + ox;
        TransformPos.Y = (float)Math.Sin(rot) * (pxl.Min() - ox) + (float)Math.Cos(rot) * (pyl.Min() - oy) + oy;
        TransformPos2.X = (float)Math.Cos(rot) * (px.Max() - ox) - (float)Math.Sin(rot) * (py.Min() - oy) + ox;
        TransformPos2.Y = (float)Math.Sin(rot) * (px.Max() - ox) + (float)Math.Cos(rot) * (py.Max() - oy) + oy;
    }
    else
    if (rot <= MathHelper.ToRadians(270) && rot >= MathHelper.ToRadians(180))
    {
        TransformPos2.X = (float)Math.Cos(rot) * (pxl.Min() - ox) - (float)Math.Sin(rot) * (pyl.Max() - oy) + ox;
        TransformPos2.Y = (float)Math.Sin(rot) * (pxl.Min() - ox) + (float)Math.Cos(rot) * (pyl.Min() - oy) + oy;
        TransformPos.X = (float)Math.Cos(rot) * (px.Max() - ox) - (float)Math.Sin(rot) * (py.Min() - oy) + ox;
        TransformPos.Y = (float)Math.Sin(rot) * (px.Max() - ox) + (float)Math.Cos(rot) * (py.Max() - oy) + oy;
    }
    else
    if (rot <= MathHelper.ToRadians(180) && rot >= MathHelper.ToRadians(90))
    {
        TransformPos2.X = (float)Math.Cos(rot) * (pxl.Max() - ox) - (float)Math.Sin(rot) * (pyl.Min() - oy) + ox;
        TransformPos.Y = (float)Math.Sin(rot) * (pxl.Max() - ox) + (float)Math.Cos(rot) * (pyl.Max() - oy) + oy;

        TransformPos.X = (float)Math.Cos(rot) * (px.Min() - ox) - (float)Math.Sin(rot) * (py.Max() - oy) + ox;
        TransformPos2.Y = (float)Math.Sin(rot) * (px.Min() - ox) + (float)Math.Cos(rot) * (py.Min() - oy) + oy;
    }
    else
    if (rot <= MathHelper.ToRadians(360) && rot >= MathHelper.ToRadians(270))
    {
        TransformPos.X = (float)Math.Cos(rot) * (pxl.Max() - ox) - (float)Math.Sin(rot) * (pyl.Min() - oy) + ox;
        TransformPos2.Y = (float)Math.Sin(rot) * (pxl.Max() - ox) + (float)Math.Cos(rot) * (pyl.Max() - oy) + oy;

        TransformPos2.X = (float)Math.Cos(rot) * (px.Min() - ox) - (float)Math.Sin(rot) * (py.Max() - oy) + ox;
        TransformPos.Y = (float)Math.Sin(rot) * (px.Min() - ox) + (float)Math.Cos(rot) * (py.Min() - oy) + oy; 
    }


Transform = new Rectangle((int)TransformPos.X, (int)TransformPos.Y, (int)TransformPos2.X - (int)TransformPos.X, (int)TransformPos2.Y - (int)TransformPos.Y);
它根据精灵的旋转来查找精灵角点的最大值和最小值,以生成边界框。
代码假设原点是精灵的中间,如果找到未旋转精灵上每个角的位置,然后围绕旋转点旋转它们以找到旋转精灵的每个角,则必须基于原点更改代码。

然后您可以找到这些点的最大和最小x和y值。
minX和minY将是边界矩形的左上角,maxX和maxY将是边界矩形的右下角。

大约一年前,我曾尝试在一辆汽车上的旋转矩形物体上安装碰撞器,结果发现是空的。虽然可以旋转精灵,但不能围绕其旋转矩形以进行碰撞

最后,我在我的物体上画了一个圆圈,这个圆圈完成了任务,但并不完美。我读到的其他解决方案包括把三个圆圈放在一个矩形物体前面,一个在中间,一个在后面。报道很好,但数学比我想要的要多

作为最后的手段,是否有一个不旋转的矩形可以覆盖你的精灵所有可能的旋转

这些都不是完美的,但它们可能足够接近

干杯,
A.

我知道这个问题有点老了,但是如果有人对一个简单的单游戏解决方案感兴趣,这个解决方案也考虑了纹理大小,因为在单游戏中,origin基于纹理大小,而不是dest rect,这里有一个:

    /// <summary>
    /// Rotate a vector around pivot.
    /// </summary>
    /// <param name="vec">Vector to rotate.</param>
    /// <param name="pivot">Point to rotate around.</param>
    /// <param name="theta">Rotation angle.</param>
    /// <returns>Rotated vector.</returns>
    public static Vector2 RotateAround(Vector2 vec, Vector2 pivot, float theta)
    {
        return new Vector2(
            (float)(System.Math.Cos(theta) * (vec.X - pivot.X) - System.Math.Sin(theta) * (vec.Y - pivot.Y) + pivot.X),
            (float)(System.Math.Sin(theta) * (vec.X - pivot.X) + System.Math.Cos(theta) * (vec.Y - pivot.Y) + pivot.Y));
    }

    /// <summary>
    /// Get rectangle and rotation (angle + origin) and calculate bounding box containing the rotated rect.
    /// </summary>
    /// <param name="rect">Rectangle to rotate.</param>
    /// <param name="rotation">Rotation angle.</param>
    /// <param name="origin">Rotation origin.</param>
    /// <param name="textureSize">In MonoGame origin is relative to source texture size, not dest rect. 
    /// So this param specify source texture size.</param>
    /// <returns>Rotated rectangle bounding box.</returns>
    public static Rectangle GetRotatedBoundingBox(Rectangle rect, float rotation, Vector2 origin, Rectangle textureSize)
    {
        // fix origin to be relative to rect location + fix it to be relative to rect size rather then texture size
        var originSize = ((origin / textureSize.Size.ToVector2()) * rect.Size.ToVector2());
        var convertedOrigin = rect.Location.ToVector2() + originSize;

        // calculate top-left rotated corner
        var topLeft = RotateAround(rect.Location.ToVector2(), convertedOrigin, rotation);

        // calculate rest of rotated corners
        Vector2[] corners = new Vector2[] {
            RotateAround(new Vector2(rect.Left, rect.Bottom), convertedOrigin, rotation),
            RotateAround(new Vector2(rect.Right, rect.Bottom), convertedOrigin, rotation),
            RotateAround(new Vector2(rect.Right, rect.Top), convertedOrigin, rotation)
        };

        // find min and max points
        Vector2 min, max;
        min = max = topLeft;
        foreach (var corner in corners)
        {
            if (corner.X < min.X) min.X = corner.X;
            if (corner.Y < min.Y) min.Y = corner.Y;
            if (corner.X > max.X) max.X = corner.X;
            if (corner.Y > max.Y) max.Y = corner.Y;
        }

        // create rectangle from min-max and return it
        return new Rectangle(min.ToPoint() - originSize.ToPoint(), (max - min).ToPoint());
    }

请添加langage Tag谢谢你的回复,它帮助我找到了每个角的位置:但我在制作矩形时遇到了麻烦。。我想要这样的东西,矩形基于角点展开,我怎样才能做到这一点?
        // update rotation and start batch
        rotation += 0.01f;
        spriteBatch.Begin();

        // dest and origin values (play with these to see different results)
        var dest = new Rectangle(new Point(200, 200), new Point(100, 200));
        var origin = new Vector2(15, 200);

        // draw sprite
        spriteBatch.Draw(rectTexture, dest, null, Color.White, rotation, origin, SpriteEffects.None, 0f);

        // draw sprite bounding box (in my case I put the functions under Source.Graphics.Utils static class)
        var boundingBox = Source.Graphics.Utils.GetRotatedBoundingBox(dest, rotation, origin, rectTexture.Bounds);
        spriteBatch.Draw(rectTexture, boundingBox, Color.Red);

        // end batch
        spriteBatch.End();