【问题标题】:How to draw the border of a square?如何绘制正方形的边框?
【发布时间】:2012-12-15 16:25:02
【问题描述】:

我正在使用 monogame(它使用 XNA API 接口)来编写我的游戏。到目前为止它很棒,但我在一些应该很简单的事情上遇到了障碍。

我需要画一个二维正方形。但我只想要边框(无填充)。

我已经看到了很多例子来展示如何做一个填充的。但是没有一个只会显示边框。

我想我可以制作一张图片并使用它。但我怀疑它会很好地调整大小。

【问题讨论】:

    标签: c# xna rectangles monogame


    【解决方案1】:

    也许您可以使用 1x1 像素纹理来绘制单个边缘和精灵批次。在 XNA 中,您可以这样做:

    class RectangleSprite
    {
        static Texture2D _pointTexture;
        public static void DrawRectangle(SpriteBatch spriteBatch, Rectangle rectangle, Color color, int lineWidth)
        {
            if (_pointTexture == null)
            {
                _pointTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1);
                _pointTexture.SetData<Color>(new Color[]{Color.White});
            }
    
            spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y, lineWidth, rectangle.Height + lineWidth), color);
            spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y, rectangle.Width + lineWidth, lineWidth), color);
            spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X + rectangle.Width, rectangle.Y, lineWidth, rectangle.Height + lineWidth), color);
            spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y + rectangle.Height, rectangle.Width + lineWidth, lineWidth), color);
        }     
    }
    

    生成的绘图将比传递的矩形宽(和高)lineWidth 个像素。

    上面是用这段代码绘制的:

    sb.Begin(); //spritebatch
    RectangleSprite.DrawRectangle(sb, new Rectangle(10, 10, 50, 100), Color.Red, 1);
    RectangleSprite.DrawRectangle(sb, new Rectangle(30, 20, 80, 15), Color.Green, 4);
    RectangleSprite.DrawRectangle(sb, new Rectangle(70, 40, 40, 70), Color.Blue, 6);
    sb.End();
    

    【讨论】:

      【解决方案2】:

      我刚刚以这种方式为Texture2D创建了一个扩展方法:

      static class Utilities {
          public static void CreateBorder( this Texture2D texture,  int borderWidth, Color borderColor ) {
              Color[] colors = new Color[ texture.Width * texture.Height ];
      
              for ( int x = 0; x < texture.Width; x++ ) {
                  for ( int y = 0; y < texture.Height; y++ ) {
                      bool colored = false;
                      for ( int i = 0; i <= borderWidth; i++ ) {
                          if ( x == i || y == i || x == texture.Width - 1 - i || y == texture.Height - 1 - i ) {
                              colors[x + y * texture.Width] = borderColor;
                              colored = true;
                              break;
                          }
                      }
      
                      if(colored == false)
                          colors[ x + y * texture.Width ] = Color.Transparent;
                  }
              }
      
              texture.SetData( colors );
          }
      }
      

      然后我测试了它:

      //...
      
      protected override void Initialize( ) {
         // TODO: Add your initialization logic here
         square = new Texture2D( GraphicsDevice, 100, 100 );
         square.CreateBorder( 5, Color.Red );
      
         base.Initialize( );
      }
      
      //...
      
      protected override void Draw( GameTime gameTime ) {
         GraphicsDevice.Clear( Color.CornflowerBlue );
      
         // TODO: Add your drawing code here
         spriteBatch.Begin( );
         spriteBatch.Draw( square, new Vector2( 0.0f, 0.0f ), Color.White );
         spriteBatch.End( );
      
         base.Draw( gameTime );
      }
      

      结果如下:

      【讨论】:

      • 这确实有效,但它覆盖了我的纹理绘图。所以 +1 因为它有效,但我试图找到可以在我的纹理周围/上方绘制一个框的东西,这样我就可以看到我的边界在哪里。
      • 为了避免覆盖纹理,只需先绘制正方形。它应该工作,让我知道。
      • @Fuex Bat-Signal:Game Dev SE seems to have 上的 Sam 拿起了你的代码,发现了一个问题。我还没有安装 XNA,所以我不能玩它,但如果你有时间,你能看一下吗?
      • @Anko 像素颜色寻址不好,应该是 x + y*Width。它适用于正方形,但不适用于矩形
      • @Blau 对于正方形,它不会产生问题,因为高度和宽度相等。虽然,把它固定为一个矩形,谢谢。
      【解决方案3】:

      我创建了一个用于绘制图元的实用程序类。您可能会发现它很有用

      static public class PrimiviteDrawing
      {
          static public void DrawRectangle(Texture2D whitePixel, SpriteBatch batch, Rectangle area, int width, Color color)
          {
              batch.Draw(whitePixel, new Rectangle(area.X, area.Y, area.Width, width), color);
              batch.Draw(whitePixel, new Rectangle(area.X, area.Y, width, area.Height), color);
              batch.Draw(whitePixel, new Rectangle(area.X + area.Width - width, area.Y, width, area.Height), color);
              batch.Draw(whitePixel, new Rectangle(area.X, area.Y + area.Height - width, area.Width, width), color);
          }
          static public void DrawRectangle(Texture2D whitePixel, SpriteBatch batch, Rectangle area)
          {
              DrawRectangle(whitePixel, batch, area, 1, Color.White);
          }
          public static void DrawCircle(Texture2D whitePixel, SpriteBatch spritbatch, IntegerVector2 center, float radius, Color color, int lineWidth = 2, int segments = 16)
          {
              Vector2[] vertex = new Vector2[segments];
      
              double increment = Math.PI * 2.0 / segments;
              double theta = 0.0;
      
              for (int i = 0; i < segments; i++)
              {
                  vertex[i] = center.ToVector2() + radius * new Vector2((float)Math.Cos(theta), (float)Math.Sin(theta));
                  theta += increment;
              }
      
              DrawPolygon(whitePixel, spritbatch, vertex, segments, color, lineWidth);
          }
          public static void DrawPolygon(Texture2D whitePixel, SpriteBatch spriteBatch, Vector2[] vertex, int count, Color color, int lineWidth)
          {
              if (count > 0)
              {
                  for (int i = 0; i < count - 1; i++)
                  {
                      DrawLineSegment(whitePixel, spriteBatch, vertex[i], vertex[i + 1], color, lineWidth);
                  }
                  DrawLineSegment(whitePixel, spriteBatch, vertex[count - 1], vertex[0], color, lineWidth);
              }
          }
          public static void DrawLineSegment(Texture2D whitePixel, SpriteBatch spriteBatch, Vector2 point1, Vector2 point2, Color color, int lineWidth)
          {
              float angle = (float)Math.Atan2(point2.Y - point1.Y, point2.X - point1.X);
              float length = Vector2.Distance(point1, point2);
      
              spriteBatch.Draw(whitePixel, point1, null, color,
              angle, Vector2.Zero, new Vector2(length, lineWidth),
              SpriteEffects.None, 0f);
          }
      }
      

      【讨论】:

        【解决方案4】:

        我会这样做:

            private void OutLine_Box(SpriteBatch sbatch, Rectangle rect)
            {
                List<Vector2> pixels = new List<Vector2>();
                for (int x = rect.X; x < rect.X + rect.Width; x++)
                {
                    for (int y = rect.Y; y < rect.Y + rect.Height; y++)
                    {
                        if (y == rect.Y || y == rect.Y + rect.Height - 1)
                            pixels.Add(new Vector2(x, y));
                        if (x == rect.X || x == rect.X + rect.Width - 1)
                            pixels.Add(new Vector2(x, y));
                    }
                }
        
                foreach (Vector2 v in pixels)
                    sbatch.Draw(PixelTexture, v, OutLineColor);
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-11-24
          • 1970-01-01
          • 1970-01-01
          • 2022-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多