【问题标题】:Why Vector2 (from XNA's library) uses float not int?为什么 Vector2(来自 XNA 的库)使用 float 而不是 int?
【发布时间】:2012-05-05 08:45:33
【问题描述】:

为什么 Vector2(来自 XNA 的库)使用 float 而不是 int

计算机屏幕上的位置以像素为单位,因此光标位置可以由两个 integers 定义。没有像 半个像素 这样的东西。那我们为什么要使用浮点数呢?

SpriteBatch 类中,我发现了 7 个称为 Draw 的重载方法。其中两个:

public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color);
public void Draw(Texture2D texture, Vector2 position, Color color);

所以我们可以看到 Draw 接受 intfloat 坐标。

我在实现游戏对象的屏幕坐标时遇到了这个问题。我假设 Rectangle 是保存对象大小和屏幕坐标的好选择。但现在我不确定...

【问题讨论】:

  • 使用标量时,请始终使用十进制数。或者,如果您的速度为 0.1f,并且您不断将其添加到 int,则位置将保持不变。但是有了浮动,这会让你的位置不断增加。
  • @patryk - 除了简单的屏幕像素位置之外,Vector2 还用于许多其他事情。大多数其他用途涉及算术,其中需要比整数更精细的精度。
  • 另外,使用Draw(Texture2D, Rectangle, Color) 可以将纹理“缩放”到目标矩形,但Draw(Texture2D, Vector2D, Color) 将使用Texture2Ds .Width.Height

标签: xna floating-point int draw spritebatch


【解决方案1】:

在数学上,向量是一个运动,而不是一个位置。虽然屏幕上的位置在技术上可能无法介于整数之间,但运动绝对可以。如果一个向量使用ints,那么你可以移动的最慢的将是(1, 1)。使用floats,您可以移动(.1, .1)(.001, .001),等等。

(另请注意,XNA 结构 Point 确实使用了 ints。)

【讨论】:

    【解决方案2】:

    您可以同时使用Vector2Rectangle 来表示您的对象坐标。我通常这样做:

    public class GameObject
    {
        Texture2D _texture;
    
        public Vector2 Position { get; set; }
        public int Width { get; private set; } //doesn't have to be private
        public int Height { get; private set; } //but it's nicer when it doesn't change :)
    
        public Rectangle PositionRectangle
        {
            get
            {
                return new Rectangle((int)Position.X, (int)Position.Y, Width, Height);
            }
        }
    
        public GameObject(Texture2D texture)
        {
            this._texture = texture;
            this.Width = texture.Width;
            this.Height = texture.Height;
        }
    }
    

    要移动对象,只需将其Position 属性设置为新值即可。

    _player.Position = new Vector2(_player.Position.X, 100);
    

    您不必担心矩形,因为它的值直接取决于Position

    我的游戏对象通常也包含绘制自己的方法,例如

    public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
    {
        spriteBatch.Draw(this._texture, this.Position, Color.White);
    }
    

    Game.Update() 中的碰撞检测代码可以只使用PositionRectangle 来测试碰撞

    //_player and _enemy are of type GameObject (or one that inherits it)
    if(_player.PositionRectangle.Intersects(_enemy.PositionRectangle))
    {
        _player.Lives--;
        _player.InvurnerabilityPeriod = 2000;
        //or something along these lines;
    }
    

    您也可以用PositionRectangle 调用spriteBatch.Draw(),您应该不会注意到太大的区别。

    【讨论】:

      【解决方案3】:

      “半个像素”这样的东西。使用非像素对齐的浮点坐标将导致您的精灵在子像素坐标处渲染。这通常是使对象看起来平滑滚动所必需的,但在某些情况下也会产生令人不快的闪烁效果。

      基本思想总结见这里:Subpixel rendering

      【讨论】:

      • 那么我应该使用什么结构来记住对象的大小(在 float 中)和屏幕坐标(也是 float)。 Rectangle 会很完美,但它使用 int。我正在寻找等效的 float Rectangle 而不创建我自己的结构(如果你明白我的意思,我不想重新发明轮子;))。
      • 在我的 2D 游戏中,我通常只使用 Vector2 作为位置,使用 Rectangle 作为边界,正如 Niko Drašković 在他的回答中所描述的那样。
      猜你喜欢
      • 1970-01-01
      • 2023-01-16
      • 1970-01-01
      • 2012-05-28
      • 2020-04-26
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多