我试图让一些原语适用于 XNA,包括制作可以旋转的轮廓矩形的能力。这非常有用,因为您可以用它创建一些甜蜜的动态内容,以及它用于调试目的。
我遇到的问题可以在这里看到
本质上,正在发生的事情是,当绘制一个轮廓矩形并将线条的粗细超过一个时,构成矩形的线条会越来越远。
这很奇怪,但我 90% 确定问题出在根源上。我希望有人可以看看并发现我的错误。
我通过将线的原点设置为矩形的中心来绘制旋转线来渲染矩形。为了实现矩形的底部和右侧部分,我将顶部和左侧的线复制并旋转 180 度。(如果你在弧度范围内工作,我就是 Pi)
最大的怪异之处在于,当我调试Draw
方法时,我发现值都完全符合预期!
这是矩形类,继承的类也在下面,以备不时之需。
public class Rectangle : Primitive
{
public float X { get { return Body.X; } set { Body.X = value; } }
public float Y { get { return Body.Y; } set { Body.Y = value; } }
public float Width { get { return Body.Width; } set { Body.Width = value; } }
public float Height { get { return Body.Height; } set { Body.Height = value; } }
public float Angle { get { return Body.Angle; } set { Body.Angle = value; } }
public override Vector2 Bounds { get { return new Vector2((Width) * Scale.X, (Height) * Scale.Y);}}
public override Microsoft.Xna.Framework.Rectangle DrawRect
{
get
{
return new Microsoft.Xna.Framework.Rectangle((int) (X - Thickness/2), (int) (Y - Thickness/2),
(int) ((X + Width + Thickness) * Scale.X),
(int) ((Y + Height + Thickness)* Scale.Y));
}
}
public bool Fill;
public Rectangle(Entity parent, string name, float x, float y, float width, float height, bool fill = false)
: base(parent, name)
{
X = x;
Y = y;
Width = width;
Height = height;
Fill = fill;
Origin = new Vector2(.5f,.5f);
}
public Rectangle(IComponent parent, string name, Body body, bool fill) : base(parent, name, body)
{
Fill = fill;
Origin = new Vector2(.5f, .5f);
}
public override void Draw(SpriteBatch sb)
{
base.Draw(sb);
if (!Fill)
{
float minx = X + (Thickness/2) + Origin.X;
float miny = Y + (Thickness/2) +Origin.Y;
//TODO: Fix origin issue
//Draw our top line
sb.Draw(Assets.Pixel,
new Vector2(minx, miny), null, Color * Alpha, Angle, new Vector2(Origin.X, Origin.Y * Bounds.Y), new Vector2(Bounds.X, Thickness * Scale.Y), Flip, Layer);
//Left line
sb.Draw(Assets.Pixel,
new Vector2(minx, miny), null, Color * Alpha, Angle, new Vector2(Origin.X * Bounds.X, Origin.Y), new Vector2(Thickness * Scale.X, Bounds.Y), Flip, Layer);
//Essentially these are the same as the top and bottom just rotated 180 degrees
//I have to do it this way instead of setting the origin to a negative value because XNA
//seems to ignore origins when they are negative
//Right Line
sb.Draw(Assets.Pixel,
new Vector2(minx + 1, miny), null, Color * Alpha, Angle + MathHelper.Pi, new Vector2(Origin.X * Bounds.X, Origin.Y), new Vector2(Thickness * Scale.X, Bounds.Y), Flip, Layer);
//Bottom Line
sb.Draw(Assets.Pixel,
new Vector2(minx, miny + 1), null, Color * Alpha, Angle + MathHelper.Pi, new Vector2(Origin.X, Origin.Y * Bounds.Y), new Vector2(Bounds.X, Thickness * Scale.Y), Flip, Layer);
}
else
{
sb.Draw(Assets.Pixel, new Vector2(X + Origin.X*Width, Y + Origin.Y*Height), null, Color * Alpha, Angle, Origin, Bounds - new Vector2(Thickness), Flip, Layer);
}
}
Primitive
public abstract class Primitive : Render
{
public Body Body;
public float Thickness = 1;
protected Primitive(IComponent parent, string name) : base(parent, name)
{
Body = new Body(this, "Primitive.Body");
}
protected Primitive(IComponent parent, string name, Vector2 pos)
: base(parent, name)
{
Body = new Body(this, "Primitive.Body", pos);
}
protected Primitive(IComponent parent, string name, Body body) : base(parent, name)
{
Body = body;
}
public static void DrawLine(SpriteBatch sb, Vector2 p1, Vector2 p2, float thickness, float layer, Color color)
{
float angle = (float)System.Math.Atan2(p2.Y - p1.Y, p2.X - p1.X);
float length = Vector2.Distance(p1, p2);
sb.Draw(Assets.Pixel, p1, null, color,
angle, Vector2.Zero, new Vector2(length, thickness),
SpriteEffects.None, layer);
}
}
Render
班级。这个并不重要,因为它只是为任何渲染类提供某种多态性。
using EntityEngineV4.Engine;
using EntityEngineV4.PowerTools;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace EntityEngineV4.Components.Rendering
{
public abstract class Render : Component
{
public float Alpha = 1f;
public Color Color = Color.White;
public SpriteEffects Flip = SpriteEffects.None;
public float Layer;
public Vector2 Scale = Vector2.One;
public Vector2 Origin;
/// <summary>
/// Handy rectangle for getting the drawing position
/// </summary>
public virtual Rectangle DrawRect { get; set; }
/// <summary>
/// Source rectangle of the texture
/// </summary>
public virtual Rectangle SourceRect { get; set; }
/// <summary>
/// Bounds of the DrawRect
/// </summary>
public virtual Vector2 Bounds { get; set; }
protected Render(IComponent parent, string name)
: base(parent, name)
{
}
public override void Update(GameTime gt)
{
base.Update(gt);
}
public override void Draw(SpriteBatch sb = null)
{
base.Draw(sb);
}
}
}
如果您有任何问题,请不要害怕提问!