[Edit: Checkout the improved Vector2 class here: improved Vector2 blog post.]

Hey, it's been a while since I've posted anything, and I've been wanting to share this Vector2 class that I have written. It started being developed less than a year ago, and has undergone some minor changes since then to try to improve efficiency and add functionality. I haven't touched it in a while since then, as I'm now working on a 3D game engine, but here is what I've got.

```/*  __      __   ___     _____    ____
*  \ \    / /  / _ \   |  __ \  |    |
*   \ \/\/ /  / / \ \  | | / /  |  __|
*    \_/\_/  /_/   \_\ |_| \_\  |_|
*      Take it to the next Level
*
*  Copyright (c) 2009 Brian Ernst.
*/

#ifndef w_Vector2
#define w_Vector2

#include <math.h>

namespace _Warp
{
typedef float Scalar;
typedef int Bool;

class Vector2
{
public:
Scalar X;
Scalar Y;

Vector2(const Scalar x = 0,const Scalar y = 0);
~Vector2();

Vector2 operator+(const Vector2& pVector) const;
Vector2 operator-(const Vector2& pVector) const;
Vector2 operator*(const Scalar& num) const;
Vector2 operator/(const Scalar& num) const;
Vector2 operator*(const Vector2& vector) const;
Vector2 operator/(const Vector2& vector) const;
void operator+=(const Vector2& pVector);
void operator-=(const Vector2& pVector);
void operator*=(const Scalar& num);
void operator/=(const Scalar& num);
void operator=(const Vector2& pVector);
Bool operator==(const Vector2& vector) const;
Bool operator!=(const Vector2& vector) const;

void Clamp(const Scalar& value);
void Normalize(const Scalar& value = 1.0f);
void Invert();

Scalar Length() const;

Vector2 Copy() const;

static Vector2 Cartesian(const Scalar& x,const Scalar& y);
static Vector2 Polar(const Scalar& radius,const Scalar& angle);
static Scalar Dot(const Vector2& pVec1,const Vector2& pVec2);
static Vector2 Rotate(const Vector2& pVec,const Scalar& angle);
static const Vector2 Zero;
};

inline Vector2 Vector2::Copy() const
{
return Vector2(X,Y);
}

inline Bool Vector2::operator==(const Vector2& vector) const
{
return X == vector.X && Y == vector.Y;
}

inline Bool Vector2::operator!=(const Vector2& vector) const
{
return X != vector.X || Y != vector.Y;
}

inline Vector2 Vector2::operator+(const Vector2& pVector) const
{
return Vector2(X + pVector.X,Y + pVector.Y);
}

inline Vector2 Vector2::operator-(const Vector2& pVector) const
{
return Vector2(X - pVector.X,Y - pVector.Y);
}

inline Vector2 Vector2::operator*(const Scalar& num) const
{
return Vector2(X * num,Y * num);
}

inline Vector2 Vector2::operator/(const Scalar& num) const
{
return Vector2(X / num,Y / num);
}

inline Vector2 Vector2::operator*(const Vector2& vector) const
{
return Vector2(X * vector.X,Y * vector.Y);
}

inline Vector2 Vector2::operator/(const Vector2& vector) const
{
return Vector2(X / vector.X,Y / vector.Y);
}
}

#endif```

And yes, I realize I need to comment this class, and I will. I might include the source files, but you can just as easily click on the "Source" button on the top right corner of the code box. And here's the cpp definitions file for the Vector2 functions:

```#include "Vector2.h"

namespace _Warp
{
const Vector2 Vector2::Zero = Vector2();

Vector2::Vector2(const Scalar x,const Scalar y)
{
X = x;
Y = y;
}

Vector2::~Vector2()
{
}

void Vector2::operator+=(const Vector2& pVector)
{
X += pVector.X;
Y += pVector.Y;
}

void Vector2::operator-=(const Vector2& pVector)
{
X -= pVector.X;
Y -= pVector.Y;
}

void Vector2::operator*=(const Scalar& num)
{
X *= num;
Y *= num;
}

void Vector2::operator/=(const Scalar& num)
{
X /= num;
Y /= num;
}

void Vector2::operator=(const Vector2& pVector)
{
X = pVector.X;
Y = pVector.Y;
}

Scalar Vector2::Length() const
{
return sqrt(pow(X,2.0f) + pow(Y,2.0f));
}

void Vector2::Clamp(const Scalar& value)
{
if(Length() <= value)
return;
Normalize();
*this *= value;
}

void Vector2::Normalize(const Scalar& value)
{
Scalar vecLength = Length();

if(vecLength == 0)
return;

X = X/vecLength * value;
Y = Y/vecLength * value;
}

void Vector2::Invert()
{
X *= -1;
Y *= -1;
}

Vector2 Vector2::Polar(const Scalar& x,const Scalar& y)
{
Vector2 pVector = Vector2();
pVector.X = atan2(y,x);
pVector.Y = sqrt(x * x + y * y);
return pVector;
}

Vector2 Vector2::Cartesian(const Scalar& radius,const Scalar& angle)
{
Vector2 pVector = Vector2();
return pVector;
}

Scalar Vector2::Dot(const Vector2& pVec1,const Vector2& pVec2)
{
return pVec1.X * pVec2.X + pVec1.Y * pVec2.Y;
}

Vector2 Vector2::Rotate(const Vector2& pVec,const Scalar& angle)
{
Scalar cosResult = cos(angle);
Scalar sinResult = sin(angle);

//Essentially, apply a 2x2 rotation matrix to the vector
Scalar newX = pVec.X * cosResult - pVec.Y * sinResult;
Scalar newY = pVec.X * sinResult + pVec.Y * cosResult;

return Vector2(newX,newY);
}
}```

It's pretty simple, but quite useful and powerful I think. I put it up here for other people to use for quick reference; let me know what you think or just drop me a line telling me you're using it for something, that'd make my day. (:

Just updated the source files and code boxes above, let me know if you have thoughts comments. The previous stuff I had posted I forgot to define Bool; and yes I'm aware of the existence of bool, but for the sake byte alignment and possible performance I'm choosing to define my own Bool; I've never tested this, though I will one of these days; and for this reason, I wonder if I should define a 64bit Bool for a 64bit system. Also I'm sorry your comments didn't show up earlier, my spam filter picked your comments out as Spam, only just realized this. I'll try to stay more on top of it in the future, so sorry for the delay of getting your comments posted.

Along the lines of a possible comment I would expect: this Vector2 class is useful for a single type of use, such as 2d gameplay, which is why a Scalar is defined to be a float. Though I'm wondering, should I use a template so I can use this for both 2d gameplay and UI stuff or whatever else? The only difference if I'm using floats and ints would be the performance difference of the calculations. I'm also unaware if there are performance differences using a template vs none; this is something I have to test or research.

# Leander 2010-10-22 8:41 pm

Oh -- right: * throw unary - in there instead of or in addition to "Invert" (and since you have unary -, do unary + too) Nice tables here: http://web.cecs.pdx.edu/~karlaf/CS202_Slides/Operator_Overloading_Guidelines.htm

# Aury 2010-10-22 10:29 pm

"* Your if(vecLength == 0) tests should probably skip doing the length thing and just check X+Y == 0, it's likely to be faster since it avoids the sqrt." I assume you mean in Normalize(), as this is the only place I can find Length() compared against 0 inside the class. However, if you were to do this, it would not normalize any vector where X == -Y. (Incidentally, X*Y == 0 also does not work for any vector where only one component is zero.) I recommend testing both components against 0, unless there is some optimization I am unaware of.

Hey Leander, thanks for all your input, I just have a few questions. Here's one of them: You've mentioned non-member, do you mean using them like this: namespace _Warp { class Vector2 { public: ... friend Scalar len2(const Vector2& vect); .... }; inline Scalar len2(const Vector2& vect) { return vect.X * vect.X + vect.Y * vect.Y; } }; Or do you suggest I move them out into a separate class somewhere like Vector2_Util or something? As far as splitting up header files, couldn't I do that anyway just using compile flags in various places in the header file (though I think it looks kind of ugly)? Right, I realize I rushed in posting this without remodeling it with some "common sense"; making a basic data type const in the parameter is pointless, check. Passing references to basic data types isn't worth the computation time, check. Using var * var instead of pow should have been a given for me, as the extra function call adds to the runtime. etc. Wow, you're definitely on top of your stuff to easily pick all this out man! You're not lead programmer for nothing. (: What would you have me do with a unary + anyway? I know the - just makes the vector negative, did you have in mind it makes negative components positive? -- When I post the modified Vector2 class I'll probably post it in a new post, and I'll definitely acknowledge you for your suggestions/fixes.