[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();
		pVector.X = radius * cos(angle);
		pVector.Y = radius * sin(angle);
		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. (:

So here's a zip file you can download: Vector2

[Disclaimer: This is an experimental post, I would not actually completely condone using this; heck, I'm not even using this. I'm using a queue based event system with reference counting smart pointers.]

For the sake of experimenting, and to make a new and "safer" Event, I found out I could call a protected function from outside of the scope of that class, from using a function pointer assigned by the parent class.  Certainly this doesn't sound safe, as it bypasses encapsulation measures; however, this allowed me to fire an event in a way only the parent could.


So I was trying to come up with an ideal Event for an EventSystem, and I had a couple ideas, though things bugged me in each.  So, this is a typical Event, which I do have a slight problem with:

 

class Event
{
public:

	void Attach(IEventObserver* eventObserver);
	void Detach(IEventObserver* eventObserver);

	void FireEvent(const EventArgs& eventArgs);
};

So, an IEventObserver can both register itself AND fire off an event; the IEventObserver shouldn't be able to fire the event it's registering to, should it? Only the parent that contains the Event should, in my belief. So I thought, is there any way I can allow the parent class to fire off the event and still allow the Event to be public?  Okay, I figured I could setup accessors to the event; however, this meant I'd have to setup an accessor for each and every single event I have, which could get ugly fast.

I eventually thought of a sneaky way, that actually shouldn't even be possible. Giving the parent class, what I call the trigger, a function pointer to a protected function that fires the event. After writing it, I realized while I liked the idea, everything about coding the use of the Event was a lot more difficult, so I provided macros to do the dirty work for you; however, it still seems like an annoying setup to me. I usually code things to be easy to interact with, and what I came up with clearly goes against my programming paradigms.

So, here's the tiny change in the Event:

class Event
{
protected:
	void FireEvent(const EventArgs& eventArgs);

public:

	void Attach(IEventObserver* eventObserver);
	void Detach(IEventObserver* eventObserver);
};

Obviously there isn't much of a difference here, there isn't much to add. The difference is here in the full version:

template <class IEventArgs>
class Event
{
	typedef std::list<IEventObserver<EventArgs>*> EList;
protected:
	EList _observers;

	void FireEvent(IEventArgs& eventArgs)
	{
		EList::iterator iter = _observers.begin();

		while(iter != _observers.end())
		{
			(*iter)->CatchEvent(eventArgs);
			++iter;
		}
	}

public:
	typedef void (Event<IEventArgs>::*IEventTrigger)(IEventArgs& eventArgs);//use an event trigger mechanism

	Event(EventTrigger& trigger)
	{
		trigger = &Event::FireEvent;
	}

	virtual ~Event()
	{
	}

	void Attach(IEventObserver<IEventArgs>* eventObserver)
	{
		_observers.push_back(eventObserver);
	}

	void Detach(IEventObserver<IEventArgs>* eventObserver)
	{
		_observers.remove(eventObserver);
	}
};

Note the EventTrigger; to create an Event you have to pass in a reference to a function pointer. Here are the three Macros I have at the top of my Event.h file (they looked ugly and hard to read inside of the code block, so here they are in a pre tag):

#define EVENT_H(variable,argType) Event::EventTrigger trigger##variable; Event* variable;
#define EVENT_CPP(variable,argType) trigger##variable = NULL; variable = new Event(trigger##variable);
#define EVENT_FIRE(variable,args) ((variable)->*(trigger##variable))(args);

You place a macro call to EVENT_H inside of the .h file, a call to EVENT_CPP in the .cpp file where the event is being constructed, and EVENT_FIRE when you want to fire the event (though, EVENT_H and EVENT_CPP are actually more annoying to use than just setting up the Event by hand, so I'll probably remove those two macros, as they don't actually help at all).

So, ignoring the macros, lets say I want to create an event, I can do this.

Event::EventTrigger keyTrigger= NULL;
Event* keyEvent = new Event(keyTrigger);

This will create an Event for me to use as well as hook up a trigger to fire the event. When I finally want to fire the event I can do something like this;

(keyEvent->*(keyTrigger))(KeyEvent(FK_F11));//this event and argument are just for example

So, this system is what I came up with, though I'm still not so sure if I like it.  I'd love to get any comments or suggestions for a better system.  Even if I don't use this setup, I still found this process to be an interesting learning experience.  I just wanted to find out if I could get access to a protected function using a function pointer; I found out I could, and I find that intriguing.  For clarification, the Event in the above example would be public, and the trigger protected (or private); so I have to update my macro EVENT_H to include those overrides.  I'll provide the source code in a couple days or so when I get everything properly packaged together; right now the code is sitting inside of my engine, and are tied into various systems, so the source files won't compile for you without modification (because I can't include all of the other misc. files).  So, this still isn't a lot nicer than the other solution; it's merely replacing an accessor with a trigger.  So, either way it's kind of ugly I think, to ensure safe firing of an event.

Anyway, I haven't touched Event Systems in more than a couple weeks, it's something I'll have to worry about very shortly; so when I revisit them, I'll probably make a blog post concerning my more finalized systems with what I finally decide to use.  Any feedback would be greatly appreciated. Thanks!

I apologize if the post jumps around a bit, it is very late as I type this.

Archive