Recent Resources
-
GLSL 4.0: Discarding Fragments to Create a Perf...
-
GLSL 4.0: Using Subroutines to Select Shader Fu...
-
Building a Complete Board-based Puzzle Game wit...
-
JIRA: Programming Workflows
-
.NET Generics 4.0: Container Patterns and Best...
-
Raw Meat: Game Design Tips from Team Meat's...
-
Sedge: An Automated Error Reporting Tool
Implementing 2D Vectors
By Willem van Doesburg | Published May 21 2000 12:40 AM in Game Programming
Download attached article resource
Download attached article resource
Introduction
In my explorations as a beginner game-programmer across the web and various books, I have not yet found a document that satisfactorily explains how to implement vectors in a game. Sure, I found numerous documents on: vector math, drawing lines, vector classes and physics. But I couldn't find a document that explains how all these things play a part in making a game. A document on vector math doesn't deal with the twisted co-ordinate system of a computer screen. A document on drawing lines doesn't explain how to represent a line as a class. A Vector class document doesn't explain operations on that class. A physics document doesn't give you any useful algorithms for your program. This document attempts to satisfy all the shortcomings of those other documents. This document will use C++ notation for examples because to me there is only ONE language.
A Vector (class)
Vectors in general can be represented in 2 ways.
Here's the class listing:
You'll notice that I included the endpoint in my class while I said earlier that you only need an angle and length to specify a vector. I chose to include the endpoint because of efficiency. You need a cosine and sine function to calculate the endpoint. By storing the endpoint we only have to do this calculation once every time the endpoint changes instead of every time we want to use the endpoint. The length of the vector is specified in amount of pixels but that could easily be modified to anything you want.
Another important thing to keep in mind is the co-ordinate system we use. Normal vector mathematics usually uses the Cartesian coordinate system.
A Cartesian co-ordinate system looks like this:
The computer designers of course chose a different approach to deal with things (as usual).
A computer screen uses the following co-ordinate system:
To make it easy for ourselves (so we don't need to rebuild a lot of formulas) we will use the Cartesian co-ordinate system. Later in this document I'll tell you how to convert your co-ordinates from 1 system to the other and back.
The angle that we use in our class is the angle between the vector and the positive X-axis.
Preparations
There are some numbers you'll need for the calculations. We need cosine and sine to calculate rotations. Experienced readers will have noticed that I store the vector angle in degrees while most math libraries use radians to calculate sine and cosine. So we'll need to convert our degrees to radians for these functions. For that we need PI so let's define PI.
This function needs to convert degrees to radians, which can be done by:
The class definition
Now that we're prepared let's look at the 2 most important functions of our class. SetLength( long Lin ) and SetAngle( long Ain ) these functions cause a new endpoint to be calculated and stored.
We can do this using the following calculation:
How to use this class
Now that we have a vector class we want to put it to use.
Well let's use a pooltable to test our vector.
In this scenario we'll have an object Ball which will use a vector to keep track of it's velocity.
This is quite simple we just move our ball around by specifying an angle and a length and then we keep adding the endpoint x,y to the x,y of the ball.
A problem arises when our ball hits a cushion on the pooltable. When this happens we'll have to calculate a new velocity vector so our ball will bounce naturally. If we now the normal of the cushion we can calculate the new vector as follows:
Conclusion
Now you know how to effectively use vectors in your games. You'll be suprised at the number of situations you can apply vectors in, especially in games. I've included links for some sample code at the top of this page.
In my explorations as a beginner game-programmer across the web and various books, I have not yet found a document that satisfactorily explains how to implement vectors in a game. Sure, I found numerous documents on: vector math, drawing lines, vector classes and physics. But I couldn't find a document that explains how all these things play a part in making a game. A document on vector math doesn't deal with the twisted co-ordinate system of a computer screen. A document on drawing lines doesn't explain how to represent a line as a class. A Vector class document doesn't explain operations on that class. A physics document doesn't give you any useful algorithms for your program. This document attempts to satisfy all the shortcomings of those other documents. This document will use C++ notation for examples because to me there is only ONE language.
A Vector (class)
Vectors in general can be represented in 2 ways.
1: by a length and an angleThese two methods each have their own math. Method 1 uses trigonometry to calculate angles and normals. Method 2 uses matrix math to calculate rotations and other operations. In this document we'll implement a vector represented by method 1.
2: by a begin and endpoint
Here's the class listing:
class C2DVectorI'll have to explain some things about this implementation of a Vector class.
{
private:
long x,y; //Endpoint coordinates
int angle; //Angle of vector
long length; //length of the vector
public:
void SetX( long Xin ); //Set the X element of the endpoint
void SetY( long Yin ); //Set the Y element of the endpoint
void SetLength( long Lin ); //Set the length in pixels
void SetAngle( int Ain ); //Set the angle in degrees
long GetX(); //Get the X element of the endpoint
long GetY(); //Get the Y element of the endpoint
long GetLength(); //Get the length
int GetAngle(); //Get the angle
public:
void operator=(C2DVector aVector); //Make this vector equal with another
C2DVector(); //constructor
C2DVector( long Xin, long Yin ); //overloaded constructor
~C2DVector(); //destructor
};
You'll notice that I included the endpoint in my class while I said earlier that you only need an angle and length to specify a vector. I chose to include the endpoint because of efficiency. You need a cosine and sine function to calculate the endpoint. By storing the endpoint we only have to do this calculation once every time the endpoint changes instead of every time we want to use the endpoint. The length of the vector is specified in amount of pixels but that could easily be modified to anything you want.
Another important thing to keep in mind is the co-ordinate system we use. Normal vector mathematics usually uses the Cartesian coordinate system.
A Cartesian co-ordinate system looks like this:
The computer designers of course chose a different approach to deal with things (as usual).
A computer screen uses the following co-ordinate system:
To make it easy for ourselves (so we don't need to rebuild a lot of formulas) we will use the Cartesian co-ordinate system. Later in this document I'll tell you how to convert your co-ordinates from 1 system to the other and back.
The angle that we use in our class is the angle between the vector and the positive X-axis.
Preparations
There are some numbers you'll need for the calculations. We need cosine and sine to calculate rotations. Experienced readers will have noticed that I store the vector angle in degrees while most math libraries use radians to calculate sine and cosine. So we'll need to convert our degrees to radians for these functions. For that we need PI so let's define PI.
#define PI 3.141592654Again for efficiency I am going to store both sine and cosine values for every angle in an array so we don't need to use those slow sin() and cos() routines every time. So let's declare those:
float costable[360];We'll also need a routine to fill these tables.
float sintable[360];
This function needs to convert degrees to radians, which can be done by:
rad = deg / 180 * PI
void InitTables()
{
float temp;
for( int i = 0; i<360; i++ )
{
temp = ((float)(360-i)/180;
//cast needed for calculation
//I use (360 - i) to compensate for the weird screen coordinates
temp *= PI;
costable[i] = (float)cos( temp );
sintable[i] = (float)sin( temp ); }
}
The class definition
Now that we're prepared let's look at the 2 most important functions of our class. SetLength( long Lin ) and SetAngle( long Ain ) these functions cause a new endpoint to be calculated and stored.
We can do this using the following calculation:
x = cos(angle) * lengthHere's what the functions look like in our code:
y = sin(angle) * length
void C2DVector::SetLength( long Lin )
{
length = Lin;
x = costable[angle]*length;
y = sintable[angle]*length;
}
void C2DVector::SetAngle( int Ain )
{
angle = Ain;
x = costable[angle]*length;
y = sintable[angle]*length;
}
How to use this class
Now that we have a vector class we want to put it to use.
Well let's use a pooltable to test our vector.
In this scenario we'll have an object Ball which will use a vector to keep track of it's velocity.
This is quite simple we just move our ball around by specifying an angle and a length and then we keep adding the endpoint x,y to the x,y of the ball.
A problem arises when our ball hits a cushion on the pooltable. When this happens we'll have to calculate a new velocity vector so our ball will bounce naturally. If we now the normal of the cushion we can calculate the new vector as follows:
- invert the velocity vector
- calculate delta( v, n )
- angle = angle +/- delta( v, n)
void CBall::HitBoundary( C2DVector* BoundaryNormal )In the implementation of my Vector class I adjusted for the weird screen coordinate system. But if you ever need to convert Cartesian coordinates to the screen you can do this as follows:
{
int angle; //the new angle
int OppAngle; //the inverted old angle
int NormDiffAngle; //difference between the inverted angle & the BoundaryNormal angle
angle = Velocity.GetAngle();
OppAngle = (angle + 180) % 360;
if( BoundaryNormal->GetAngle() >= OppAngle )
{
NormDiffAngle = BoundaryNormal->GetAngle() - OppAngle;
angle = (BoundaryNormal->GetAngle() + NormDiffAngle) % 360;
}
if( BoundaryNormal->GetAngle() < OppAngle )
{
NormDiffAngle = OppAngle - BoundaryNormal->GetAngle();
angle = BoundaryNormal->GetAngle() - NormDiffAngle;
if( angle < 0 ) angle += 360;
}
Velocity.SetAngle( angle );
}
void ConvertCoordinates( long* X, long* Y, BOOL convert )
{
int Xmiddle;
int Ymiddle;
Xmiddle = (int)(XRES/2); //XRES is the Screen resolution in the x direction
Ymiddle = (int)(YRES/2); //YRES is the Screen resolution in the y direction
if( convert)
{
*Y = -*Y;
*X = *X + Xmiddle;
*Y = *Y + Ymiddle;
}
else
{
*X = *X - Xmiddle;
*Y = *Y - Ymiddle;
*Y = -*Y;
}
}
Conclusion
Now you know how to effectively use vectors in your games. You'll be suprised at the number of situations you can apply vectors in, especially in games. I've included links for some sample code at the top of this page.
Download attached article resource


















