2013-06-20 105 views
3

我正在构建一个带有对话框的游戏,我希望能够以与最终幻想系列非常类似的风格(如Final Fantasy VII)的方式为程序框生成纹理。这里是我到目前为止的代码片段:创建圆角矩形纹理2D

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); 
    } 
} 

我所寻找的是以下几点:

  • 4路渐变色(实现)
  • 圆角矩形
  • 边框渐变

任何帮助将不胜感激。

我想通过this question的矩形。

+0

你知道所谓的“缩放9网格”技术的? http://despre.md/ideapress/what-is-scale9grid/ – Goose

+0

@Goose我明白,技术存在,但我原本以为我会认为,因为我会动态处理这一切,这对我来说不会奏效。我会看看我有什么,看看我能否将这些知识融入我所做的事情中。 –

+0

你是对的。如果您想要动态创建形状,没有多大意义。我建议它仅作为动态创建形状的替代方法。 Scale9grid允许你使用纹理来制作任意大小的窗口。这取决于你的目标是什么。 – Goose

回答

5

我想通了,我有什么麻烦;计算拐角弧。我想到的是,人们可以用一个点的距离来理解绘制边界的方式,而不是用数学来计算圆内的点。下面我发布了代码来生成圆角矩形。

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); 
} 

与所有上面的代码中,这是结果: Rounded Texture in Action