C# 创建圆角矩形纹理2D

C# 创建圆角矩形纹理2D,c#,xna,xna-4.0,C#,Xna,Xna 4.0,我正在构建一个带有对话框的游戏,我希望能够以一种非常类似于最终幻想系列(think like)的风格,按程序为对话框生成纹理。以下是我目前掌握的代码片段: public class DialogBox { public Rectangle BoxArea { get; set; } public List<Color> BoxColors { get; set; } public List<Color> BorderColors { get; se

我正在构建一个带有对话框的游戏,我希望能够以一种非常类似于最终幻想系列(think like)的风格,按程序为对话框生成纹理。以下是我目前掌握的代码片段:

public class DialogBox
{
    public Rectangle BoxArea { get; set; }
    public List<Color> BoxColors { get; set; }
    public List<Color> BorderColors { get; set; }
    public int BorderThickness { get; set; }
    public int BorderRadius { get; set; }
    private Texture2D texture;

    public void CreateBackdrop(ref GraphicsDevice graphics)
    {
        texture = new Texture2D(graphics,
                                BoxArea.Width,
                                BoxArea.Height,
                                true,
                                SurfaceFormat.Color);
        Color[] color = new Color[texture.Width * texture.Height];

        for(int x = 0; x < texture.Width; x++)
        {
            for(int y = 0; y < texture.Height; y++)
            {
                switch(BoxColors.Count)
                {
                    case 4:
                        Color leftColor = Color.Lerp(BoxColor[0], BoxColor[1], (y / (texture.Height - 1)));
                        Color rightColor = Color.Lerp(BoxColor[2], BoxColor[3], (y / (texture.Height - 1)));
                        color[x + y * texture.Width] = Color.Lerp(leftColor,
                                                                  RightColor,
                                                                  (x / (texture.Width - 1)));
                        break;
                    case 2:
                        color[x + y * texture.Width] = Color.Lerp(BoxColors[0],
                                                                  BoxColors[1],
                                                                  (x / (texture.Width - 1)));
                        break;
                    default:
                        color[x + y * texture.Width];
                        break;
                 }
            }
        }
        texture.SetData<Color>(color);
    }
}
公共类对话框
{
公共矩形框区域{get;set;}
公共列表框颜色{get;set;}
公共列表边框颜色{get;set;}
公共int边界厚度{get;set;}
公共整数边界半径{get;set;}
私有纹理2D纹理;
公共空白CreateBackup(参考图形设备图形)
{
纹理=新纹理2D(图形,
面积,宽度,
面积,高度,
是的,
表面形态(颜色);
颜色[]颜色=新颜色[texture.Width*texture.Height];
对于(int x=0;x
我正在寻找的是以下内容:

  • 四向渐变色(已实现)
  • 圆角矩形
  • 梯度边界
任何帮助都将不胜感激


我通过算出了矩形。

我算出了我遇到的问题;计算角弧。我发现,人们可以用与点的距离来理解绘制边界的方法,而不是用数学来计算圆内的点。下面我发布了生成圆角矩形的代码

public Texture2D CreateRoundedRectangleTexture(GraphicsDevice graphics, int width, int height, int borderThickness, int borderRadius, int borderShadow, List<Color> backgroundColors, List<Color> borderColors, float initialShadowIntensity, float finalShadowIntensity)
{
    if (backgroundColors == null || backgroundColors.Count == 0) throw new ArgumentException("Must define at least one background color (up to four).");
    if (borderColors == null || borderColors.Count == 0) throw new ArgumentException("Must define at least one border color (up to three).");
    if (borderRadius < 1) throw new ArgumentException("Must define a border radius (rounds off edges).");
    if (borderThickness < 1) throw new ArgumentException("Must define border thikness.");
    if (borderThickness + borderRadius > height / 2 || borderThickness + borderRadius > width / 2) throw new ArgumentException("Border will be too thick and/or rounded to fit on the texture.");
    if (borderShadow > borderRadius) throw new ArgumentException("Border shadow must be lesser in magnitude than the border radius (suggeted: shadow <= 0.25 * radius).");

    Texture2D texture = new Texture2D(graphics, width, height, false, SurfaceFormat.Color);
    Color[] color = new Color[width * height];

    for (int x = 0; x < texture.Width; x++)
    {
        for (int y = 0; y < texture.Height; y++)
        {
            switch (backgroundColors.Count)
            {
                case 4:
                    Color leftColor0 = Color.Lerp(backgroundColors[0], backgroundColors[1], ((float)y / (width - 1)));
                    Color rightColor0 = Color.Lerp(backgroundColors[2], backgroundColors[3], ((float)y / (height - 1)));
                    color[x + width * y] = Color.Lerp(leftColor0, rightColor0, ((float)x / (width - 1)));
                    break;
                case 3:
                    Color leftColor1 = Color.Lerp(backgroundColors[0], backgroundColors[1], ((float)y / (width - 1)));
                    Color rightColor1 = Color.Lerp(backgroundColors[1], backgroundColors[2], ((float)y / (height - 1)));
                    color[x + width * y] = Color.Lerp(leftColor1, rightColor1, ((float)x / (width - 1)));
                    break;
                case 2:
                    color[x + width * y] = Color.Lerp(backgroundColors[0], backgroundColors[1], ((float)x / (width - 1)));
                    break;
                default:
                    color[x + width * y] = backgroundColors[0];
                    break;
            }

            color[x + width * y] = ColorBorder(x, y, width, height, borderThickness, borderRadius, borderShadow, color[x + width * y], borderColors, initialShadowIntensity, finalShadowIntensity);
        }
    }

    texture.SetData<Color>(color);
    return texture;
}

private Color ColorBorder(int x, int y, int width, int height, int borderThickness, int borderRadius, int borderShadow, Color initialColor, List<Color> borderColors, float initialShadowIntensity, float finalShadowIntensity)
{
    Rectangle internalRectangle = new Rectangle((borderThickness + borderRadius), (borderThickness + borderRadius), width - 2 * (borderThickness + borderRadius), height - 2 * (borderThickness + borderRadius));

    if (internalRectangle.Contains(x, y)) return initialColor;

    Vector2 origin = Vector2.Zero;
    Vector2 point = new Vector2(x, y);

    if (x < borderThickness + borderRadius)
    {
        if (y < borderRadius + borderThickness)
            origin = new Vector2(borderRadius + borderThickness, borderRadius + borderThickness);
        else if (y > height - (borderRadius + borderThickness))
            origin = new Vector2(borderRadius + borderThickness, height - (borderRadius + borderThickness));
        else
            origin = new Vector2(borderRadius + borderThickness, y);
    }
    else if (x > width - (borderRadius + borderThickness))
    {
        if (y < borderRadius + borderThickness)
            origin = new Vector2(width - (borderRadius + borderThickness), borderRadius + borderThickness);
        else if (y > height - (borderRadius + borderThickness))
            origin = new Vector2(width - (borderRadius + borderThickness), height - (borderRadius + borderThickness));
        else
            origin = new Vector2(width - (borderRadius + borderThickness), y);
    }
    else
    {
        if (y < borderRadius + borderThickness)
            origin = new Vector2(x, borderRadius + borderThickness);
        else if (y > height - (borderRadius + borderThickness))
            origin = new Vector2(x, height - (borderRadius + borderThickness));
    }

    if (!origin.Equals(Vector2.Zero))
    {
        float distance = Vector2.Distance(point, origin);

        if (distance > borderRadius + borderThickness + 1)
        {
            return Color.Transparent;
        }
        else if (distance > borderRadius + 1)
        {
            if (borderColors.Count > 2)
            {
                float modNum = distance - borderRadius;

                if (modNum < borderThickness / 2)
                {
                    return Color.Lerp(borderColors[2], borderColors[1], (float)((modNum) / (borderThickness / 2.0)));
                }
                else
                {
                    return Color.Lerp(borderColors[1], borderColors[0], (float)((modNum - (borderThickness / 2.0)) / (borderThickness / 2.0)));
                }
            }


            if (borderColors.Count > 0)
                return borderColors[0];
        }
        else if (distance > borderRadius - borderShadow + 1)
        {
            float mod = (distance - (borderRadius - borderShadow)) / borderShadow;
            float shadowDiff = initialShadowIntensity - finalShadowIntensity;
            return DarkenColor(initialColor, ((shadowDiff * mod) + finalShadowIntensity));
        }
    }

    return initialColor;
}

private Color DarkenColor(Color color, float shadowIntensity)
{
    return Color.Lerp(color, Color.Black, shadowIntensity);
}
public Texture2D CreateRoundedRectangleTexture(图形设备图形、int-width、int-height、int-borderThickness、int-borderRadius、int-borderShadow、List BackgroundColor、List-BorderColor、float-initialShadowIntensity、float-finalShadowIntensity)
{
if(backgroundColors==null | | backgroundColors.Count==0)抛出新的ArgumentException(“必须定义至少一种背景色(最多四种)”;
if(borderColors==null | | borderColors.Count==0)抛出新的ArgumentException(“必须定义至少一种边框颜色(最多三种)”;
如果(borderRadius<1)抛出新的ArgumentException(“必须定义边界半径(舍入边)”;
如果(borderThickness<1)抛出新的ArgumentException(“必须定义边框厚度”);
如果(borderThickness+borderRadius>height/2 | | borderThickness+borderRadius>width/2)抛出新的ArgumentException(“边框太厚和/或太圆,无法适应纹理”);

如果(borderShadow>borderRadius)抛出新的ArgumentException(“borderShadow”的大小必须小于borderRadius(suggeted:shadow)您知道称为“缩放9栅格”的技术吗"?@Goose我知道技术是存在的,但我原本认为,因为我会动态地处理这一切,这对我来说不太合适。我会看看我拥有什么,看看我是否能将这些知识整合到我正在做的事情中。你是对的。如果你想动态地创建形状,这没有多大意义。我建议将其作为动态创建形状的替代方法。Scale9grid允许您使用纹理来创建任意大小的窗口。这取决于您的目标是什么。@Goose我的目标是能够在运行时按程序创建这些纹理。老实说,这并不需要任何具有艺术技能的人,但对于我们这些缺乏最后,它将为我们提供一种为对话框创建简单圆角矩形的方法。