2013-08-03 43 views
0

我正在嘗試爲XNA獲取一些原語,包括能夠旋轉的輪廓矩形。這非常有用,因爲您可以使用它創建一些可愛的動態內容以及用於調試目的。XNA原始矩形有旋轉問題

我遇到的問題可以看出here

本質上,發生了什麼事時,畫的輪廓矩形時,並轉動線的厚度可達過去的一,組成矩形的線條移動更遠並離得更遠。

這很奇怪,但我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); 
    } 
    } 
} 

如果您有任何問題,請不要害怕問!

回答

0

你應該用尺度除原點。

var scale = new Vector2(Bounds.X, Thickness * Scale.Y); 
var origin = new Vector2(Origin.X, Origin.Y * Bounds.Y)/scale; 
sb.Draw(Assets.Pixel, new Vector2(minx, miny), null, Color * Alpha, 
     Angle, origin, scale, Flip, Layer); 

雖然我認爲你正在做的事情有點複雜......我會用一個變換矩陣變換的drawed矩形...

public void DrawBorder(Rectangle Bounds, int ThickNess, float angle, Color color) { 
     Vector3 Origin = new Vector3(Bounds.Width, Bounds.Height, 0) * 0.5f; 
     Vector3 Pos = new Vector3(Bounds.X, Bounds.Y, 0); 

     Matrix transform = Matrix.CreateTranslation(-Origin) 
         * Matrix.CreateRotationZ(angle) 
         * Matrix.CreateTranslation(Pos); 
     Batch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, transform); 

     Bounds.X = 0; 
     Bounds.Y = 0; 
     Rectangle aux = Bounds; 

     Bounds.X -= ThickNess; 
     Bounds.Width = ThickNess; 
     Batch.Draw(Batch.WhiteTexture, Bounds, color); 
     Bounds.X = aux.Right; 
     Batch.Draw(Batch.WhiteTexture, Bounds, color); 

     Bounds.Y = aux.Top - ThickNess; 
     Bounds.X = aux.Left - ThickNess; 
     Bounds.Width = aux.Width + 2 * ThickNess; 
     Bounds.Height = ThickNess; 

     Batch.Draw(Batch.WhiteTexture, Bounds, color); 

     Bounds.Y = aux.Bottom; 

     Batch.Draw(Batch.WhiteTexture, Bounds, color); 

     Batch.End(); 
    } 
+0

謝謝你,讓我試試看。我會檢查矩陣的東西,我已經使用了一個用於我的相機,並且我在第一個'spritebatch.Draw'中使用它。我不知道你可以用矩陣旋轉單個物體,這肯定會讓我的生活更輕鬆。 :) – redcodefinal

+0

我查了矩陣的東西,我認爲這會比它的價值更麻煩。此外,您的解決方案似乎沒有解決問題:( – redcodefinal

+0

規模影響的起源...我雖然該部門將解決它...我已經添加了一個矩陣的代碼...我假設原點是矩形的中心......但是如果你想圍繞任意原點旋轉,很容易改變它 – Blau