Introduction to C++ with Game Development: Part 15, Mathematics

by IGAD of NHTV University at May 20, 2010

Introduction

If you are like me, you probably hate mathematics. For some strange reason, game development is full of it, yet many game developers consider themselves noobs in this area. It might have something to do with the fact that you get away with plenty of trial and error: once your formulas work, you can basically stop trying to understand them.

In this tutorial, we'll have a look at some cool applications of maths, in pretty common situations. So, let's brush up those skills...Follow me.

Clipping

The first practical problem we will be tackling is clipping. Many games will offer you a huge world, but lets face it: it still needs to fit on the screen. If something is completely outside screen boundaries, we simply don't draw it, but what if it's only partially on-screen? Try this:

The output of this code is... nothing. The reason is simple. Have a look at surface.cpp, line 135 and onward: every line that has its first or last point outside the screen will be skipped completely. Why? Because you can't draw pixels outside the screen. Of course, that's a pathetic solution. It would be much better to clip the line, so that it does fit on the screen. But how was that done again...

Let's look at the red line first. Let's say our screen is 640x480, and the red line starts at (-20, 280) and ends at (380, 440). Figuring out where it enters the screen works like this:

While drawing the line, we move 400 (= x2 - x1) pixels to the right.

While drawing the line, we move 160 (= y2 - y1) pixels to the bottom of the screen.

For clipping, you will generally handle the four sides of the screen one by one. For the left side, we can now find a generic answer: if a line starts with a negative x, then it can be clipped like this:

y1 += -x1 * ((y2 - y1) / (x2 - x1));
x1 = 0;

If the left side of the red line wasn't the start, but the end, then something similar happens, but you need to swap all variable names. In practice, it's easier to make sure beforehand that the line always goes from left to right. If it doesn't, you just flip it.

So, how would we handle the green line? The maths is similar: this time we want to know how large the bit is that sticks out at the right side. Once we know that, we can adjust (x2, y2). Like this:

y2 -= (x2 - 640) * ((y2 - y1) / (x2 - x1));
x2 = 640;

There you go. You should now have the tools to finally fix that line function in the surface class so that it actually behaves like it should, and you can store it for later usage.

Aiming a turret

The second problem also requires some math. Let's first get some code in place. In game.h, find the line that says 'void MouseMove' and replace the {} at the end by a semi-colon (';'). Then, above the Tick method in game.cpp, add:

Now there's a gun, but we need to figure out its direction. Well, maths to the rescue again! You may recall that sin, cos and tan are quite useful for filling in gaps if you have some information about a triangle.

In this image, we can use tan for all kinds of interesting operations. We know that tan(a) = Y/X. For our problem, we want a, so we use atan: a = atan( Y / X ). For a given x and y, this will get us the angle. Let's see what we get:

Add this code in the Tick function, after the call to Clear. The values that atanf returns look like this:

That's wrong of course, but it's still useful information. Assuming that we want 0 at the top (convenient for our sprite), the top-right quadrant is correct if we adjust it using a = (90 - a). The bottom-right quadrant also needs an adjustment: a = 90 + a. The bottom left quadrant is correct when a = 270 - a, and finally, the top-left quadrant should be a = a + 270. So, one question remains: how do we identify the quadrants? The math for that is simple: if ((x > 0) && (y < 0)) then we are in the top-right quadrant. The others are found in the same way.

You now have enough information for the assignment. Go forth and code!

Assignment

Finish the application with the following modifications:

Add a white square on the screen, starting at position (100, 80) and extending to (560,400).

Clip the red mouse-laser to this box.

Draw the correct frame of the aagun sprite, so that it faces the mouse cursor.