4
votes

Why Vector2 (from XNA's library) uses float not int?

Position on computer screen is given in pixels so that cursor position can be defined by two integers. There is no such a thing like half a pixel. Why we use floats then?

In SpriteBatch class I've found 7 overloaded methods called Draw. Two of them:

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

So we can see that Draw accepts both int and float coordinates.

I came across this problem when I've been implementing screen coordinates of my game's objects. I assumed that Rectangle is good choice to hold object's size and screen coordinates. But now I'm not sure...

3
When you're working with scalars, always use decimal numbers. or if you have a speed at 0.1f, and you keep adding it to a int, the position will remain the same. But with a float this will make your position keep increasing.Gustavo Maciel
@patryk -The Vector2 is used for so many other things besides simply screen pixel positions. Most of the other uses involve arithmetic where precision finer than whole numbers is desired.Steve H
Also, using Draw(Texture2D, Rectangle, Color) you can 'scale' texture to destination rectangle, but Draw(Texture2D, Vector2D, Color) will use Texture2Ds .Width and .Height.SkillGG

3 Answers

6
votes

Mathematically, a vector is a motion, not a position. While a position on the screen might not technically be able to be between integers, a motion definitely can. If a vector used ints then the slowest you could move would be (1, 1). With floats you can move (.1, .1), (.001, .001), and so on.

(Notice also that the XNA struct Point does actually use ints.)

4
votes

You could use both Vector2 and Rectangle to represent your objects coordinates. I usually do it like this:

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

To move objects, just set their Position property to a new value.

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

You don't have to worry about the rectangle, as it's value depends directly on Position.

My game objects also usually contain methods to draw themselves, such as

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

Collision detection code in your Game.Update() could just use the PositionRectangle to test for collisions

//_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;
}

You could also call the spriteBatch.Draw() with PositionRectangle, you shouldn't notice much difference.

3
votes

There is such a thing as "half a pixel." Using float coordinates that aren't pixel-aligned will cause your sprites to be rendered at sub-pixel coordinates. This is often necessary to make objects appear to scroll smoothly, but it can also produce an unpleasant shimmering effect in some circumstances.

See here for a summary of the basic idea: Subpixel rendering