Xna 如何在旋转的矩形上执行剪裁?

Xna 如何在旋转的矩形上执行剪裁?,xna,Xna,所以我有这个小组课。这有点像一个窗口,可以调整大小、关闭、添加按钮、滑块等。如果你们还记得的话,很像Morrowind中的状态屏幕。我想要的行为是,当精灵在面板的边界之外时,它不会被绘制,如果它部分在外部,则只绘制内部的部分。 所以它现在要做的是首先得到一个代表面板边界的矩形和一个精灵矩形,它找到两者之间的相交矩形,然后将该相交转换为精灵矩形的局部坐标,并将其用于源矩形。它是有效的,虽然我觉得代码很聪明,但我无法摆脱有更好的方法来实现这一点的感觉。此外,在这种设置下,我不能为我的2D相机使用全局

所以我有这个小组课。这有点像一个窗口,可以调整大小、关闭、添加按钮、滑块等。如果你们还记得的话,很像Morrowind中的状态屏幕。我想要的行为是,当精灵在面板的边界之外时,它不会被绘制,如果它部分在外部,则只绘制内部的部分。 所以它现在要做的是首先得到一个代表面板边界的矩形和一个精灵矩形,它找到两者之间的相交矩形,然后将该相交转换为精灵矩形的局部坐标,并将其用于源矩形。它是有效的,虽然我觉得代码很聪明,但我无法摆脱有更好的方法来实现这一点的感觉。此外,在这种设置下,我不能为我的2D相机使用全局变换矩阵,“世界”中的所有东西都必须通过相机参数进行绘制。不管怎样,这是我的代码:
对于交叉口:

     public static Rectangle? Intersection(Rectangle rectangle1, Rectangle rectangle2)
     {
        if (rectangle1.Intersects(rectangle2))
        {
            if (rectangle1.Contains(rectangle2))
            {
                return rectangle2;
            }
            else if (rectangle2.Contains(rectangle1))
            {
                return rectangle1;
            }
            else
            {
                int x = Math.Max(rectangle1.Left, rectangle2.Left);
                int y = Math.Max(rectangle1.Top, rectangle2.Top);
                int height = Math.Min(rectangle1.Bottom, rectangle2.Bottom) - Math.Max(rectangle1.Top, rectangle2.Top);
                int width = Math.Min(rectangle1.Right, rectangle2.Right) - Math.Max(rectangle1.Left, rectangle2.Left);
                return new Rectangle(x, y, width, height);
            }
        }
        else
        {
            return null;
        }
     }
对于在面板上实际绘制:

    public void DrawOnPanel(IDraw sprite, SpriteBatch spriteBatch)
    {
        Rectangle panelRectangle = new Rectangle(
           (int)_position.X,
           (int)_position.Y,
           _width,
           _height);
        Rectangle drawRectangle = new Rectangle();

        drawRectangle.X = (int)sprite.Position.X;
        drawRectangle.Y = (int)sprite.Position.Y;
        drawRectangle.Width = sprite.Width;
        drawRectangle.Height = sprite.Height;

        if (panelRectangle.Contains(drawRectangle))
        {
            sprite.Draw(
                spriteBatch,
                drawRectangle,
                null);
        }
        else if (Intersection(panelRectangle, drawRectangle) == null)
        {
            return;
        }
        else if (Intersection(panelRectangle, drawRectangle).HasValue)
        {
            Rectangle intersection = Intersection(panelRectangle, drawRectangle).Value;

            if (Intersection(panelRectangle, drawRectangle) == drawRectangle)
            {
                sprite.Draw(spriteBatch, intersection, intersection);
            }
            else
            {
                sprite.Draw(
                    spriteBatch,
                    intersection,
                    new Rectangle(
                        intersection.X - drawRectangle.X,
                        intersection.Y - drawRectangle.Y,
                        intersection.Width,
                        intersection.Height));
            }
        }
    }
所以我想我的问题是,有没有更好的方法


更新:刚刚发现了剪刀矩形属性。这似乎是一种体面的方式;它需要生成一个光栅化状态对象并将其传递到spritebatch.Begin重载中,该重载接受该对象。看来这可能是最好的选择。还有一个视口,我显然可以改变它。想法?:)

有几种方法可以将绘图限制在屏幕的一部分。如果该区域是矩形的(这里似乎就是这种情况),则可以将视口(请参见GraphicsDevice)设置为面板的曲面


对于非矩形区域,可以使用模具缓冲区或使用深度缓冲区的一些技巧。在模具缓冲区或深度缓冲区中绘制曲面形状,将渲染状态设置为仅绘制位于刚在模具/深度缓冲区中渲染的形状中的像素,最后渲染精灵。

一种方法是简单的逐像素碰撞。虽然这是一个坏主意,如果精灵是大的或众多的,这可以是一个非常简单和快速的方式来完成工作与小精灵。首先,对面板执行边界圆或边界正方形碰撞检查,以查看是否需要进行逐像素检测

然后,创建一个contains方法,该方法检查精灵的位置、比例和旋转是否将其放置在面板内部,以至于它必须完全被面板包围,因此在这种情况下不需要每像素碰撞。只需创建一个具有精灵对角线长度的宽度和高度的边界正方形,并检查是否与该正方形发生碰撞,就可以很容易地做到这一点

最后,如果这两个都失败了,我们必须进行逐像素碰撞。检查精灵中的每个像素,看看它是否在面板的范围内。如果未设置,则将像素的alpha值设置为0


就这样

我建议你在你的问题中使用一个更明确的表述,类似于“如何在旋转的矩形上执行剪切?”之类的东西。哦,哇,我甚至没有想到旋转。谢谢