Learn how to implement some more advanced math functions, with some help from the C++ standard library.

Posted

In the previous lesson, we talked about exponents and square roots. Lets see how we can implement them in C++

We saw how we could do something like $2^3$ is equal to $2 \times 2 \times 2$, or $8$. This is sometimes also *called raising 2 to the 3rd power*.

We'd like to be able to do this in code. One way we might be to have a function we can call with two numbers - a *base* and a *power*. For example, $2^3$ might come from:

`pow(2, 3);`

Or, more generally, we'd have two variables like $x$ and $y$, and we could calculate $x^y$ by doing:

`pow(x, y);`

We perhaps know how we could create such a function - that function might involve a loop that multiplies `x`

by `x`

until some condition involving `y`

is no longer true. Fortunately, the standard library has already implemented this, and many more maths helpers for us.

`CMath`

To access the standard libraries math utilities, we need to include `<cmath>`

:

`#include <cmath>`

In some compilers, the `#include <cmath>`

declaration will throw an error. It may be necessary to use `include <math.h>`

instead

After including `cmath`

or `math.h`

the `pow`

function is now available within the `std`

namespace:

`std::pow(x, y);`

Like with any namespace, if we have an appropriate `using`

statement, we can omit the scope resolution:

```
using namespace std;
pow(x, y);
```

When we need to raise something to a small power, we don't need a helper function. For example, to raise `a`

to the power of `2`

, it's likely easier to have our code be `a * a`

rather than `pow(a, 2)`

Implementing a function that calculates the square root ourselves would be a bit more difficult, with what we've learnt so far.

Fortunately, `CMath`

gives us access to the `std::sqrt`

function too:

```
#include <cmath>
std::sqrt(25); // 5
```

What if we wanted to get the square root of `-25`

?

There's no real number that can multiply by itself to give an answer of `-25`

, or any other negative number.

Because of this, when we're using square root functions, we typically want to make sure that the thing we're trying to calculate the square root of is positive.

If our program ever finds itself needing to get the square root of a negative number, it's likely we made a mistake in our logic somewhere.

If we do end up passing a negative number to `std::sqrt`

, this will result in an exception being thrown, which may get our program into a broken state.

Programming a computer to calculate the square root of an input variable is not as easy as it seems. There are many different algorithms that can be used, each with their advantages and disadvantages.

The standard library's `sqrt`

function has the advantage of being extremely accurate, but quite slow. This is often not the trade off we want when working with graphics, particularly when we may be doing thousands of these calculations per frame.

Typically, we prefer a faster implementation that gets an approximate answer.

Because of this, `std::sqrt`

tends to not be used in these type of applications. But, for simplicity, we'll stick with it in this course.

With these new functions at our disposal, we can now update our `Vector3`

struct with the ability to return its length, as well as the distance to another vector.

```
#include <cmath>
struct Vector3 {
float x;
float y;
float z;
float GetLength() {
return std::sqrt(x * x + y * y + z * z);
}
float GetDistance(const Vector3& Other) {
using namespace std;
return sqrt(
pow(x - Other.x, 2) +
pow(y - Other.y, 2) +
pow(z - Other.z, 2)
);
}
};
```

With these new additions to our toolbox, we are now able to introduce the concept of attack range to our characters.

For example, by comparing the `WorldPosition`

of our character to the `WorldPosition`

of its target using the `GetDistance`

function, we can see how far away the two objects are.

This would allow us to prevent our character from attacking an enemy that is too far away. We could also implement behaviours like character doing more damage to targets in melee range.

In the next lesson, we will take this further, and introduce some additional vector math. This will allow us to implement rules around how characters can change their `WorldPosition`

, giving us the groundwork for character movement. See you there!

Was this lesson useful?

Posted

This lesson is part of the course:### Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

- 41.GPUs and Rasterization
- 42.SDL Renderers