Sprite Border

How to draw borders on a Texture2d sprite?

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

But when using it, the loaded sprite is not visible
2021-11-04_125420
This is the result without using the CreateBorder method
2021-11-04_125446

Hello,

I think your problem is probably due to the layerdepth of your texture2D and your border being the same.
Your layerdepth can be set in the spritebatch draw method.

If you don’t mind adding extra package, you should check monogame extended. It provide additional method to the spirebatch. There is one called draw rectangle that can interest you.

2 Likes

I think this is your problem. For anything that’s not where you want to set your border, you’re resetting the colour to transparent.

If you’re interested in an alternative, you might consider just not modifying your sprite at all here. Design your border as a separate sprite, draw it, then draw your sprite (with transparency) over top. Sure it’s two draws instead of one but unless you’re drawing a tooooooon of these, it’s not really going to matter and will give you the flexibility to design your border sprite however you like.

1 Like

Thanks, I thought about it, but I was looking for a smarter way not to draw two drawings

The issue is likely that you’re expecting the call to texture.SetData to merge the color array with the existing texture, but it instead replaces the data.

If you add the following line at the top then the color array will be filled with the existing texture data first:

Color[] colors = new Color[texture.Width * texture.Height];
texture.GetData(colors);

Then if you remove the line which sets non border areas with Color.Transparent then only the border pixels will be modified.

The problem is that you are doing it ass-backwards. Why do you need to modify the texture directly? Why not just draw the border on top of that sprite? It’s gonna be faster and much easier. Even if you NEED to draw on a texture, use RenderTarget and draw on it. Direct texture data access was not made for whatever you’re trying to achieve here.

Actually this is a good point. It gives you the flexibility of having two sprites we talked about before, but also eliminates the need to have two draws (if that’s something that concerns you).

Draw both textures to a rendertarget, then use that as your texture :slight_smile:

I don’t know a ton about MonoGame yet. I came here looking how to add a border to a rectangle dawn here. basically I am trying to replicate a simple experiment I’ve done in Processing, where I am using a Texture2d and want the visual equivalent of stroke and fill.

As convoluted as this seems, the extension method here almost suited my purposes, except I had the same problem. The original color being overwritten.

Anyway, for my purpose I didn’t need the border width, this is just for diagnostic purposes. But I figured out how to preserve the underlying colors, in case this is useful to anybody else.

public static void CreateBorder(this Texture2D texture, int borderWidth, Color borderColor)
{
var colors = new Color[texture.Width * texture.Height];
texture.GetData(colors);
for (var x = 0; x < texture.Width; x++)
for (var y = 0; y < texture.Height; y++)
{
var color = colors[x + y * texture.Width] ;
if (x == 0 || x == texture.Width - 1 || y == 0 || y == texture.Height - 1)
{
color = borderColor;
}
colors[x + y * texture.Width] = color;
}
texture.SetData(colors);
}

2 Likes

I misread this and thought something wasn’t working for you, so I did a little test to see if I could help. From what I could tell everything was actually working fine! I had to re-read your message like 4 times to figure out that you were just posting a helpful tip for folks in the future :stuck_out_tongue:

Quick tip though, if you wrap your code in three ` (back tick, next to 1 on your keyboard) at the start and end it will format it nicely for you. Like this!

```
// some code here
```