Standard Library Maths Helpers

Learn how to implement some more advanced math functions, with some help from the C++ standard library.
This lesson is part of the course:

Game Dev with SDL3

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

Free, Unlimited Access
3D art showing a character studying maths
Ryan McCombe
Ryan McCombe
Posted

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

Exponentiation

We saw how we could do something like 232^3 is equal to 2Ă—2Ă—22 \times 2 \times 2, or 88. 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, 232^3 might come from:

pow(2, 3);

Or, more generally, we'd have two variables like xx and yy, and we could calculate xyx^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>

Error: cmath not found

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);

Squaring and Small Powers

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)

Square Root

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

Square Root of Negative Numbers

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.

Alternative Square Root Functions

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.

Implementing Vector Length and Distance

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?

Ryan McCombe
Ryan McCombe
Posted
DreamShaper_v7_cyberpunk_woman_playing_video_games_modest_clot_0.jpg
This lesson is part of the course:

Game Dev with SDL3

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

Free, Unlimited Access
  • 25.Making Minesweeper with C++ and SDL2
  • 26.Project Setup
  • 27.GPUs and Rasterization
  • 28.SDL Renderers
Movement and Physics
DreamShaper_v7_cyberpunk_woman_playing_video_games_modest_clot_0.jpg
This lesson is part of the course:

Game Dev with SDL3

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

Free, unlimited access

This course includes:

  • 27 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Implementing Movement using Vectors

Learn some more vector math, and see how we can use it to implement gameplay movement.
3D art of a teacher in a classroom
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved