Nez 圆角矩形边框组件源码实现
Nez 圆角矩形边框组件源码实现
一、效果
图片如下

对应使用该组件的场景如下:
using FanaticGene.Test.Components;
using Microsoft.Xna.Framework;
using Nez;
namespace FanaticGene.Test.Scenes;
public class TestScene : Scene
{
public override void Initialize()
{
base.Initialize();
ClearColor = Color.White;
var entity = CreateEntity("111");
entity
.AddComponent<BorderPrototypeSpriteComponent>()
.SetHeight(300)
.SetWidth(200)
.SetBorderThickness(3)
.SetBorderColor(Color.Red)
.SetColor(Color.Black);
entity.SetPosition(new Vector2(400, 300));
}
}
二、代码
using Microsoft.Xna.Framework;
using Nez;
using Nez.Sprites;
using Microsoft.Xna.Framework.Graphics;
using Nez.Textures;
namespace FanaticGene.Test.Components;
public class BorderPrototypeSpriteComponent : SpriteRenderer
{
public override float Width => _width;
public override float Height => _height;
public int Radius => _radius;
private int _radius = 12;
public Color BorderColor => _borderColor;
private Color _borderColor = Color.Red;
public int BorderThickness => _borderThickness;
private int _borderThickness = 3;
public override RectangleF Bounds
{
get
{
if (_areBoundsDirty)
{
_bounds.CalculateBounds(Entity.Transform.Position, _localOffset, _origin, Entity.Transform.Scale,
Entity.Transform.Rotation, _width, _height);
_areBoundsDirty = false;
}
return _bounds;
}
}
public float SkewTopX;
public float SkewBottomX;
public float SkewLeftY;
public float SkewRightY;
float _width, _height;
public BorderPrototypeSpriteComponent() : this(50, 50)
{
OnPropertyChanged(new Vector2(50, 50));
}
public BorderPrototypeSpriteComponent(float width, float height) : base(Graphics.Instance.PixelTexture)
{
_width = width;
_height = height;
OnPropertyChanged(new Vector2(width, height));
}
/// <summary>
/// sets the width of the sprite
/// </summary>
/// <returns>The width.</returns>
/// <param name="width">Width.</param>
public BorderPrototypeSpriteComponent SetWidth(float width)
{
_width = width;
OnPropertyChanged(new Vector2(_width, _height));
return this;
}
/// <summary>
/// sets the height of the sprite
/// </summary>
/// <returns>The height.</returns>
/// <param name="height">Height.</param>
public BorderPrototypeSpriteComponent SetHeight(float height)
{
_height = height;
OnPropertyChanged(new Vector2(_width, _height));
return this;
}
private void OnPropertyChanged(Vector2 size, bool isForced = false)
{
var width = (int)size.X;
var height = (int)size.Y;
if (isForced == false)
{
if (_sprite.Texture2D.Width == width && _sprite.Texture2D.Height == height) return;
}
var texture2d = new Texture2D(Nez.Core.GraphicsDevice, width, height);
var colors = new Color[width * height];
var radius = _radius;
void SetPoint(Color color, int x, int y)
{
colors[y * width + x] = color;
}
Color GetPoint(int x, int y)
{
return colors[y * width + x];
}
void SetRectangle(Color color, int x, int y, int width, int height)
{
for (int i = 0; i < width; i++)
{
var offsetX = i + x;
for (int j = 0; j < height; j++)
{
var offsetY = j + y;
SetPoint(color, offsetX, offsetY);
}
}
}
//_sprite = new Sprite();
void SetRadius(Color color, int cwidth, int cheight, int startX, int startY, Vector2 center)
{
for (int i = 0; i < cwidth; i++)
{
for (int j = 0; j < cheight; j++)
{
var offsetX = i + startX;
var offsetY = j + startY;
var point = new Vector2(offsetX, offsetY);
var distance = Vector2.Distance(center, point);
if (distance <= radius)
SetPoint(color, offsetX, offsetY);
}
}
}
void SetRadiusBorder(Color color, int cwidth, int cheight, int startX, int startY, Vector2 center)
{
for (int i = 0; i < cwidth; i++)
{
for (int j = 0; j < cheight; j++)
{
var offsetX = i + startX;
var offsetY = j + startY;
var point = new Vector2(offsetX, offsetY);
var distance = Vector2.Distance(center, point);
if (distance <= radius && (radius - distance) <= BorderThickness)
SetPoint(color, offsetX, offsetY);
}
}
}
// 水平
{
var startX = radius;
var startY = 0;
var cwidth = width - 2 * radius;
var cheight = radius;
SetRectangle(Color, startX, startY, cwidth, cheight);
}
// 水平
{
var startX = radius;
var startY = height - radius;
var cwidth = width - 2 * radius;
var cheight = radius;
SetRectangle(Color, startX, startY, cwidth, cheight);
}
// 内容
{
var startX = 0;
var startY = radius;
var cwidth = width;
var cheight = height - 2 * radius;
SetRectangle(Color, startX, startY, cwidth, cheight);
}
// 左上角
{
var startX = 0;
var startY = 0;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(radius, radius);
SetRadius(Color, cwidth, cheight, startX, startY, center);
}
// 右上角
{
var startX = width - radius;
var startY = 0;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(width - radius, radius);
SetRadius(Color, cwidth, cheight, startX, startY, center);
}
// 左下角
{
var startX = 0;
var startY = height - radius;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(radius, height - radius);
SetRadius(Color, cwidth, cheight, startX, startY, center);
}
// 右下角
{
var startX = width - radius;
var startY = height - radius;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(width - radius, height - radius);
SetRadius(Color, cwidth, cheight, startX, startY, center);
}
// 边框
{
var startX = radius;
var startY = 0;
var cwidth = width - 2 * radius;
var cheight = BorderThickness;
SetRectangle(BorderColor, startX, startY, cwidth, cheight);
}
// 边框
{
var startX = radius;
var startY = height - BorderThickness;
var cwidth = width - 2 * radius;
var cheight = BorderThickness;
SetRectangle(BorderColor, startX, startY, cwidth, cheight);
}
// 边框
{
var startX = 0;
var startY = radius;
var cwidth = BorderThickness;
var cheight = height - 2 * radius;
SetRectangle(BorderColor, startX, startY, cwidth, cheight);
}
// 边框
{
var startX = width - BorderThickness;
var startY = radius;
var cwidth = BorderThickness;
var cheight = height - 2 * radius;
SetRectangle(BorderColor, startX, startY, cwidth, cheight);
}
// 左上角
{
var startX = 0;
var startY = 0;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(radius, radius);
SetRadiusBorder(BorderColor, cwidth, cheight, startX, startY, center);
}
// 右上角
{
var startX = width - radius;
var startY = 0;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(width - radius, radius);
SetRadiusBorder(BorderColor, cwidth, cheight, startX, startY, center);
}
// 左下角
{
var startX = 0;
var startY = height - radius;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(radius, height - radius);
SetRadiusBorder(BorderColor, cwidth, cheight, startX, startY, center);
}
// 右下角
{
var startX = width - radius;
var startY = height - radius;
var cwidth = radius;
var cheight = radius;
var center = new Vector2(width - radius, height - radius);
SetRadiusBorder(BorderColor, cwidth, cheight, startX, startY, center);
}
texture2d.SetData(colors);
_sprite = new Sprite(texture2d);
}
/// <summary>
/// sets the skew values for the sprite
/// </summary>
/// <returns>The skew.</returns>
/// <param name="skewTopX">Skew top x.</param>
/// <param name="skewBottomX">Skew bottom x.</param>
/// <param name="skewLeftY">Skew left y.</param>
/// <param name="skewRightY">Skew right y.</param>
public BorderPrototypeSpriteComponent SetSkew(float skewTopX, float skewBottomX, float skewLeftY, float skewRightY)
{
SkewTopX = skewTopX;
SkewBottomX = skewBottomX;
SkewLeftY = skewLeftY;
SkewRightY = skewRightY;
return this;
}
public BorderPrototypeSpriteComponent SetRadius(int radius)
{
_radius = radius;
OnPropertyChanged(new Vector2(_width, _height), true);
return this;
}
public BorderPrototypeSpriteComponent SetBorderColor(Color color)
{
if (color == BorderColor) return this;
_borderColor = color;
OnPropertyChanged(new Vector2(_width, _height), true);
return this;
}
public BorderPrototypeSpriteComponent SetBorderThickness(int value)
{
if (value == BorderThickness) return this;
_borderThickness = value;
OnPropertyChanged(new Vector2(_width, _height), true);
return this;
}
public new RenderableComponent SetColor(Color color)
{
if (color == Color) return this;
Color = color;
OnPropertyChanged(new Vector2(_width, _height), true);
return this;
}
public override void OnAddedToEntity()
{
OriginNormalized = Vector2Ext.HalfVector();
//Origin =
}
public override void Render(Batcher batcher, Camera camera)
{
//var pos = (Entity.Transform.Position - (Origin * Entity.Transform.Scale) + LocalOffset);
//var size = new Point((int)(_width * Entity.Transform.Scale.X), (int)(_height * Entity.Transform.Scale.Y));
//var destRect = new Rectangle((int)pos.X, (int)pos.Y, size.X, size.Y);
//batcher.Draw(_sprite, destRect, _sprite.SourceRect, Color.White, Entity.Transform.Rotation,
// SpriteEffects.None, LayerDepth, SkewTopX, SkewBottomX, SkewLeftY, SkewRightY);
batcher.Draw(_sprite, Entity.Transform.Position + LocalOffset, Color.White,
Entity.Transform.Rotation, Origin, Entity.Transform.Scale, SpriteEffects, _layerDepth);
}
}

浙公网安备 33010602011771号