Higher-Order Fun

Game Design & Game Programming

Math for game programmers 02 – Vectors 101

If you don’t already use vectors (and I mean vectors in the MATHEMATICAL sense, not in the “dynamic array” sense that languages like C++ or Java use), this is probably going to be the single most useful piece of math you can learn for writing games. It’s easy, efficient, and makes your code much shorter. In fact, provided that you’re using a language that supports definition of operators for user-defined types (like, say, C++ or Haskell), using vectors is going to be extremely intuitive and simple.

Motivation: The Ugly Code

Consider that you want to simulate some simple physics, such as an object accelerating in 3D space. We’re going to use the formulas Δs = v₀t + ½·a·t² and Δv = a·t (where s is the position, v₀ is the speed at the start, a is the acceleration, and t is the elapsed time). You might declare the object as something like this:


class PhysicsObject {
  public:
    float pos_x, pos_y, pos_z; // Position
    float vel_x, vel_y, vel_z; // Velocity
    float imass; // The inverse of the mass (1/m)

    void addImpulse(float force_x, float force_y, float force_z, float t) // t is time, in seconds
    {
        float halft2 = 0.5f * t * t;

        float accel_x = force_x * imass;
        float accel_y = force_y * imass;
        float accel_z = force_z * imass;

        pos_x += vel_x * t + accel_x * halft2;
        pos_x += vel_y * t + accel_y * halft2;
        pos_x += vel_z * t + accel_z * halft2;

        vel_x += accel_x * t;
        vel_y += accel_y * t;
        vel_z += accel_z * t;
    }
};

Not very pretty – there’s a lot of redundancy – whatever you do for one axis, you do for the other two. If only there was a way to do that all at once…

Enter vectors: The Pretty Code

Here’s the same code, but this time using a hypothetical 3d vector class:


class PhysicsObject {
  public:
    vector3f pos; // Position
    vector3f vel; // Velocity
    float imass; // The inverse of the mass (1/m)

    void addImpulse(vector3f force, float t) // t is time, in seconds
    {
        vector3f accel = force * imass;
        pos += vel * t + accel * (0.5f * t * t);
        vel += accel * t;
    }
};

Much shorter, isn’t it? You now have half as many lines to write, test and debug. Not only that, but they’re also simpler, and you avoid a whole class of “copy-paste but oops forgot to change a letter in one place” bugs. So, after all, what ARE these vectors? How do they work?

P.S.: If you’re using a language which does not allow you to define your own operators, the code above will get quite uglier… Java, I’m looking at you.

Defining vectors

If you go check Euclidean Vector at Wikipedia, you’ll see that it’s defined as a geometric object that has magnitude (length) and direction. For our purposes, while important to remember that definition, we’ll think of vectors as an n-tuple of a given type. In the example about, we have a 3-tuple (“a triple”) of floats. In other words, our definition would be something like this:


class vector3 {
  public:
    float x, y, z;

    inline vector3 operator + (const vector3 &param) const
    {
        return vector3(x + param.x, y + param.y, z + param.z);
    }

    inline vector3& operator += (const vector3 &param)
    {
        x += param.x;
        y += param.y;
        z += param.z;
        return *this;
    }

    inline vector3 operator * (float param) const
    {
        return vector3(x * param, y * param, z * param);
    }

    // Lots of other methods here
};

Basically, all it does (so far) is take basic arithmetic operators and apply them to 3 values, instead of just one. When you add two vectors, it adds each component – x to x, y to y and z to z. There’s also the “scale” operator, which is the multiplication by a scalar (a scalar is a non-vectorial number, like a float). When you multiply a vector by a scalar, you simply multiply all components by it. So, if you want to make your vector twice as big, just multiply it by 2.

That’s it! That’s the basic idea! Whenever you have two or more points and always want to perform the same set of operations on them, use a vector! In fact, most properties that apply to scalar numbers will also work here… If you happen to know that you need to multiply velocity by time to get a change in position, you can do that with vectors in just the same way you would with scalars.

When should you use vectors like this? Whenever it makes sense. If you’re passing along two or three values which all represent the same point, do yourself a favor and pack them in a vector. Not only will it be much harder to accidentally mix up stuff, your code will be shorter. Even if they aren’t a POSITION, they might still be represented by a vector – for example, the size of a rectangle is a vector where x is the width and y is the height. That way, if you have a vector representing the starting position of the rectangle, and a vector representing its size, you can easily find its ending position by adding them up.

But vectors are far more powerful than this. On the next article, we’ll explore other common operations done on them, such as length, normalization, dot product and cross product. You wouldn’t believe me if I told you just how damn useful those can be.

11 ResponsesLeave one →

  1. Even with my mathematical inability I was able to comprehend your explanations. This means you’re a great tutor. Keep it up.

  2. jlmf

     /  2012-09-03

    Well, it is clear thtat you are using object oriented programming. I’m sure the number of operations is exactly the same. The code is much pretty, but not more efficient. By the way I’m in favour of using geometry-algebra-math in programming (in all type of programming). Regards…

  3. Walter Weinzinger

     /  2012-09-03

    As a physics major, I was very puzzled with these statements above:

    float accel_x = force_x * imass;
    float accel_y = force_y * imass;
    float accel_z = force_z * imass;

    since Newt II states F=ma, or, a=F/m

    Did your code actually run correctly?

    Thank you!

    Walter Weinzinger
    Flagstaff, AZ

  4. amz

     /  2012-09-03

    It might not be clear in the body of the article, but the comment on the code itself explains it: imass is the inverse of the mass, therefore multiplying by it is the same as dividing by the mass.

  5. I’m pretty sure you don’t need those ‘inline’ keywords. Any method defined within the class declaration is implicitly inline. Lovely article by the way, it would be fabulous if you could keep this particular series of blog posts going! Kudos.

  6. whocares

     /  2014-02-25

    In “The Ugly Code” you increment 3 times the pos_x variable; I think it’s a typo and you meant pos_x, pos_y, pos_z.

  7. Richard

     /  2015-08-30

    What’s this &amp stuff in the code? Doesn’t help.

  8. Richard

     /  2015-08-30

    To the physics major: read the code. imass is 1/mass.

  1. Math for Game Programmers 05 – Vector Cheat Sheet | Higher-Order Fun
  2. Game programming in C++ « C Sharp Important Notes
  3. Matemática para programadores de Jogos: Vetores |

Leave a Reply

*