2013-06-20 66 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