Introduction to Matrix Operations

In this part, we’ll be looking at basic matrix math. We’ll be looking at how we create the various transformation matrices that we use for rotating, moving and scaling. If you really want, you can skip to the second part where we look at some code and let glm do the maths for us. But I really recommend actually learning the basics of matrix operations.

Matrices

Matrices are basically small tables of numbers. They are used in graphics programming when transforming vectors and object. We use them to move, rotate and scale objects. The math behind them is relatively simple though some of it can be hard to wrap your mind around first. And there are several mistakes that are easy to make and very hard to debug, so it’s very useful to know a bit about them and how they work.

The basics

In all simplicity, a matrix is just a table of numbers. Like the one you see below. With it comes a lot of simple operations we can do to transform objects ( like we saw with the model/view/projection matrix in the last part. But even though the idea is simple and the operations are basic ( usuaully just addition and multiplication ), they can quickly become confusing

The unit matrix

What you see above is what we call the “unit matrix”. You can look at this like the base matrix or the null matrix. The idea behind it is that anything you multiply it with will remain the same ( we’ll look at this soon. ) That makes the unit matrix the starting point as well as it’s used in a few different, more complex matrix expression.

Matrix – vector multiplication

The simplest operations we’ll be looking at, is multiplying a matrix with a vector. This is quite straight forwards, though there will be a lot of numbers to keep track of so read through it a few times and get comfortable with it before proceeding. The formula for multiplying a 3×3 matrix with a 3d vector is as follows :

Let’s isolate just the top row ( all rows are multiplied in the same way )

We can multiply 4×4 matricies and verticies like this :

Step-by-step guide

1. Look at first row
1. Multiply first matrix value on that row with first vector value (x)
2. Multiply second matrix value on that row with second vector value (y)
3. Multiply third matrix value on that row with third vector value (z)
4. Continue until no more more numbers on that line of the matrix
5. Add all the numbers together
2. Repeat for next row until no more rows
3. Done!

You might have noticed that this requires that the number of values in each row of the matrix is the same as the numbers of values in the vector. If we have 3 values in each row of the matrix, the vector needs to have 3 values as well. This isn’t really an issue for us, so we won’t be looking at these cases here.

The unit matrix

As mentioned earlier, the unit matrix won’t change anything we multiply by it. We can see this by doing a multiplying with placeholder values for x, y, z and w

So now that we’ve learned how to do multiplication, let’s test it out and see if it’s really true! Let’s try to multiply it by the vector 1.03, -4.2, 9.81, 13 :

As you can see, we end up with the same as we began with, 1.03, -4.2, 9.81, 13.

Matrix – matrix multiplication

Multiplying a matrix with a vector was quite easy. Now let’s make things a tiny bit more difficult and multiply a matrix with a different matrix. This is one of the most important basic operations we need to do. It plays a huge role in moving/scaling/rotating objects. And, as we’ll see in a later part, it’s a very important part of lighting.

Matrix multiplication depends a bit on the sizes of the two matrices. But we’ll simplify it to say that we’ll always be working with unifrom matrixes ( 2×2, 3×3, 4×4 ). Firstly, lets look at the generic formula :

Now this seems a bit complicated, so let’s look at how to calculate just the first number :

As you can see, for the first part of the multiplication we use the first numbers of both matrices ( A11 and B11 ). But for the second number, we use the next number in the same row for matrix A ( A12 ) and the next number in the same column for matrix B ( B21) This pattern repeats for the next number on that row like this :

Now we move to the next row and repeat the process :

And finally, the last cell :

This can also be extended to a 3×3 matrix like this

This is a lot of numbers, but if you look closely, you’ll see it’s a lot like the previous one, only with an extra number on each row and column. So in this case, for the first number, all we did was add + a13 * b31 to the original operation ( which was a11 ∗ b11 + a12 * b21 ) For the second number on the top row we added + a13 ∗ b32 to the original operation. The third number on the top row is new but it follows the same pattern;

For all the numbers on the same row from matrix A

a11, a12, a13

and all the numbers in the same column from matrix B

b13, b23, b33

multiply each pair in the same position and add them together.

a31∗b13 + a32∗b23 + a33∗b33

The unit matrix again

Now let’s try multiplying a vector with the unit matrix again. We should get the same result as we started with, but let’s see…

Success! This product is exactly the same as we started with!

Ordering matters

A very important part of matrix operations is the ordering. Normally in mathematics the ordering is not important. When it comes to simple multiplication it does not matter what order you multiply two numbers 123 * 321 gives the exact same result as 321 * 123. But when it comes to matrices, this is not true. Let’s look at a very simple example :

But if we flip the ordering…

..we end up with something completely different.

Because of this, it is important to keep track of the ordering, otherwise, you’ll end up spending hours debugging!

Using matrices to change vertexes

Now that we’ve learned about the basic math about matrices, it’s time to learn how to use them. We’ll be using them to move, scale and rotate objects. We do this by multiplying each vertex by a matrix. After multiplying the vertex, we get a new vertex back that has been moved/scaled/rotated. After doing this to all the vertexes of the object, the entire object will have been moved/scaled/rotated. Creating these matrices is quite easy though there will be a few numbers to keep track of. Let’s look at the operations one by one.

Moving (translating)

The matrix we use for moving an object is quite simple. It is defined like this :

\begin{bmatrix}
\end{bmatrix}

Where dx is movement in x direction, dy is movement in y direction and dz is movement in z direction. So in effect, we get this matrix :

\begin{bmatrix}
1 & 0 & 0 & \phantom{-}9.2\\
0 & 1 & 0 & \phantom{-}1.2\\
0 & 0 & 1 & -3.7\\
0 & 0 & 0 & \phantom{-}1\\
\end{bmatrix}

Will move the object 9.2 in the x direction, 1.2 in the y direction and -3.7 in the z direction.

Now this might look a bit familiar. Let’s compare it to the unit matrix :

\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1\\
\end{bmatrix}

That’s right. It’s the same except the dx, dy and dz part. This will come into effect when we do the actual translation.

Since we are using a 4×4 matrix, it is easier to use 4d vector. But that raises a new question; what about the last value? The x, y and z is, of course, the position. But there is a final number we haven’t cared about yet. As it turns out, this has to be 1 we’ll find out why now.

Let’s look at an example. Say we have the vector [11, 1.5, -43] first we need to add the last digit, 1 so we end up with :

\begin{bmatrix}
\phantom{-}11\\
\phantom{-}1.5\\
-43\\
1
\end{bmatrix}

Now for the translation matrix. Let’s use the one from above which will move the object 42 in the x direction, 19 in the y direction and -13 in the z direction.

\begin{bmatrix}
1 & 0 & 0 & \phantom{-}9.2\\
0 & 1 & 0 & \phantom{-}1.2\\
0 & 0 & 1 & -3.7\\
0 & 0 & 0 & \phantom{-}1\\
\end{bmatrix}

Finally we can try the translation. Translating an object is simply just multiplying the vertex and the translation matrix :

This might seem like a bit of over complication. Why not just add the numbers? Just adding the numbers would be practical if we were just moving the object. But we can do other things like scaling and rotating. By using a matrix, we can combine all of these into a single operation. So let’s look at the next operation, scaling.

Making things bigger or smaller (scaling)

The second operation we’ll look at is how to make objects larger or smaller. This is quite similar to translating objects. For scaling we have the base matrix:

\begin{bmatrix}
sx & 0 & 0 & 0\\
0 & sy & 0 & 0\\
0 & 0 & sz & 0\\
0 & 0 & 0 & 1
\end{bmatrix}

And just like with translation matrices, we multiply our vector with this matrix to get the scaled vector back.

Here sx, sy, sz are the scale factors, which are the numbers we need to multiply with in order to get the result :

• If you don’t want to scale it all all, you se the scale factor to 1.
• If you want to double the size you have a scale factor of 2, for trippling you have 3, etc…
• If you want to make it 50% larger, you have a scale factor of 1.5, 25% larger the scale factor is 1.25, etc…>
• If you want to halve it, you have a scale factor of 0.5, make it 75% smaller the scale factor is 0.25, etc…

Let’s first look at an example:

Say we have the vertex [2.1, 3.4, -9.5] and we want to scale it like the following :

• Make it 70% smaller in x direction
• Scale factor becomes 1.0 - 0.7 = 0.3
• Make it 80% larger in y direction
• Scale factor becomes 1.8
• Triple the size in z direcion
• Scale factor becomes 3.0

This gives us the scale factors [0.3, 1.8, 3.0 and the vertex [2.1, 3.4, -9.5]. Let’s plot these into the matrix operation:

This gives us the scale factors [0.3, 1.8, 3.0 and the vertex 0.63, 6.12, -28.5]… Which tells us that the vertex has been moved :

• Closer to the center in x direction ( becasue object get smaller in x direction )
• A little further away from the center in y direction ( which means the object gets larger in y direction )
• A lot further away from the center in z direction ( getting a lot larger in z direction )
• And if we apply this to all the vertices in an object, we find that the center of the object remains the same, so we’re not actually moving the object, we’re just moving the individual vertices. Closer to or further away from the center.

Rotating

Now this is where things get a little complicated. We need to translate the object using numbers calculated using sin and cos. The formula for calculating the rotated x and y is as follows :

 x2 = cos β * x1 − sinβ * y1 y2 = sin β * x1 + cosβ * y1 

I won’t go into details about why this formula works, but you can read about it here.

Specifying axis

In order to rotate a 3d object, we need an axis to rotate it around. Take a look at the dice below :

It is laid out like the following :

Now imagine we want to rotate it so that we see other numbers. In order to do this, we need an axis to rotate it around. Imagine we stick a toothpick throw this dice from 5 to 6 like the following :

Now we can rotate the dice 90° down and we end up with something like this :

[Note: If anyone has any tips or can in any way help me improve these illustrations, it’d be much appreciated]

The math

When it comes to the actual math, it’s a bit more complicated. I won’t be explaining where we get the matrices for rotation, but if you’re interested, you can read more about it here.

Like with translating and scaling, we use a matrix to do the rotation. But the matrix itself is a bit complex and is a little different depending on which axis you rotate :

For X axis

\begin{bmatrix}
1 & \phantom{-}0 & 0 & 0\\
0 & \phantom{-}cos\phantom{-}θ & sin\phantom{-}θ & 0\\
0 & -sin\phantom{-}θ & cos\phantom{-}θ & 0\\
0 & \phantom{-}0 & 0 & 1\\
\end{bmatrix}

For Y axis

\begin{bmatrix}
cos\phantom{-}θ & 0 & -sin\phantom{-}θ & 0\\
0 & 1 & 0 & 0\\
sin\phantom{-}θ & 0 & \phantom{-}cos\phantom{-}θ & 0\\
0 & 0 & 0 & 1\\
\end{bmatrix}

For Z axis

\begin{bmatrix}
cos\phantom{-}θ & -sin\phantom{-}θ & 0 & 0\\
sin\phantom{-}θ & \phantom{-}cos\phantom{-}θ & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1\\
\end{bmatrix}

Why are they so different

The reason why they are different is how they multiply with the unit matrix

\begin{bmatrix}
1 & 0 & 0 & 0\\
0 & 1 & 0 & 0\\
0 & 0 & 1 & 0\\
0 & 0 & 0 & 1\\
\end{bmatrix}

You’ll see that the formula for rotating around the x axis :

\begin{bmatrix}
1 & \phantom{-}0 & 0 & 0\\
0 & \phantom{-}cos\phantom{-}θ & sin\phantom{-}θ & 0\\
0 & -sin\phantom{-}θ & cos\phantom{-}θ & 0\\
0 & \phantom{-}0 & 0 & 1\\
\end{bmatrix}

Has the same first column and row [1, 0, 0, 0] as the unit matrix. If you look at how matrices are multiplied, you’ll see that this won’t change the final x coordinate

And if you look at the matrices for rotating around y and z, you’ll see the same. The y rotation matrix has the same second column and row as the unit matrix [ 0, 1, 0, 0 ] and the one for z axis has the same third column and row as the unit matrix [ 0, 0, 0, 1]. This means that rotating around z axis doesn’t change the z coordinate, and rotating around the y axis doesn’t change the y coordinate

Imagine putting a dice on a table. Now turn the dice clockwise or counter-clockwise without lifting the dice in any way. If you define the z axis to be the height above the table, you’re now rotating the dice around the Z axis. And since you’re not lifting it, the z coordinate remains the same.

Example

Let’s make a matrix for rotating the point [2,4, 8] by 30 degrees around the x axis.

As you can see, the y and z coordinates have changed, but the x coordinate is the same. This is due to how matrix multiplication work.

Other axis

You might wonder; what if I want to move the object around a combination of two or three axes? Well, that’s a bit more complex, and I won’t go into the math here. But we’ll see how we can use glm to specify an exact axis of rotation below

Putting it all together

Before we look at how to do these operations using code, we need to look at how to do it by hand. Or by online matrix calculators in this case… Buy why? As I mentioned earlier, ordering is important here. Do things in the wrong order, and you get weird results.

In the previous post, we looked at object space, world space, view/camera space camera and projection space. Let’s skip the last two for now and focus on the object and world space.

Remember that object space is basically the model represented as a set of coordinates around origin [0, 0, 0] and that world space is the position of the object in the game world. So if the object has moved 10 units to the right, it’ll have the position [0, 10, 0] which means we have to move it there. This is where the translation matrix comes in! The object could also have turned around ( rotated ) and grown (scaled). Since the object is defined in object space ( vectors around [0,0,0] ) and this will never change, we need to move/scale and rotate the object every time. So we need to multiply every coordinate with this matrix in order to place/scale/rotate it correctly.

Luckily we can just multiply the matrices together and reuse this matrix until the object moves. But this is also where we need to be careful about getting the orientation right. Let’s start by moving and scaling.

Example – Wrong way

Say we want to scale by 2 units in every direction and move 3 unites in every direction. Remember that the scale matrix looks like this :

\begin{bmatrix}
sx & 0 & 0 & 0\\
0 & sy & 0 & 0\\
0 & 0 & sz & 0\\
0 & 0 & 0 & 1
\end{bmatrix}

Filling in numbers :

\begin{bmatrix}
2 & 0 & 0 & 0\\
0 & 2 & 0 & 0\\
0 & 0 & 2 & 0\\
0 & 0 & 0 & 1
\end{bmatrix}

And translation matrix

\begin{bmatrix}
\end{bmatrix}

Filling in the numbers, we get :

\begin{bmatrix}
\end{bmatrix}

Now let’s multiply them :

Let’s analyse this. Looking at the scale numbers, we see 2, 2, 2 as we expected. But when we look at the translation, we see 6, 6, 6! That’s wrong! We wanted 3, 3, 3, not 6, 6, 6!

The reason why this happens is that we multiplied by scale first when we should have started with the translation instead. So let’s reverse the order of the operations and try again

That’s more like it. We see that we move by 3 and scale by a factor of 2.

When we add rotation, we can run into the same problem. Imagine if the object is first moved, then rotated we would still move around the origin(0,0,0). But since we already have moved the object away from the origin, we’ll orbit the origin ( much like a planet ) instead.

The correct order

In our example ( and in most cases ) the correct order is scale -> translate -> rotate. You might think it would be the other way around, but matrix operations are in the opposite order of what you expected. So you start out with the last thing you want to happen ( scale ) and end with the first (rotate)

Using glm to do matrix operations

Luckily, we don’t have to do all of this ourselves. In fact, glm does nearly all the math for us. Including rotation ( fortunately )All of these methods takes a glm 4×4 matrix, called mat4 this is basically just a 4×4 array representing a matrix.

You can find the documentation here.

glm::translate

Takes a matrix, translates it and returns it.

Parameters :

• glm::mat4 original – the matrix you want to translate
• glm::vec3 dist – the distance to move

Return :

The original matrix original translated by dist like we looked at earlier

glm::scale

Takes a matrix and scales it and returns it

Parameters :

• glm::mat4 original – the matrix you want to scale
• glm::vec3 scale – the factors to scale by

Return :

The original matrix original scaled by scale matrix like we looked at earlier

glm::rotate

Takes a matrix and rotates it around an axis and returns it

Parameters :

• glm::mat4 original – the matrix you want to scale
• double angle – the amount/angle you want to rotate by ( radians )
• glm::vec3 axis – the axis to rotate by

Return :

The original matrix original rotated by angle around the axis, axis like we looked at earlier

Putting it all together

Now that we have looked at the functions, we can easily put them all together.

This is a simple class that shows how you can use all the operations we’ve looked at.

File notes

You can find the source code for an application that lets you move/scale/rotate a cubehere.

Images with colored matrix/vector multiplications has been made using calcul.com

Dice illustration has been made using Inkscape

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Continuing where we left of…

Last time we left off after having taken a look at UDP connections. But, as we saw, UDP connections have several issues :

• No delivery guarantee
• Packages might not arrive in the same order they were sent

So how do we solve these issues? By creating an actual connection. A TCP connection that is.

TCP connections

As mentioned in the previous post, UDP connections aren’t connections at all. It’s basically just two parts sending data back and forth between them. TCP connections, however, are proper connections. This means we know the following :

• Both parts tries to keep the connection alive
• Both parts have received everything the other part has sent
• Every package has been received in order

These points requires two different mechanisms, so let’s look at the one by one.

How TCP works

In order to have a connection, both parts have to agree on it. This is different from UDP connection because in UDP connections we just send the data without bothering about actual connections. So how do we set up the TCP connection? By using a technique called three-way handshake

The three-way handshake

The process of establishing a TCP connections requires three different steps:

• Part 1 contacts part 2 and asks to start a connection
• Part 2 replies and either says OK, or declines
• If part 2 declines, the process stops here
• Part 1 replies back, to confirm that he’s received part 2’s request
• Now the actual connection is started and we can send data

The third step might seem kinda unnecessary, but remember that any packages can get lost. And so if part 2 doesn’t get the answer from part 1, part 2 doesn’t know whether part 1 is still there. Part 1 might have lost the connection or wished to stop it altogether. We can compare this to starting a phone call :

1. Part 1 calls part 2
2. Part 2 picks up and says hello
3. Part 1 says hello back

After the last step, the conversation is started. All of these step are necessary for us to know there is an actual conversation. Skipping one of them might make you think something is wrong. For instance, if part 2 doesn’t say ‘hello’, you might think there is something wrong with the connection.

Dealing with the UDP issues

The major flaw of UDP is that it doesn’t deal with loss of packages. And another issue is that we don’t know if we’re getting the correct package at the correct time. Potentially we can get every package in the wrong order. Which could lead to everything from glitchy gameplay to crashes. So let’s look at the mechanics that makes TCP connections able to give their guarantees :

ACK numbers

In TCP every package gets a unique number. This is basically just a counter so the first package gets the number 0, next one 1 and so on…

This number is then sent back from the recipient to confirm that “okay, so now I have every package up to this package” ( I will refer to the confirmation as ACK numbers.) So when we get an ACK for the last paackage we sent, we know that the other part has received everything we have sent so far. This means we don’t have to worry about any of the packages having been lost.

But say the receiver misses a package in the middle? For example, what if the receiver gets package 1,2,4, but not 3? The receiver will look at the ACK numbers and think “huh… I’m missing a package here.” And will only send ACK 2 back. At this point, your application might get package 1 and 2, but not 4, since it’s out of order.

Flow of TCP

Let’s look at an example to see how the TCP might handle loss of packages.

1. Sender sends package 1,2,3,4
2. Receiver receives package 1
• Send ACK 1 all good so far!
3. Receiver receives package 2 and 4
• Uh oh! Where’s package 3?
4. Sender receives ACK 2
5. Sender waits a while before resending package 3 and 4
• It sends package 4, which the receiver already has, because it only got ACK2
• Now your application will get the last two packages ( 3 and 4 )
• Receiver sends ACK 4
7. Sender receives ACK 4
• The original package 3 was just delayed get it again.

Now the receiver has got all 4 packages and all is fine and dandy. But if you study the example, you see that in our case the sender has to resend 2 packages ( 3 and 4), while the receiver in reality only needed one ( 3 ) And in addition, we got package 3 twice. But even though we got package 4 early, it wasn’t sent to our application before we got package 3 because TCP we receive everything in order. This is one of the major drawback of TCP ; there can be lots of delays and re-sending of packages.

TCP send rate

A final issue about TCP performance is how it regulates package sending. TCP can send several packages at any time. The basic idea is that every time every package is sent successfully and in time, it’ll send more packages the next time.

So the first time, it might only send 2 packages the first time. But if it gets ACK for all those three in a given time, it might send 4 the next time. Then maybe 8 and keep increasing it until it doesn’t get an ACK for all packages on time. When that happens, it’ll send less packages the next time. Let’s look at a simple example :

1. Send 2 packages
• Receive ACK for both packages
2. Send 4 packages
• Receive ACK for all packages
3. Send 8 packages
• Receive ACK for only 5 packages
• We’re missing 3 packages! Maybe this was too many packages? Try sending less…
4. Send 6 packages

As you can see, TCP will try its best to keep sending the maximum number of packages without having to resend anything.

Complexity of TCP

Although TCP is quite old ( more than 30 years old, ) it’s really complicated. There are a lot of different mechanisms involved to deal with anything that might happen. Not only do they handle the cases we’ve seen, but it also, as we saw, needs to control the speed for optimal performance.

I have purposely simplified it because its nice to have a basic understanding of how TCP works as this might help you to choose whether you should use UDP or TCP

The two different parts of TCP connections

Since TCP connection are actual connections, there needs to be a central part ( server ) that the others ( clients ) connect to. I’ll briefly discuss servers and clients, and what their roles are when it comes to TCP

Server

The server is the part that all the clients will connect to. So the server will always be listening for new connection and accepting them as they come. The server will be accepting connections from any client, so we don’t specify IPs on their server side ( ,ore on this later. ) We will only specify the port to listen to.

Client

The client tries to connect to the server. It needs to know both the IP and port of the server before it can try to connect to the server. The server doesn’t know anything about the client until it tries to connect to the server.

When the server accepts the client, the connection is established. At this point in time, the server also has a connection to that client specifically. We’ll see this later.

Note that these are just different types of connection, not necessarily different computers. A computer can have any number of server and / or client connections.

Time for some code

So now that we have all the technical information about TCP is out of the way, we can start setting up a TCP connection of our own. As you might expect, the source code for TCP is a bit more involved than the UDP one.

This part relies on code from my previous post. If something is unclear, you can go back and read that part if you want more information. I have also added links to the documentation in the headers.

SDLNet_ResolveHost

Just like with UDP, we need to ask SDL net to get correct the correct representation ( because of different endianness). The function is the same ( but it is used in a different way for servers, so do read on)

Parameters :

• IPaddress* address – a pointer to an allocated / created IPAdress.
• const char* hostIP address to send to ( xxx.xxx.xxx.xxx )
• Uint16 port – the port number to send to

Return value

The int value 0 on success, otherwise -1. In this case, address.host will be INADDR_NONE. This can happen if the address is invalid or leads to nowhere.

But there is a slight difference in how it’s used. Since TCP connections are actual connections it has both a server and a client part :

Server

The server part needs to be listening for IPs that are trying to connect. So we’re not really resolving a host this time. We’re just preparing the IPaddress for the next step.

So what we do is that we simply use null as the IP. This tells SDL_net that we don’t want to use this IPaddress to connect to a host, but rather just listen for other connections. SDL_net does this by setting the IP to INADDR_NONE. This comes into play in the next step ( SDLNet_TCP_Open)

Client

For clients, this function is used more or less exactly like in the previous part ; it’ll prepare the IPaddress with the information we supply.

Of course, the port on both the server and client side has to be the same.

Note: no connections has been initiated yet, we’ve just asked SDL to prepare the port and IP address for us.

TCPSocket

This is a new type. It represents a TCP connection. We’ll use it just like UDPSocket but of course this time it represents a TCP connection instead of a UDP connection.

SDLNet_TCP_Open

Now that we have an IPadress correctly set up, we can try to connect to a host. This is done by the function SDLNet_TCP_Open

Here is the function signature.

Parameters :

• IPaddress *ip – an IPaddress* contaning the IP and port we want to connect to. We’ll use the one we got from SDLNet_ResolveHost

Return:

• For clients : a TCPsocket to the server, which can be used for sending and receiving data
• For servers : a TCPsocket used for listening for new clients trying to connect

This function will try to open a connection. But just like with SDLNet_ResolveHost, there are two different cases here

Server

Above we saw that if we call SDLNet_ResolveHost with null as the IP, SDL_net will set the IP of the to INADDR_NONE. This means we will be listening for connections, rather than trying to connect. This is because, as a server, we don’t actively try to connect to another host ( we just accept connections ), so we don’t know about any IP address yet.

What this function does in this case, is that it tries to open the port for listening.

Client

For clients, this works much like for UDP : we try to connect to the server with the given IP and port

At this point, the client is connected to the server, and now they can communicated. This is a little different from how it works in UDP so let’s start by looking at how the communcation can be done in TCP

A quick example

Before we jump into the next part, let’s have a quick look at an example of how to use these two functions. These two functions are the initialization part of the TCP code. Since these steps are slightly different form client to server, I’ll cover them separately.

Server

Simply set up the IP address and use it to open a port for listening :

Client

Simply set up the IP address and try to connect to server with that IPaddress :

The job of the client

The clients are the parts you’ll be dealing with they most. A client communicates with other clients. This is more or less just like in UDP, but there are som differences.

SDLNet_TCP_Send

Sending data using TCP is done using a slightly different function from that of UDP :

Parameters :

• TCPsocket sock – the TCPsocket* on which to send the data
• const void *data – the data to send
• int len – the length of the data ( in bytes )

This function is quite straight ahead. The only thing to note is the void*. The type void* is something that is widely used in C but not so much in C++. It’s basically a pointer to anything. So the data can be just about any form of data. This requires a bit of low-level C “hacking” to get right.

Return:

The number of bytes that was sent. If this is less than the size of the data we tried to send ( or the len parameter, ) an error has occured. This error could be the client disconnecting or a network error.

Using this function correctly is tricky, in a similar way to UDP. Let’s look at a possible way to implement it ;

SDLNet_TCP_Recv

Receiving data using TCP is also done using a slightly different function from that of UDP :

Parameters :

• TCPsocket sock – the TCPsocket* on which to recv the data from
• const void *data – the data to receive
• int maxlen – the maximum data to receive

Return:

The number of data received. If this is less than 0, an error has occured.

And since this is C ( and not C++ ) we need to allocate a decent sized buffer in advance ( this is the void *date part. It’ll have the same size as maxlen. The setting of the buffer involves a little C-style trickery.

Let’s look at an example :

The job of the server

So now we have a TCPsocket that listens to the port we specified. And now we can try to accept new connections. For now, we’ll try to accept connections right out of the blue. But later we’ll look out how to check for clients trying to connect. Anyways ; here is the method we need:

SDLNet_TCP_Accept

This is the essentially the accept part of the three-way handshake. The client has tried to connect to us and we need to accept it before the connection is established. This function does exactly what you might expect : it accepts an incoming TCP connection, informs the client and thus establishing the connection.

Parameters :

• TCPsocket *server – the TCPsocket* we use for listening for new connections. This is the TCPConnection we created using SDLNet_TCP_Open.

Return :

A different TCPsocket this TCPsocket does represent a connection to a specific client. If it’s valid, it means a connection has been established. If it’s null it means no connection was established. This can mean that there was an error. But it can also mean that there was no clients trying to connect.

This function might lead to some confusion as there are two TCPsockets, but remember :

The first one ( the parameter we supply ) is ther server TCPsocket. This is not connected to any client, we just need it to be able to listen for new connection. We create this TCPSocket by callling SDLNet_TCP_Open

The second TCPsocket is for a specific client.We create this TCPSocket by callling SDLNet_TCP_Accept. When it’s created, it can be used exaclty like the TCPsockets created on the client side. ( As I talked about in the cleint part of SDLNet_TCP_Open )

Dealing with SDLNet_TCP_Recv

There is a major issue with the receive function. It blocks. This means the function waits until it has received something. Actually, according to the documentation, it’ll wait til it has received exactly maxlen bytes and then set those in the void* data. But from what I’ve found, this isn’t 100% true.

What I have found, is that the function will block. But only until it has received something ( at most maxlen bytes. ) So, in other words, it waits til it has received something, no matter how little or much it is. But even though this is better than waiting for maxlen bytes, the fact that it blocks is still an issue we’ll need to solve.

SDLNet_TCP_Recv will also join together messages if it can. So say client 1 sends

“Hello”

and

“World”

in two separate messages, SDLnet can join them together so that what client 2 gets is

“HelloWorld”

in one message.

This can ( and probably will ) happen if buffer size is large enough.

Or, if the buffer size is too small one call might only get part of the data. So if client 1 sends :

“HelloWorld”

But client 2 has the buffer size set to 6, it’ll get

“HelloW”

The first time client 2 calls SDLNet_TCP_Recv. And

“orld”

The second time it calls SDLNet_TCP_Recv

That means there are two issues to fix : the fact that it blocks and the fact that we might not receive everything with one call to SDLNet_TCP_Recv.

SDLNet_SocketSet

To solve this, we can check if something has happened on a collection of TCPsockets, this includes someone connecting, disconnecting or receiving data.

We can use a SDLNet_SocketSet to solve this. Think of it as simply a set of sockets. We’ll be using it for storing and checking TCPsockets to see if there is any activity. A SDLNet_SocketSet can contain any number of TCPSockets. Those can be both server and client connections.

This is a really simple function for adding a socket to a SDLNet_SocketSet. It also exists for UDP, but we’ll be using the TCP version, of course.

Parameters :

• SDLNet_SocketSet *set – the SDLNet_SocketSet we want to add the TCPsocket to
• TCPsocket *sock – the TCPsocket we want to add to the SDLNet_SocketSet

Return :

The number of TCPsockets in the SDLNet_SocketSet on success. Or -1 on failure.

SDLNet_CheckSockets

Now that we’ve added sockets to the SDLNet_SocketSet, we can use the SDLNet_CheckSockets function to check for activity. “Activity” in this case basically means that something has happened. This can either mean we have received data, that someone has disconnected or that there is an error.

Parameters :

• SDLNet_SocketSet *set – the SDLNet_SocketSet we want to check for activity
• Uint32 timeout – a variable stating how long ( in milliseconds ) we want to wait for activity. We can wait anything between 0 milliseconds and… well anything up to 49 days.

Return :

The number of TCPsockets in the SDLNet_SocketSet with activity on success. Or -1 if either theSDLNet_SocketSet is empty or there was an error.

After we’ve called SDLNet_CheckSockets, we can use this function to check whether a particular TCPSocket has been marked as active. This function should be called on a socket on a SDLNet_SocketSet after code>SDLNet_CheckSockets has been called on the SocketSet that holds that TCPSocket.

Parameters :

• TCPSocket *socket – the TCPSocket we want to check for activity

Return :

Count of TCPSockets with activity

In other words ; we use SDLNet_CheckSockets to see if any of the TCPSockets in a SDLNet_SocketSet has any activity. If so, we can call SDLNet_SocketReady on each of the SDLNet_SocketSets in that SDLNet_SocketSet to see if that TCPSocket in particular has any activity.

Examples

Now let’s look at how you could implement an update function that checks for activity. They’ll be different for server and client connections since client connections checks for incoming messages and disconnections. While on the server side we’ll simply check for clients trying to connect.

Client side example

As I mentioned above, on the client side we need to check for connections and incomming messages. Here is a way to do that :

A problem that arises here, is that calling code>SDLNet_CheckSockets kind of sets the TCPSocket back to “inactive” when you call it. Even if there is several messages waiting to be read.

So when you have called ReadMessage(), you have no way of knowing if it has any more data. Calling it again, would mean calling SDLNet_TCP_Recv again which could block until the other client sent more data.

This is an issue lots of tutorials that I’ve seen has. But there is a solution that doesn’t block ; we just need to call SDLNet_CheckSockets again. So just add this to the bottom of the previous function

Server side example

On the server side, we need to check for clients trying to connect. This is fortunately a little bit simpler than what we had to do on the client side. Here is the code :

I think that’s all for now. You can find a working implementation

here.

Conclusion

Setting up a TCP connection using SDL_Net is quite tricky. Lots of tutorials out there just briefly discuss the topic without going into much detail about the different functions. Hopefully this post has helped you get a better view of the different parts of SDL_net ( I sure did writing it! ) I might also post a third networking post about an even better way of doing network communication using both UDP and TCP for maximum performance.

I’m also really glad to finally have finished and published a new post. I know it’s been a long time since last time, but I’ve been a bit busy at work and haven’t really had the time or energy. But I feel some of my energy is back. And getting positive feedback is always amazing, they help me keep going. So thanks to everyone who’s commented! : )

(Semi) Final code :

Working implementation of TCP connections ( NOTE : work in progress! )

Github page

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Introduction

A huge aspect of game programming is multiplayer. A huge share of all the popular video games today support internet in sme ways. But this introduces several new challanges. Both in the communciation over internet itself but also in what data to send, how to react to data and how to make everything synchronized. This is going to be a sub series in itself starting off with how to do the actual communication.

Packages

When you’re sending something over the Internet, it’ll get split into quite small packages. Each of these packages are usually a few kilobytes or smaller. There are actually several types of packages which get wrapped in each other. I won’t get into the details of this, but what we need to know is that there are several types of packets and they get wrapped in each other.

One of the basic packet types is the IP ( Internet Protocol ) packet. You can look at this as the package that leaves our computer and is sent out on the Internet. Every package that is sent across the Internet is of this type.

We won’t go into the details of each of these fields, the image is there just to show you how it looks. I might go into the details on a later point in time, but that is a big topic and we don’t really need to know all of that in order to do multiplayer.

The package is then sent out on the Internet and will eventually find its way to its destination PC. This is similar to sending a letter. You put the letter inside an envelope and write the destination address on it. Then the mail carrier will take care of the rest.

Actually, that isn’t entirely true because there is another step before the package leaves your computer; we need a protocol.

Protocols

Above we saw an example of in IP package.

So now that we know about packages, the next topic is protocol. A protocol is basically a set of rules about how the two parts should communicate. Most important to us, these rules dictate how to detect package loss and how to deal with them.

Why do we need protocols?

Most of the times when you send something, everything goes fine and the recipient gets the data packages he need. But things can go wrong. Let’s take an example.

Say we have sent our letter to someone. But on it’s way, the letter gets lost. But how can we know? The mail carrier doesn’t know that the letter is lost. The recipient doesn’t know you’ve sent the letter and you yourself is assuming the letter arrived at its destination without any issues.

The exact same thing could happen on the Internet ; packages can get lost, and none will know. So how can the problem be avoided? This is where protocols come in!

There are two protocols, we’ll cover, TCP and UDP. This time, I’ll only cover UDP. I’ll cover the other one, TCP, in a later post.

UDP

The most basic of the protocols we’ll look at is UDP ( User Datagram Protocol. ) Actually, UDP is so basic, there is no rules about how to deal with package loss. You have to handle that yourself.

Another issue is that there is no guarantee that the packages will be received in order. So you could get packages 1,2,3 as 3,2,1 or 3,1,2 or 2,3,1 etc.. And that’s if you do get all packages. Needless to say, using UDP can cause lots of problems. But its’ simple so we’ll start with it.

UDP is generally used for performance or simplicity reasons :

• Video streaming
• If a package is lost, this is just a tiny piece of the stream data and you might not even notive it
• In cases where you just want to send a state to the server
• Like using ping where you just get an echo back
• If you don’t get a message back, you can retry again and again, or report an error
• Games
• For reducing lag
• This means they have their own way of dealing with package loss

On the Internet, there are two units used for addressing, the IP address and the port number. We need both of these to communicate over the Internet.

The IP address is used to address computer. Every unit on the Internet has an IP address that refers to that unit. You can look at it as the address of a house. So when you send a letter to someone in a house, you write the address to that house. When you send a packet to a computer, you send a packet to that IP address.

Port numbers

Port numbers are used to distinguish between connections. Each connection has a separate port number tied to it. If we didn’t have port numbers, all data would go into a large buffer and you’d have no idea which of these datas where yours.

So if an IP adress refers to a house, a port could be looked at as a name.

When you set up a connection, you need both of these an IP address and a port number. Actually you need two of both since the receiver needs to know who sent the package so that it needs to know who to reply to. So all in all, we need two IPs ( out IP and destination IP ) and two port numbers ( our port numbers, destination port numbers. )

So basically, you neeed :

• The recipients IP address and port number

Setting up the connection

Actually, UDP is not really a connection, it’s just two parts sending data back and fort. But both parts still needs to know both IP and port number of each other. And it is common and more practical to think about it as an actual connection.

There are two roles in a UDP “connection”.

• A client
• Tries to connect to a server
• A server
• Waits for a connection from a client

So the procedure for a “connection” will be something like this

• Server with ip 123.123.123.123 waits for connection, listening to port 123
• Client sends a packet to 123.123.123.123, port number 123
• Server stores IP and port number for client
• Server and client now knows both port number and IP of each other
• Now the server and client can now send data back and forth

Sockets

The final part we need to cover about connections are sockets. A socket is a combination of IP address and ports that is unique on every PC for every connection. It consists of the following :

• IP and port of the client side of the connection
• IP and port of our the remote part of the connection
• This part is mostly used for TCP connections, we won’t use it
• Type of connection ( UDP, TCP, etc… )

We’ll be using sockets as a unit to keep track of a connection. You can look at scokets to the sockets you plug your electric devices to. Following that analogy, the wire would be the connection ( network cable ). So, in essence, it’s what connects your application to the Internet.

I realize this all might be a lot of information and hard to wrap your hand around it all, but it’ll get clearer when we put it to use.

SLD_net

Now that we know a tiny bit about UDP connections, let’s try to set up one ourselves. For that purpose, we need the SDL_net library. It is capable of setting up and maintaining both UDP and TCP connections. Since UDP connections are way simpler, we’ll only cover that for now.

Networking is, just like text rendering and .png loading, a separate part of SDL called SDL_net. We install it the exact same way as before :

Installation

Installing SDL2_net is done exactly like SDL2_image. Just replace SDL2_image with SDL2_net

Here’s the short version :

Linux

For Linux you can use need to install -lSDL2_net or -libSDL2_net or -SDL2_net ( the actual name might be different in different distributions. )

The linker flag is -lSDL2_net

The process is more or less identical to that of setting up SDL2_image.

If you can’t find SDL2_net in any repositories and it’s not installed by default, you might have to compile it yourself. For more information, see my blog post about setting up SDL2.

Windows

Similar to setting up SDL2 base.

The difference is that you have to download the development files for SDL2_net

And similarly add SDL2_net.lib to library includes and add SDL2_net.lib to the library flags ( where you previously added SDL2_image.lib )

And with that, it should work.

Mac

See the first part of my tutorial. Just install SDL2_net instead of SDL2

Using SDL_net to set up a connection

Setting up a connection with SDL_net is a bit more complicated than what we’ve previously seen. This is because there are a few steps, the code will be very C ( not C++ ) and there are some buffers ( raw arrays ) we need to keep track off.

We’ll be cutting out all GUI because we simply don’t need it. It will make our code shorter and it’ll be easier to display the results.

Structures of SDL_net

SDL_net contains two parts we need for out UDP connection. Let’s start with the simplest, IPAddress.

A simple struct with the following fields :

• uint_32_t hostIP v4 address
• uint16_t host – protocol port

It is used for keeping IP and port number together. Some functins takes this as one of the parameters.

UDPSocket

A pointer to a data type that holds to a pointer. Since it a pointer, it can be NULL, in which case there is no connection and we can’t send data back and forth.

UDPpacket

Our data packet. Contains the data we are sending back and forth along with some other information.

• int channel
• The src/dst channel of the packet
• We won’t be using this
• Uint8 *data
• The packet data we’re sending
• Can be of any length
• int len
• The length of the packet data
• Used to find the end of the data in the data pointer
• int maxlen
• The max size of the data buffer
• Always as large or larger than len
• Only used for data package creation on the senders side
• int status
• Packet status after sending
• Number of data sent
• -1 on failure
• IPaddress address
• the source/dest address of apacket
• For received packages this is the IP / port of the remote part.
• For sent packages this is the IP / port to send to.

The various fields of a UDP packet is set with various function used for sending and receiving data. It might seem confusing right now, but it’ll get clearer once we get into the actual code.

Functions of SDL_net

SDLNet_Init

This function is just like SDL_Init and TTF_Init ; it initializes the SDL_net

SDLNet_UDP_Open

This function is used for creating a socket which we will use later to send data.

Parameters :

• Uint16 port – the port we want to use. If you use 0, SDL_Net will assign a port for you.

Return value :

A valid UDPsocket, NULL on error. Remember that UDPSocket is a pointer.

As we saw earlier, UDP isn’t actually a connection. All we are doing is sending data back and forth. And all we need to do that is a socket. Now that we’ve opened this socket, we can start dealing with packages.

SDLNet_ResolveHost

As stated before, we need an IP address and port number in order to send data. The problem is that there are several ways to represent IP addresses and port numbers. The difference between them is the order in which the they are converted to binary. These orders are refereed to as little endian and big endian I won’t dive more into this, but you can read about it here.

The issue is that different system use different endian. So we need a uniform way of setting the IP address and port number. This is where SDLNet_ResolveHost comes in. What it does, is that it sets the name values of an IPAdress for us so we don’t have to think about endians at all.

Parameters :

• IPaddress* address – a pointer to an IPAdress. Needs to be allocated / created in advance. ( In our case, we’ll use a variable and not a pointer so we don’t have to worry about this. )
• const char* hostIP address to send to ( xxx.xxx.xxx.xxx )
• Uint16 port – the port number to send to

Return value :

0 on success, otherwise -1. In this case, address.host will be INNADDR_NONE. This can happen if the address is invalid or leads to nowhere

SDLNet_AllocPacket

Allocates a UDP_Packet and returns a pointer to it.

Parameters :

• int size – size of the packet in bytes. 0 is invalid.

Return value :

A valid pointer to UDPpacket, NULL on error ( such as out of memory )

The size of the packet determines how much data we get every time. It’ll never be more than this size, but it can be less. You can also expect that some packages gets mfSerged or split up into different segments. This is something we’ll need to handle.

After allocation space for a packet, we can finally fill that packet up with something. Which is kinda the point of this ordeal.

SDLNet_UDP_Send

Sends a UDPpacket

Parameters :

• UDPsocket sock – Our socket to send data from ( the one we created with SDLNet_UDP_Open )
• int channel – We’ll completely ignore this parameter and just set it to -1 ( all channels )
• UDPpacket* packet – the data we want to send ( finally! )

Return value :

The number of destinations the packet was sent to. In our case, this will be 1. But it could be more. Because of this 0 is returned on errors. Anything higher than 0 means partial success ( since we were able to send to at least one destination. )

In our case, the function should always return 1 but I find it better to just check for 0.

SDLNet_AllocPacket

Now that we know how to send data, we also need to know how to recieve them.

Parameters :

• UDPsocket sock – Our socket to receive data from ( the one we created with SDLNet_UDP_Open> )
• UDPpacket* packet – the data we received

Return value :

The int value 1 when a packet is received, 0 when no packets where received, and -1 on errors.

Example

To make it simpler to use SDL_Net, I’ve made a helper class that takes care of everything. You’ll find an example at how to use it below.

Compile

To compile it on Linux or Mac. Simply run :

clang++ UDPExample.cpp -std=c++11 -lSDL2_net -o UDPTest

Starting the example

To use the example, you need two instance of the application. So start up two instances of it.

You’ll be asked to enter local IP. This is the IP of the computer you are sitting on. You can use 127.0.0.1 which simply means “this computer”. You can do this in both instances. You’ll also be asked to enter a local port and remote port. These needs to be opposite on the two instances ; the local port of the first one, needs to be the remote port of the other. This is because we need to know where to send it to and where to listen for data on.

Instance 2

( notice the difference in local and remote port on the two instances. )

Using the example

After inserting IP and port data, you’ll be presented with a simple menu :

Nothing will happen before you do one of the three options. And if your message doesn’t show up on the other instance, make sure you’ve entered ‘2’

And now you should be able to set up connections. Feel free to use the UDPConnection struct as you like.

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Standard Template Library

A major part of C++ is the Standard Template Library ( STL ). It is quite large and it contains both containers ( like vector, stack and maps ) with a lot of functionality for using these. In this post, we’ll look at one part of the STL, iterator, and in the following post we’ll look at other parts of STL like the algorithms library

Iterators

Iterators can be looked at like pointers. They reference an item in a data structure( including string ). They can also be used with streams. The iterators enables us to iterate through them using various operations like ++.

But we need different types of iterators because data structures can often be iterated in different ways. Some ways are efficient on some containers while they might be inefficient or even impossible on other containers.

Let’s take a look at the different type of iterators.

• Output iterators
• Very restricted
• Can only be written to ( not read )
• Can only move forward after writing
• Example : std::cout
• Input iterators
• Counterpart of output iterators
• Can only be read ( not written to )
• Example : std::cin
• Forward iterator
• Can do everything input iterator can do
• Can also move forward at any time
• Example : std::forward_list
• Bidirectional iterator
• Can do everything forward iterator
• Can also move backwards at any time
• Example std::list
• Random access iterator
• Can do everything bidirectional iterator can do
• Also supports random access ( [] )
• Example : std::vector and std::array

Here’s a simple overview :

The properties of the various iterators here are the bare minimum of the “pure” version of the iterators. Some implementations might support more operations.

Note that forward iterator, bidirectional iterator and random access iterator does not implement output iterators. This means that they can’t, by definition, write to the object they refer to. We’ll get back to this later.

Let’s start by looking at the first type of iterator, output iterator.

Output iterator

As mentioned earlier, output iterator is a very limited type of iterator it is also the only iterator that can write to the object.

You can’t go back with an output iterator, and you can’t iterate over the same range twice. And there is no guarantee that you can write to the same position twice without incrementing the operator. And you can’t compare two output iteratrs either. What you’re basically doing is writing into a “black hole”; you’re just writing and you can’t see what you have written.

This might seem very constrictive, there’s very little we can do. But these rules only apply in some cases, like when writing to streams, which we’ll look at later. You can look at the iterators that follows everything described above as pure output iterators

Most iterators, though implement output iterators but also has other traits that enables more functionality. We’ll look at these later.

A simple example

This is a very simple example of the intended usage for output iterators :

Or, in other words :

• Write
• Move forward
• Write
• Move forward

A bit more complex example

In C++ you have streams, which allows you to to either write or read from them using the >> and << operators. Examples of this is cout ( write ) cin ( read ). This makes cout output operators ( because they output to the terminal. )

cout is of the type ostream. You also have an iterator to this type, called ostream_iterator that can be set to an ostream Writing to this iterator writes to the ostream it’s an iterator to.

Using this knowledge, we can create an iterator to cout, this enables us to write to the terminal using an iterator

Output :

11
44
33

The ostream_iterators are output iterators. Using cout like this shows how output iterators works ; you can only write and the writing has to be sequential. You can newer go back. Once you’ve written something, you can’t “go back” and write something in the position before what you just wrote.

Input iterator

The counterpart of output iterators is input iterators. But where output iterators can only write, input iterators can read but there is also a small changes in the restrictions :

• You can compare two iterators
• Comparing two  iterators is not guaranteed to work unless at least one of them is past the end ( like std::end )
• Since you can read, you can also use the -> operator to access member variables

A simple example

The following example shows the essential use of an input iterator :

Or, in other words :

• Move forward
• Move forward

A more complex example

In the previous example, we saw that ostream_iterators are output iteratorss. Which means we can use them to write to cout. Similar to this, we have istream_iterators that are input operators. And where we can use ostream_iterators with cout, we can use istream_iterators with cin which reads input.

Here too we have to work consecutively, we can’t go back or skip ahead, we can read input in a similar to when we wrote to cout

Example input :

3
2
6
f

Output :

Write 3
You wrote 3
2
Write 2
You wrote 2
6
Write 6
You wrote 6
f

Since we’ve specified int as the template argument of the input_iterator, the input_iterator ( intReader ) will become the same as invalid, which in C++ means the iterator will point to the element past the end element. This is the same as readerEnd and the loop will terminate.

Forward iterator

If you take a look at the iterator overview above, you’ll see that the forward iterator implements input iterator. This means a forward iterator can do anything an output iterator can do.

Forward vs input operator

A forward iterator has a few extra features that input iterators don’t have. These are :

Equality check

Two forward iterators are guaranteed to compare as equal if they refer to the same element

• An input iterator can, as we saw above, be compared to another output iterator, but the operation is only guaranteed to be true  if one of them is past the end of the container

Example :

The compare operation ( it1 == it2 ) is not guaranteed to be true for  output iterators or input iterators, but it is for forward iterators 

Forward iteration

A forward iterator can also iterate forward as many times as you like before reading

• With  output iterators or input iterators we would have to read or write in between each time we iterate forward.

Example :

If we had used an output iterator or an input iterator to do the multiple iterations would have caused the iterators to become invalid.

Iteration over same range

Finally, a forward iterator can iterate over the same range twice.

• output iterators or input iterators are intended to only iterate over the same range once ( single-pass ) but are intended to be able to do this ( multi-pass )

Example :

Here we’ve effectively moved back and continued moving forward, which again would not be possible with code>output iterators or input iterators.
As you can see, using  forward iterators is in many ways more convenient than using output iterators or input iterators, but some object only has very few operations, like the streams we looked at earlier.

Luckily, most ( if not all ) structures in the C++11 supports at least the functionality of forward iterators. Most of them provide iterators that has more properties, but this time we’ll look at a structure that only provides forward iterators

Forward list

A linked list is a container that works a bit different from the array-like containers. Basically, each element has a pointer to the next element. So that all the elements are chained together using pointers. If you want to go from one element to another, you use the next pointer. This can mean a lot of operations if the list is very large.

The objects will not be one contiguous piece of memory like arrays are. This means there are no quick ways to go from the first to the last element. So if we wanted to go from Node 1 to Node 2 in the above illustration, we would have to go via Node 3. And if we wanted to go back from Node 3 to Node 1 we would have a problem. There is no pointer that goes back in a forward list. If you want to get to a previous node, you would need a pointer to an earlier element. The forard_list itself keeps a pointer to the first element in order to be able to access all elements.

A container in like this didn’t exist in C++ until C++11 which has the container forward list.

Iterating forward lists

The forward list is a great way of showing how the forward iterators works. The forward list can only be iterated forward and the forward iterator can only iterate forwards.

Let’s look at an example :

We are now at the fifth element ( 5 ), but say we want to print the previous element ( 0 )? We need to go back to the begin element and increment like above.

Output :

43 63 11 0 5 0 

Forward iterators and output iterator

• Per definition, forward iterators  does not include the properties of output iterators.
• Most implementations of forward iterators does however support assignment like output iterators. These iterator are called mutable forward iterators

Bidirectional iterator

The bidirectional iterator is very similar to forward iterator. The only different is that it also supports backwards iteration. And that’s all the difference between code>forward iterator and bidirectional iterator.

In the forward iterator section we looked at singly linked lists which has a pointer to the next element. But most linked lists also has a pointer to the previous element.These are called doubly linked lists or simply just linked list.

The container type doubly linked lists are identical to singly linked lists, with the one exception that each Node now has a pointer to the previous Node too.

The prev pointer enables us to iterate backwards, so now we need an iterator that can iterate backwards and forwards. This is where the bidirectional iterator comes in.

An example

The following example is the similar to the example for forward list but this time we solve the last problem in a different way.

We are now at the fifth element, but say we wanted to go back to the previous element? Since doubly linked lists support bidirectional iterators, we can use -- to iterate back.

-it;

Output :

43 63 11 0 5 0 

As you can see, bidirectional iterators can iterate back and forth without problems. Now let’s look at the final iterator, random access iterator.

Random access iterator

The final iterator is also the one with the most features. It can be used like a pointer. In fact, some implementations of STL uses pointers as random access iterators.

Here’s a list of the features of a random access iterator

• All the features of bidirectional itearator
• Random access
• Access items by [] operator
• it[n] returns the value of the position it + n
• it[n] is the same as *( it + n )
• Iterator arithmetics
• This means you can add or subtract integer values and iterators
• it += n moves it forward n steps
• it -= n moves it backward n steps
• it + n returns an iterator to the element n steps after it
• n - it returns an iterator to the element n steps before it
• it - it2 returns the distance between it and it2
• Iterator comparison
• This means you can check which if one iterator is before another iterator
• it1 < it2 returns true if it1 is before it2
• it1 > it2 returns true if it1 is after it2
• it1 >= it2 returns true if it1 is not before it2
• it1 >= it2 returns true if it1 is not after it2
• not it1 < it2

Array-like containers

Array like containers are all containers that are organized as a continuous piece of memory. This means you can predict where the next item is, since it the next item will always be the previous item + the size of each item. Using this knowledge, it’s easy to jump forward or backwards. An example of these containers is vector, which I covered in a previous part.

The above example shows how any array-like container ( vector, array, queue, deque, … ) is laid out in memory. Everything is in one continuous block which means we always know where the next element is.

An example

The following example shows usage of random access iterators:

Conclusion

There are several types of iterators in C++. Especially random-acces iterators can be particularly useful. We will see more of this in the next post. The next part will also introduce a few new iterators, but they are all variations of the iterators in this post.

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Memory in C++

One of the major parts of C++11 is the new smart pointers. But why do we need them, and why should you steer away from the old style pointers?

This post is intended both as an introduction, and a reference guide to the smart pointers found in C++11. It will cover what they are, how to use them and how they work.

Memory allocation in C++

C++ supports dynamic memory allocation ( new / delete ). It’s a way of creating a object whenever you need it. The object will live until you call delete on it. Otherwise it won’t be deleted, not even when it goes out of scope. And if you don’t delete it, none will, which in turns causes memory leaks. It might also cause undefined behavior ( which means anything can happen ) if, for instance, you delete something and try to use it afterwards.

Smart pointers

Smart pointers are like regular pointers, but they provide extra functionality such as automatic checks or other safety mechanisms. C++11 introduces three smart pointer types :

• unique_ptr
• Only one unique_ptr can point to the object at the time
• shared_ptr
• Several shared_ptrs can point to the object at a time.
• Object is released when no shared_ptrs point to the object
• weak_ptr
• Non-owning, needs to be converted into an shared_ptr to use the object it points to

Using smart pointers

Once you have created the smart pointer, you can use it as a regular pointer :

 -> * ! == ... 

All of the above operations are supported for the smart pointers in C++11. This is not true for weak_ptr, but we’ll get to that later.

You can also use them in ifs like this :

It will enter the if as long as the smart pointer is initialized and is managing a valid object ( meaning it’s not a NULL pointer )

We’ll now take an in-depth look at the smart pointers, one at the time.

unique_ptr

An unique_ptr is the sole owner of an object that it points to. Two unique_ptrs can also swap objects, but they can never manage the same object. And as with all smart pointers, it takes care of deleting the object.

Initialization and allocation

There are two ways of doing this, regular constructor or make_unique

constructor

The constructor is pretty straight forwards. You just set the template arguments ( in this case Foo ) and pass an allocated ( new‘ed ) object :

This is pretty straight forwards ; template parameter is the type and you supply an allocated ( new‘ed ) object.

make_unique

The second alternative is using a function named make_unique, this is in most cases better, because it constructs the object and it helps prevent errors. It also follows the naming convention ofshared_ptr which can be constructed in the same way with the make_shared method.

This is how to use make_unique :

What make_unique does is that it creates a new unique_ptr that manages a new object of the template type ( Foo in our case. ) It takes the arguments of the make_unique function itself and passes it to the constructor of the new Foo. Then the function returns the unique_ptr it created and the =operator assigns it to the unique_ptr we declared ( p2 )

This function requires C++14, it should have been included in C++11, a simple oversight lead to it not being included in the standard. But don’t worry, it’s easy to get this to compile:

• On Linux / Mac
• Change -std=c++11 to -std=c++1y in your compile command
• On Windows
• Newer versions VisualStudio should support this without you having to do anything.

If neither of the above works, you can copy-paste this :

Destruction and deallocation

Since the unique_ptr is a smart pointer, it handles deallocation automatically. In general, this means that the unique_ptr calls delete on the object it holds. This happens when :

• The unique_ptr is being destroyed.
• Happens when the unique_ptr goes out of scope.
• You set the unique_ptr to point to something else
• More on this below.

Releasing the object

Releasing the object means that the unique_ptr stops managing the object. This means you can let a regular pointer “take over” the object the unique_ptr was managing. So when the unique_ptr goes out of scope or is destroyed in any way, the pointer object it was managing wont be affected.

Here’s an example :

• fooUPtr now manages pFoo1
• pFoo1 is unchanged

• fooUPtr no longer manages the object pFoo1 points to
• pFoo2 now points to the same object as pFoo1

But now pFoo1/pFoo2 needs to be deleted. Since they both point to the same object, we just need to delete one of them :

Changing the object being pointed to / reassignment

Changing what the unique_ptr points to is quite easy. It can be done in two ways :

These are used in a similar work

And

Both of these properly deallocates the original object managed by foo1, calling its destructor in the process. Then the new object returned by new is assigned to foo1 and foo1 now manages it just like it did with the previous object.

Transferring ownership

You can’t set two unique_ptrs to manage the same object, but you can transfer ownership from one unique_ptr to another. And you can swap the managed object of two unique_ptrs.

Swapping owenership

Swapping ownership can be done in two ways ; a member function, or the std::swap() function.

Member function

The member function is very straight forwards :

std::swap

std::swap() is a very simple, but also very useful algorithm defined in the algorithm header ( until C++11 and utility since C++11 ). It basically swaps two objects of whatever type you pass as arguments. It can be two ints, two std::strings or two objects of a class/struct or anything else you want.

The version used for unique_ptrs is just an overload of this that uses the above swap( std::unique_ptr ) member function function internally. Here’s how to use it :

So in reality, the member function and swap() are identical. The result of both of these are as you would expect :

• foo1 now manages foo2
• foo2 now managesfoo1

Reseting

You can use the reset() to reset the unique_ptr This means that we change what pointer the unique_ptr manages, deleting the old one. This method can only be used with raw pointers, not smart pointers.

Example :

What this does

• Crates a new uniqe_ptr that manages a new Foo object
• Deletes the old managed Foo object and replaces it with a new one

Transfering owenership

You can use the = operator to transfer ownership :

This takes the pointer from foo2 and gives it to foo1. This means that :

• foo2 no longer handles any object ( like calling )
• This is because only one unique_ptr can manage an object at a time
• The object that foo1 was holding is deleted
• Because foo1 is going to be managing foo2

This is the same as doing :

Note that this is not the same as swapping two unique_ptr

If we swap, the result would be :

• foo1 manages foo2
• foo2 manages foo1

In this case the result is.

• foo1 manages foo2
• foo2 doesn’t manage any object

Destroying the object

When you want to destroy the object the unique_ptr manages, there are two ways you can do it:

• Destructor
• This simply means letting the unique_ptr go out of scope
• The reset() method
• You can use this with either a NULL pointer or another pointer, the managed object will get deleted in both cases

The bool operator

The bool operator dictates what happens when used in a boolean expression like if () . It will return true if the unique_ptr manages an object. If not, it’ll return false. In other words ; if, and only if, you can use it, it’ll return true, so this is exactly the same as you do when you’re checking if a pointer is NULL or nullptr

The other operators

The other operators works just like regular pointers, so I won’t discuss them here.

shared_ptr

shared_ptr is, as the name implies, a smart pointer that allows sharing. This means you can have several shared_ptrs that point to the same object. This is not permitted by unique_ptr as we saw in the previous section.

Implementation

The shared_ptr is a bit more complex than unique_ptr. This is because a shared_ptr needs to keep track of how many other shared_ptrs are managing this object, But for unique_ptrs there will always be only one pointer managing the same resource, so there is no need to keep track of the number of other unique_ptrs that are managing this object ( because it’s always just one! )

In order to keep track of this information, shared_ptr keeps a pointer to a structure called a control block. This structure has three member variables :

•  shared_ptr reference count
• How many shared_ptrs are managing to the object
• weak_ptr reference count
• How many weak_ptrs are referring to this object
• More on  weak_ptrs later
• A pointer to the object the shared_ptr manages

The shared_ptr also keeps a pointer to the object it manages. And this is where it gets a little complicated, because this pointer is closely related to the one in the control block. But why? The reason for this is a bit complicated and it has to do with the two ways of creating a shared_ptr, make_shared and constructor. I will discuss this in the next section :

Initialization

When it comes to unique_ptr, the difference between using make_unique and the regular constructor is slight ( that doesn’t mean you shouldn’t use make_unique as often as you can! ) But in a shared_ptr things are different.

As stated above, a shared_ptr has two elements : a control block and a pointer to the object it manages. Both of these needs to be allocated, but before we get into that, let’s look at how we can create a shared_ptr :

Or

Using constructor

In the first example, we first allocate Foo using new before pass it to the shared_ptr constructor. This means that the shared_ptr has no control over the allocation of Foo so all it can do is to create the control block and have it point to Foo. The figure below will show the procedure for when you create a shared_ptr using constructor :

Foo and ControlBlock allocated in two steps

As you can see, the control block and the Foo needs to be allocated in two steps. First the object, then the control bloc.

Using make_shared

But if we let make_shared handle the allocation of Foo, it can allocate both the control block and Foo in one go. It’ll look something like this :

Foo is now part of the FooControlBlock

So make_shared creates the object and the control block together in one operation. This makes the operation faster than creating them in two step, but it requires them to be one object, so here Foo is part of the control block itself.
make_shared is available in C++11 so you can use it without enabling C++14

When not to use make_shared?

There are two cases when you can’t use make_shared :

• If you are using a pointer that’s already created somewhere else
• Using make_shared means the object would be re-allocated
• Pass the pointer in the constructor instead ( where we passed  new Foo() in the example above )
• If you don’t want to use the default delete
• You can’t specify a custom deleter using make_shared
• This is a bit complicated, so I won’t go into details

Destruction and deallocation

The destructor for shared_ptr is also a bit different from unique_ptr because an unique_ptr will always be the sole manager of an object ( not other unique_ptr or shared_ptrswill be managing it. ) This means it’s always safe to delete, so that’s what the unique_ptr will do.

But when it comes to shared_ptrs, we can’t do that before we make sure that no other shared_ptrs are managing it. So what we do is that we look on the control block and how many shared_ptrs are managing it. If this is 0, we are the last owner and we can safetely delete it.

The weak_ptr reference count it not checked at this point. I’ll get into why in the next section that discusses weak_ptr and how the relate to shared_ptrs.

Changing the object being pointed to / reassignment

Similar to unique_ptrs but here we need to do some extra work. There’s two different cases for this ; setting the shared_ptr to be the same as another shared_ptr and setting the shared_ptr to manage a new pointer.

In both of these cases, it will decrement the shared_ptr reference count in the control block. And if this count reaches 0 it will delete the object being pointed to ( but not necessarily the control block, more on this later. )

Assigning to a different shared_ptr

Assigning a shared_ptr to a different shared_ptr is done using the =operator.

Here’s a simple example

Result

• The original ptr1‘s shared_ptr count is now 0, and the object it manages will be deleted
• ptr1 and ptr2 will now both manage the same object as the original ptr2 with a shared_ptr count of 2

Assigning shared_ptr to a new object

Assigning a shared_ptr to a new object/pointer is done using the reset() function :

Here’s a simple example

Result

• The shared_ptr reference count for sharedPtr is decremented as if we were calling the destructor.
• The Foo object sharedPtr was originally manging may get deleted
• sharedPtr now manages the object rawPtr points to.

As you can see from the examples, you use opeator= for reassigning to another shared_ptr but reset() for reassigning to a different raw pointer. You can’t use them the other way around. This can help prevent bugs by giving an error if the programmer uses the wrong versions.

There is a way you can use operator= to assign to a new pointer;  using make_shared to create a new object :

This works because make_shared creates and returns a fully constructed shared_ptr ( just like make_unique described above ) and the =operator assigns it just like in the example above.

Swapping

The syntax for swapping shared_ptrs is the exact same as for swapping two unique_ptrs :

Member function :

std::swap :

This will, as you would expect, swap both the control block and pointer for both the shared_ptr. It needs to swap the control block since this is what keeps tracks of the number of references to the pointer so these needs to be consistent.

The bool operator

The bool operator dictates what happens when used in a boolean expression like if () . It will return true if the shared_ptr manages an object. If not, it’ll return false. In other words ; if, and only if, you can use it, it’ll return true, so this is exactly the same as you do when you’re checking if a pointer is NULL or nullptr

This is exactly the same as for unique_ptr.

The other operators

The other operators, just like with unique_ptr, works just like regular pointers, so I won’t discuss them here.

weak_ptr

As mentioned in the introduction, weak_ptr doesn’t actually manage a pointer. It just holds a non-owning ( "weak" ) reference to an object that is managed by a shared_ptr. It also keeps a pointer to the control block ( the exact same as the one in the shared_ptr who manages the object. This means it has to be created from a shared_ptr so that it can get a pointer to the control block.

wrak_ptr and the control block

The control block, as we saw in the previous section, keeps a count of both shared_ptr and weak_ptr who’s using the object. We also saw that the object will get deleted if the count of shared_ptrs using the object is 0 regardless of how what the weak_ptrs count is. This is part of the point of weak_ptr; it is not supposed to keep objects alive except for in situations we explicitly tell it to.

But even though the managed object will get deleted if the count of shared_ptrs is 0, the control block will remain intact. The control block will only be deleted if both the conut of shared_ptr and weak_ptr uses. This is because the weak_ptr uses the control block to check if the object is alive.

Creating a weak_ptr

There are two ways of creating a weak_ptr from a shared_ptr: constructor and =operator. This is very straight forwards :

All of these will set up the pointer and the control block and increment weak count by 1.

Creating a weak_ptr from a raw pointer won’t work simply because it isn’t designed to be managing a pointer by itself. And you can’t use them with unique_ptrs because unique_ptrs are supposed to be the sole owner.

Reseting a weak_ptr

The object a weak_ptr can be reset ( so that it no longer references any object ) using the destructor or the reset() function.

Using a weak_ptr

weak_ptr has the function lock(). What this function does is that it makes a shared_ptr of itself. This shared_ptr will work exactly as any other shared_ptrs maintaining the object. It will increase the shared_ptr count, so this shared_ptr will keep the object alive.

If the object has been deleted, it will still return a shared_ptr. But this shared_ptr doesn’t point to anything, it’s essentially a nullptr. It will return false if you use it in a if or loop condition, just like a regular shared_ptr or unique_ptr that doesn’t manage an object.

This function is the crucial part of the weak_ptr. It enables us to keep weak_ptrs that refers to object maintained by a shared_ptr without preventing it from being deleted and we can still use it safely when we want.

So let’s look at an example :

Usage 1

Here everything works as intended. The weak_ptr refers to sharedPtr which has a valid object inside this scope.

• lock() returns a shared_ptr that manages the same object as sharedPtr
• The returned shared_ptr is valid so it enters the if
• While in this if, the shared_ptr, fromWeakPtr1 keeps the object alive, even if all other shared_ptr should be destroyed in other threads in the meantime

Usage 2

Our shared_ptrs has gone out of scope ( both the original and the one we created from the weak_ptr and the object has been deleted. But the weak_ptr, weakPtr still exists as it was declared out of the scope. So we try to use it again :

•  We create our shared_ptr from the weak_ptra
• The shared is created, but since the original object was deleted, this is essentially a nullptr
• The shared_ptr returns false and it doesn’t enter the if.

Leaving the scope

Finally we leave the scope and we delete weakPtr. Now the weak_ptr count will be 0 and the control block will be deleted ( shared_ptr count was already 0 )

Releasing the object

A weak_ptr can’t release the object because it doesn’t have control over it, and the object might be NULL. For this reason, weak_ptr does not have a release() function. The closest thing is the reset() function described above.

Swapping

The syntax for swapping weak_ptrs is the exact same as for swapping two shared_ptrs and code>unique_ptrs:

std::weak_ptr< Foo >( new Foo ) foo2; std::weak_ptr< Foo >( new Foo ) foo2; 

Member function :

foo1.swap( foo2 );

std::swap :

std::swap( foo1, foo2 );

This will, as you would expect, swap both the control block and pointer for both the weak_ptrs. It needs to swap the control block since this is what keeps tracks of the number of references to the pointer so these needs to be consistent.

Changing the object being pointed to / reassignment

Similar to shared_ptrs but with a few differences :

• Since we are not managing the object, we don’t need to worry about deleting it.
• It might already have been deleted at this point, but this will not cause the opeartion to fail
• Decrement count for weak_ptr, not shared_ptr
• If weak_ptr count reaches 0 and the count for shared_ptr is also 0, we delete the control block
• Now we can set the pointer to the object and control block
• Both of these will already have been created by a shared_ptr

You can create reassign a weak_ptr to both a shared_ptr and another weak_ptr

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Text styles using SDL2_ttf

In the last post we looked at how to render text. Now let’s take this a step further and change the appearance of the font. There are two ways you can change how the font looks. Font style and font outline.

Fon styles

SDL TTF allows you to set the style of the font. It supports the following font styles

• bold
• italic
• underlined
• strikthrough

You can combine these in any way you like. We’ll start off with just setting a single font style at a time, and then move on to see how we can apply several of them at once.

Font styles

Settnig font styles in TTF is easy, it just requires a single function. The function let us you set one or more font styles. Let’s start off by looking at how to set just one font style

Setting the font style

We can set the font style using the following function

Arguments :

•  TTF_Font *font – the font to set the style on
• int style       – the style to set on the font

As you can see, the style parameter is an int and not an enum. I’ll get back to why that is later, but for now let’s look at the possible values for style, these are all self-explanatory so I won’t be adding a description.

• TTF_STYLE_NORMAL
• TTF_STYLE_BOLD
• TTF_STYLE_ITALIC
• TTF_STYLE_UNDERLINE
• TTF_STYLE_STRIKETRHOUGH

Any text you render after setting this font style will have the new effect, but it won’t change any text you have written with a different style. So when you set the style to TTF_STYLE_BOLD, all text you render from that point and until you set a different style will be bold. And as long as you pass any of the above values to the function, the font will only have the one last style you set.

Let’s do a simple example

Any text rendered at this point will be normal with no font styles

Any text rendered at this point will be bold

Any text rendered at this point will be in italics, but not bold

Any text rendered at this point will be normal with no font styles

Any text rendered at this point will be underlined

As you can see, this is pretty straight forwards. So let’s make things a little bit trickier by setting multiple font styles at once. To do this, we must first look a bit at the binary number system

Binary numbers

In order to learn about how to combine these flags, we need to look at binary numbers first of all. If you don’t already know about binary numbers, you should take a look at the above link. It’s not crucial, but it is highly recommended to know a little about them. I might create a blog post about them at some point. For now, I’ll just talk a tiny bit about the binary number system. But as I said, I highly recommend understanding it fully to the point where you can convert back and forth between binary and decimal numbers

The binary number system

On a daily basis, we use the decimal number system. The binary numbers system is just a different way of representing numbers. Any numbers can be converted from any other number system. So you can convert binary numbers to decimal numbers ( and the other way around ).

A computer stores numbers as individual bits ( 0‘s and 1‘s ). They correspond to on / off or true / false.

Let’s take a look at an 8 bit binary number ( 1 byte )

1010 0101

As you can see, it has 8 digits. So that’s eight different flags. Each of these flags have two different possible values : 0 / 1 or false / true. So that’s 8 bools for the price of a single byte!

Bitwise operations

So how do we use these 8 booleans? As you know, we have the following boolean operations in C++:

• and ( && )
• or ( ||

These work on an entire variable. An int, for instance will be false if its value is 0, otherwise its true.

But there are similar operations that does this on all bits of a variable. These are called bitwise operations, simply because they operate on a simple byte. To do a bitwise operation, we need two variables of equal size ( same number of digits ), for instance two bytes. The result of a bitwise operation is a third variable of the same size. So if we do a bitwise operation between two bytes, we get a third byte back as a result.

Let’s create two bytes, we’ll use these for a few examples

Byte 1 : 0101 0011 ( 64 + 16 + 2 + 1 = 85 )
Byte 2 : 0110 0010 ( 32 + 64 + 2 = 98 )

We’ll be referring to each digit as a position. So the digits in the first position is 0 in both or bytes. In the second position it’s 1 in both bytes and in the third it’s 0 in the first byte and 1 in the second byte.

Bitwise OR

A bitwise OR operation means we look at all positions as check if either of them is 1 if so, we set the digit in that position to 0. If no digit in that position is 1, we set it to 0

The operator for bitwise OR in C++ is | ( just one |, not two )

Here is a simple example of bitwise OR between two bytes

0101 0011 OR 0110 0010 = 0111 0011

Bitwise AND

In a bitwise AND operation, we look at each position and see if both of them are 1. If so, we set the digit in that position to 1, otherwise we set it to 0. So in OR we set it to 1 if any of the two is 1, here we only set it to 1 if both are 1.

The operator for bitwise AND in C++ is & ( just one &, not two )

Here’s the a simple example :

0101 0011 AND 0110 0010 = 0100 0010 

Bitwise XOR

XOR or exclusive OR is slightly less known than OR and AND. In an XOR operation, we check if the two values are different. So this is equivalent to != in C++.

• ( true  != false ) = true
• ( true  != true  ) = false
• ( false != true  ) = true
• ( false != false ) = false

Simply put, an XOR operation is true if the two parts are different. So in a bitwise XOR operation, we look at each position and see if the two digits are different. If so we set the digit at that position to 1, otherwise we set it to 0.

The operator for bitwise XOR in C++ is !=

Here is an example :

0101 0011 XOR 0110 0010 = 0011 0001 

Bitwise NOT

We also have the a bitwise version of the NOT opeartion this is done by using the ~ operator in C++. If we used ! we would get the result of NOT on the entire variable, not the individual bits which is what we want. This operation only takes a single element and flips all bits ( turns 1‘s into 0‘s and 0‘s into 1‘s. ). Let’s test it on our two bytes

The operator for bitwise NOT in C++ is !

Byte 1 :

NOT 0101 0011 =   1010 1100

Byte 2 :

NOT 0110 0010 =   1001 1101

Setting and checking individual bits

So now that we know how to do bitwise operations, we need a way of checking and setting the individual bits. This is done simply by using OR, AND and XOR. Before we take a look at how to do this, let’s define a few values to check.

Remember that the different font styles are ints? This is because they are used to perform bitwise operations to set and unset different bits. Here they are again, this time with their values. For simplicity, I’ll only list the last four bits ( the others are always 0 ). The values are in decimal with the binary representation in parenthesis

• TTF_STYLE_NORMAL = 0 ( 0000 )
• TTF_STYLE_BOLD = 1 ( 0001 )
• TTF_STYLE_ITALIC = 2 ( 0010 )
• TTF_STYLE_UNDERLINE = 4 ( 0100 )
• TTF_STYLE_STRIKETRHOUGH = 8 ( 1000 )

As you can see, they all have only one ( or zero ) bit set. This means we can use AND, OR or XOR on just one bit.

Setting a bit

To set a bit ( without affect any other bit ) we use the ORoperation. So say that we have four bits set to 0, 0000 and we want to set the bit for bold on it ( 0001 ). In other words, we want the result 0001. What we do is : that we take our original 4 bits ( 0001 ) and set it to the original 4 bits ( 0001 ) OR‘ed with the bitmask for bold ( 0001 ) :

0000 OR 0001 ( value of TTF_STYLE_BOLD )
=
0001

Simple as that! This woks for any of the other flags in the same way. They all will end up setting one bit.

Note that this will not change any other bits. If we try set the italics font style on the above variable we get :

0001 OR 0010 ( value of TTF_STYLE_ITALIC )
=
0011 ( TTF_STYLE_BOLD and TTF_STYLE_ITALIC set )

Let’s make a simple function that adds a style to a mask.

Unsetting a bit

Sometimes we want to unset a bit. Say for instance we want to remove the italics from the font above. How do we do that without affection the other values? This is a bit more complex, because it requires two operations. What we are trying to do is the following :

Say we have a bitmask ( 0000 1011 ) and we want to unset the bit for bold text, but leave the rest unchanged. So we need to be able to go :

From 1011 to 1010

To do this, we need to use an AND operation. This is because we can’t turn of a bit using OR, and XOR would only flip it back and forth between 0 and 1

But we can’t use AND with the flag we want to unset alone, because that would keep the flag at 1 and change every other to 0!

0000 0101 AND 0000 0001 = 0000 0001

This is the opposite of what we want! Wait? Opposite you say? Well how about we use the NOT operator here to get the opposite result? This works perfectly, because NOT 0000 0001 is 1111 1110. And, as we saw earlier, doing AND 1 won’t change the element we’re AND‘ing with. So we get :

0000 0101 AND 1111 1110 = 0000 0100

Success! Only the bit we were trying to unset has changed. So let’s make a function that does this for us :

Checking a bit

To check a bit, we also need to use the bitwise AND operation. And since we are only checking and not setting, we don’t have to store the value anywhere which means we don’t have to worry about changing anything.

To check a bitmask, simply do an AND operation with the value you want to check for ( in this case, any of the TTF_STYLE_.... values ). So, to check if a text is bold, we do an AND between our mask and TTF_STYLE_BOLD :

0011 ( our bit mask, TTF_STYLE_BOLD and TTF_STYLE_ITALIC set )
AND 0001 = 0001

As you can see, we only check the bit that’s set in our variable ( TTF_STYLE_ITALIC set ) the others will be 0 no matter what our mask is. The value 0001 is not 0, and thus this evaluates to true and we now know that the font is bold.

If our mask didn’t have the bold bit set ( only the italic one ), our mask would be 0010. An AND between 0010 AND 0001 is false ( they have no bit set to 1 in common ) and the result is 0 aka false.

So let’s create a function for that too!

Conclusion

With a little knowledge about binary numbers and bitwise operations, we can easily set, add, remove and check various font styles in SDL_TTF.

Since it does involve a little low level code, I made a simple class that does the apparitions for us in a more intuitive way. I strongly suggest using this opposed to “raw” TTF_Fount*

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Rendering text

In the previous parts, we’ve look at how to render rectangles and images, both with and without transparency. Now it’s time to look at how we can render text.

Rendering text is tricky. You’ll want to be able to render any font, in any size and preferably every possible character. Luckily, with the SDL_ttf library, this is easy.

SDL2_ttf

SDL2_ttf, just like SDL2_image, is an additional library for SDL2. It can use just about every font, and you can set the size and text styling too!

What’s TTF?

TTF, or TrueType Fonts is a type of fonts developed by Apple and Microsoft in the late 90’s. True Type Fonts offers a high degree of control on how the font looks. The internals of TTF fonts and how they work isn’t important here. The important part is that they’re easy to use, will look really nice ( even scaled up. ) And they’re also widely used, so finding fonts shouldn’t be a problem.

SDL2 TTF?

As with SDL2_image, SDL2_ttf is an additional library for SDL2 that deals with rendering text and makes it very easy. It is based on libfreetype, a library for writing text using TTF fonts. However, it’s not very practical to use. SDL2_TTF makes using it a lot easier. But if you do want to use it yourself, you can take a look at their tutorial.

Setting up SDL2_TTF

Setting up SDL2 requires a tiny bit more work than SDL2_image, but don’t be scared, it’s still very easy. First we need to install the ttf library.

Installation

Installing SDL2_ttf is done exactly like SDL2_image. Just replace SDL2_image with SDL2_ttf

Here’s the short version :

Linux

For Linux you can use need to install -lSDL2_ttf or -libSDL2_ttf or -SDL2_ttf ( the actual name might be different in different distributions. )

The linker flag is -lSDL2_ttf

The process is more or less identical to that of setting up SDL2_image.

If you can’t find SDL2_ttf in any repositories and it’s not installed by default, you might have to compile it yourself. For more information, see my blog post about setting up SDL2.

Windows

Similar to setting up SDL2 base.

The difference is that you have to download the development files for SDL2_ttf

And similarly add SDL2_ttf.lib to library includes and add SDL2_ttf.lib to the library flags ( where you previously added SDL2_image.lib )

And with that, it should work.

Mac

See the first part of my tutorial. Just install SDL2_ttf instead of SDL2

Initialization

Unlike SDL2_image does need to be initialized. Why? Because libfreetype, the library that SDL2_ttf builds upon needs to be initialized, so naturally SDL_ttf needs to be initialized too.

Initializing SDL2_ttf requires a single function, TTF_Init() :

Just like SDL_Init(Uint32 flags) this function returns -1 on error, but unlike SDL_Init(Uint32 flags), this method does not have any flags.

Sine this function can fail and return -1, we should print an error if this happens. This means our routine for initializing SDL2_ttf will be the similar to SDL2, just with the two functions above :

TTF_Font

The basic object for SDL_TTF is TTF_Font. A TTF_Font basically holds information about a font like the font itself and data about styling and size. The exact internals of TTF_Fonts is only known to the library using it so I won’t go into depths about it.

The only thing you need to remember about TTF_Fonts is that they hold all information about the font that SDL_TTF needs to render it, and that they need to be loaded and unloaded ( we’ll look at this later. )

This is the central structure of SDL2_ttf. It holds the font itself, the size and some other style information ( I’ll go into this in the next part ). So, in order for us to use an TTF_Font we need to load it. This is done using a load function :

Arguments :

• const char *file – a pointer to the .ttf file
• int ptsize – the size of the font

Return value :

A pointer to the created TTF_Font<

The function returns a NULL pointer of it can’t find the file, or there is another error ( like SDL2_ttf isn’t initialized. So this too should be handled by priting the error using SDL_GetError(), just like when initializing ttf

Cleaning up fonts

Just like we with SDL_Texture*  and SDL_Surface*, we need to clean our fonts when done. This is just as easy for TTF_Fonts as with SDL_Texture*  and SDL_Surface*. We simply call a function that does it for us :

Rendering text

There are three functions you can use to render text, depending on what you want. Let’s start with the first one :

TTF_RenderText_Solid

This function is used for quick and simple rendering of a text, using a specific font and a font color. The background of this is transparent. Here’s the signature:

Arguments :

•  TTF_Font *font – the font to use
• const char *text – the text to render
• SDL_Color fg –  the color to use for the text

Return value :

A SDL_Surface with the rendered text

The function returns a NULL pointer of it can’t find the file, or there is another error ( like SDL2_ttf isn’t initialized. So this too should be handled by priting the error using SDL_GetError(), just like when initializing ttf

The result will look something like this :

TTF_RenderText_Blended

The next function is very similar to the previous one

Arguments :

•  TTF_Font *font – the font to use
• const char *text – the text to render
• SDL_Color fg –  the color to use for the text
• SDL_Color fg –  the color to use for the text

Return value :

A SDL_Surface with the rendered text

The function returns a NULL pointer of it can’t find the file, or there is another error ( like SDL2_ttf isn’t initialized. So this too should be handled by priting the error using SDL_GetError(), just like when initializing ttf

As you can see, both the arguments and return value is the same for TTF_RenderText_Solid and TTF_RenderText_Blended. So what’s the difference between TTF_RenderText_Solid and TTF_RenderText_Blended? The difference is that TTF_RenderText_Solid is very quick, but TTF_RenderText_Blended produces a better result. In our game, we won’t be updating our text surfaces all that often, and there’s not a lot of them either, so TTF_RenderText_Blended is a good choice.

Here’s what TTF_RenderText_Blended looks like :

And here’s a comparison between TTF_RenderText_Solid and TTF_RenderText_Blended :

The difference is not huge, but in the actual game it will be more clear. And the difference might also vary from font to font.

This function is a bit different from the two other ones. It will render the texture with a specified background color.

Arguments :

•  TTF_Font *font – the font to use
• const char *text – the text to render
• SDL_Color fg –  the color to use for the text
• SDL_Color bg –  the color to use for the background

Return value :

A SDL_Surface with the rendered text

The function returns a NULL pointer of it can’t find the file, or there is another error ( like SDL2_ttf isn’t initialized. So this too should be handled by priting the error using SDL_GetError(), just like when initializing ttf

So it’s almost the same as the other two, just with a fourth argument for the background color. The return value is also the same as the other two. The difference in the resulting function is that you will get a texture with a background color. The background color ( bg ) will fill the entire rect around the text. The text will be rendered on top of it with the specified foreground color ( fg ).

The result will look something like this :

An example

Below is a simple example that should run and compile out of the box. For compilation details, look below.

Compilation notes

Running it is just as simple as with SDL2_image. So that means compilation on Windows is already set up when you installed TTF

Linux / Mac

If you are compiling using the compiler, you have to add -lSDL2_ttf to the compile string like so :

clang++ main.cpp -std=c++11 -o Game -lSDL2 -lSDL2_image -lSDL2_ttf

If you want to run it, you simply do

./Game

Updated game code

I have done a bit of cleaning up in the game code. I’ve added a new Texture class for text, cleaned up include, removed ( and added ) comments, improve delta calculation++ Everything should be explained in comments, but, of course, if you have any questions of any kinds, just comment or contact me, I’ll be happy to help.

You can find the code here.

Conclusion

Text rendering can be hard, but SDL2 makes it quite easy. Just load your TTF_Fonts and you can easily get them as a SDL_Surface.

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Getting rid of SDL_Delay

Up until now, we’ve been regulating movement by just setting a delay of 16 milliseconds at the end of each frame like so :

This would work if the frames always lasted less than 1 millisecond, but they don’t. There is absolutely no grantee that the each frame will last as long as the previous one. And when the duration of each frame differs, the animation will become choppy and not smooth like we want it to be. So how can we get smooth animation?

Method 1 – our current solution

We’ve set an aim for 60 frames per second. Since there is 1000 millisconds ( ms ) in a second, each frame should take 1000 ms / 60 frames = 16 ms.Since our code is very light, we’ve just assumed that each frame takes less than 1 ms, so we’ve added a 1ms delay.

Method 2 – using delta

Another, better way we could limit framerate is to calculate delta time and use that to set the delay. Delta time is the time between each frame ( or update. )

If a frame takes 3 ms, delta will be 3 ms. In method 1 we had a 16ms delay and ignore the delta time completely. This means there would always be a 16ms delay. If the frame took 3ms, the delay would still be 16ms. This means the entire frame would take 3ms + 16ms = 19ms. If this happened often, the duration of a frame would jump up and down, and the animation would be choppy.

Using delta time, though, we could simply subtract that from the 16ms to ensure that every frame lasted exactly 16ms. So if a frame lasts 3ms the delay would be 13ms for a total of 16.

Let’s create a simple example function that takes the delta time and does the delay :

This is a valid solution, and your game will run relatively smoothly in 60 fps. You can, of course change the framerate as you please simply by 1000ms by the desired framerate to get the delay amount :

This method will produce smooth animation, but the third method shows an even better method!

Method 3 – using delta, no delay

Method 1 and 2 has worked by limiting frame rate. But why limit it? We can just skip the delay altogether and just use the delta time to adjust animation. Most modern games works this way. Since we adjust movement with delta time, it doesn’t matter if we run in 60 fps or 6000 fps. For smooth animation, this method is superior to the ones above. Waiting 16 ms between frame can make objects jump a tiny bit. And having your game run at 200fps will make a difference, even though the human eye sees 24fps as smooth.

It’s also very simple, just multiply the movement with the delta time.

Implementation of method 3

Implementing frame independent movement is quite simple, but there are a few things you need to be aware of in order to get it right.

Delta time

Probably the most important point. In order to get animations right, the delta tie needs to be accurate. Very accurate, preferably with microsecond ( µs ), or nanoseconds ( ns )

There are various ways to do this.

• The C way
• – Confusing
•   Functions takes a struct and fills it with time / date
• – Not always accurate
• – Hard to use correctly
• – Platform dependent
• No one way to do it in Linux and Winows
• + No library needed,
• + Doesn’t need C++11 support
• Boost
• – Adds and a dependency, just for time
• – Syntax can be hard to understand
• + Cross-platform
• + Does everything you need easily
• + Doesn’t need C++11 support
• C++11

In this part, we’ll be using the chrono library. I suggest using it over the old C way. If you can’t compile C++11, you can use the boost version.

chorno

chrono is the new timing library in C++11. I covered this in my previous post, and I recommend that you read it before you read on. If you choose not to read it, I will give you the short version of the various part of the chrono library :

• duration
• Holds the amount of time between two points in time
• Can be stored as any time unit ( seconds, millisconds, years, fortnights, .. )
• Can use both double and int
• time_point
• Holds a point in time
• Subtracting a time_point from another returns a duration
• Clock
• Three kinds: steady_clock, system_clock, high_resolution_clock
• Used to get current time as a time_point

Getting the delta

So here’s the code for our simple delta timer :

Using delta to calculate movements

Now that the worst part is over, it’s time for some minor details on how to implement frame independent movement.

First of all, the animated objects needs to have speed. And for better precision, we use doubles. Let’s make a simple struct for holding the speed. Our speed will have values between -1.0 and 1.0.

We also need an Update( double delta ) functions that’s used to update the position of the object.

There’s a few things wrong with this, though. First of all, delta values will be really small, and our speed is between-1.0, and 1.0 so the resulting movement will be really small. We can solve this by multiplying with a constant.

But there is a second issue here : both speed and delta are likely to do decimal numbers. So the result of the multiplication will almost always be a decimal number as well. But we just put it into an int and this means we’ll loose the decimal precision. So if the result is 0.8, we’ll end up adding 0. And if the same things happen in the next frame, we’ve “lost” 1.6 worth of movement. A whole pixel! It might seem like a small thing, but it would make the movement really choppy. So instead we introduce two new member variables to our Texture struct to hold the result of the multiplication.

Final function

Here’s our final Update function:

In Texture :

Calling it :

Conclusion

That concludes the tutorial on delta timers. I’ve made a few updates, put things into different classes and other minor improvements. The full code is too big to include in this blog post, but you can find a full zip of it here.

I’ve added a new .cpp file, so you need to add that to the compilation string if you’re using clang or gcc

clang++ main.cpp Texture.cpp -std=c++11 -lSDL2 -lSDL2_image -o Game

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

std::chrono

Today, we’ll learn how to use the chrono library. It’s used for timing functionality. It supports a variety of different operations and can be quite daunting in the beginning. The library contains several new types, but I’ll try to explain all of them shortly. But first a few practical tips that will make using std::chrono easier.

using std::chrono

For working with chrono I suggest writing using namespace std::chrono somewhere your code ( preferably at the top ). This means you don’t have to write std::chron:: in front of everything.

Is easier to read than :

Usually, using namespace statements are discouraged to avoid name collisions, but since we are writing std::chrono we could only get name collisions with items in the std::chrono library, which is less likely to happens.

Includes

To make sure everything compiles as it should, please add the headers and using to the top of your file :

I also want to point out that this guide is rather comprehensive. This is because it’s a good idea to have deep understanding how the various components of the chrono library works. Just writing this guide helped me to understand a lot of it. My hope is that it will help you too.

If you want more information, you can look at the en.cppreference documentation for chrono. This resource covers most, if not all of the features in C++11 with detailed information and good examples. It’s very useful for learning and as a reference.

Overview

Here is a quick overview of the chrono library.

I will now go over each of these components, starting with the basic one, ratio

ratio

The ratio is actually not a direct part of chrono but it’s very useful for working with chrono and just useful in general. A ratio is just that, a ratio or a fraction if you will. For example the ratio between a minute and a second is  60 / 1  since you need 60 seconds to make a minute. ration is defined in it’s own header file, simply called ratio

Definition

The class is templated. The definition looks like the following :

Even though this is a templated class, which can be complicated and hard to understand, the template arguments are quite straight forwards.

Template arguments :

• Num  – the numerator, or simply the top part of a fraction
• Denom  -is the denomerator or bottom part of fraction

These two numbers forms a fractions :

Num / Denom

Usually these numbers are dividable by 10, so you end up with numbers like 1000 or 0.001

Both variables are of the type std::intmax_t, which means they are the biggest possible type of signed int available, usually at least 64 bits. For example int64_t.

Predefined ratios

In the chrono library ticks are stored in fractions of second. A few examples :

• A second : ratio < 1 /1 >
• A second is 1 / 1 of a second.
• Can also be written as std::ratio< 1 >  since the denomerator defaults to 1
• A millisecond : ratio < 1 /1000 >
• A millisecond is 1 / 1000 of a second
• A minute : ratio< 60 /1 >
• A minute is 60 / 1 seconds.
• Can also be written as ratio< 60 > since the denomerator defaults to 1

Resource on ratios

As a part of the ratio header, there’s a lot of predefined ratios ( milli, nano, kilo, mega, … ). Because ratio is not directly a part of the chrono library ( it has other uses than just chrono ), there is no predefined values for minutes, hours, etc. There’s just the ones based on the standard units that’s used for distance or weight. You can refer to either of these using the std:: prefix. Since the ratios are not part of the chrono library, it’s just std:: and not std::chrono::.

For a full list of the predefined values, take a look at the documentation.

duration

duration( or std::chrono::duration ) is one of the basic classes of the chrono library. As the name suggests, it stores a time duration. Or a distance between to points in time if you like.

Member variables

It’s quite simple in its structure, it only has two member variables :

• rep
• an arithmetic type ( basically any unit that can hold a number ) that stores the number of ticks ( number of seconds, minutes, years, etc.. ).
• period
• a ration containing the type of unit rep stores. In effects this means “how many seconds/minutes/years,… is one tick.”

Constructing a duration

The creation of a duration is a bit complex as it involves two template arguments that sets representation type and a ratio plus the constructor.

teamplate arguments

The actual templated part looks like this :

Template parameters :

• rep – the type to hold the ticks
• Typically int or double
• ratio – the type units used by duration
• Covered above

The ratio defaults to 1 / 1, meaning seconds. The number of ticks the duration should use are sent to the constructor in the ordinary way using the parenthesis after the variable name.

To create a duration for containing seconds, you can do :

This creates a duration for holding seconds.

Other ratios

To create different durations we can use the ratio like above.  For example 10 millisecond becomes :

We can simplify this by using the predefined ratios already in C++11 :

Okay, but what about 10 minutes? This is quite similar to the above :

We do std::ratio< 60, 1 >  because a minute is 60 / 1 seconds which or simply 60 seconds. But we can’t simply this like above because there is not predefined ratio for minutes. The predefined ratios are all “clean” ratios like 1 / 100, 1000 / 1, 1 / 10,  10 / 1, etc…

Predefined durations

But there is another, even simpler way! Just like in ratio there are predefined values in duration And they’re very simple to use.

So say you wanted a duration of 10 milliseconds :

Or 10 minues :

Constructor

The duration has three major constructors

• Default, empty constructor
• Looks something like this : duration( )
• Initializes the duration
• Constructor with rep variable
• Looks something like this : duration( rep ) where red can be int, doube or similar
• Sets the internal tick variable to the variable passed in constructor
• This is the one we’ve used up until now
• Construct for other duration
• Looks something like this : duration( duration )
• Sets the internal tick variable based on the passed duration
• The = operator works in the same way
From rep type

Takes a value ( rep ) as argument and sets the ticks of the duration to it.

From other duration type

Takes a duration as argument and sets the ticks of the duration to it. Will convert between the two types of duration based on the ration. This means that if you pass a minutes duration to a seconds duration, you will get the number of minutes * 60 ( because there are 60 seconds in a minute.

Example

This creates a 10 second duration

Duration functions

Duration has a few functions, but I’ll just cover two of them now

• count
• Returns the number of ticks
• duration_cast
• Converts a duration of duration into another.

count

This function simply returns the number of ticks. So for our 10 millisecond example, this will be 10.

Code example :

Output :

duration_cast

When we’re working with two different types of durations things can get a bit weird. A simple example : what’s 3 minutes minus 36 seconds. The answer is quite simple for a human to figure out. But the results in your program needs to be a duration but which unit? Since 3:24 can’t be expressed exactly in minutes, we need to change either the 3 minutes to seconds, or the 36 seconds to minutes. Here’s where duration_cast<> comes in.

This simply casts our 3 minutes into 180 seconds. After doing that, we can simply do :

And we’ll get the result in seconds ( 144. ) If you had converted this to minutes, it would take the whole minutes and strip the seconds. Meaning you would end up with 2

Floating points

Up until now, we’ve only used integer values for representing ticks. This means we can only represent whole tick. So a duration of seconds using an int to represent ticks means it can only represent whole seconds. Consider the following code :

This will fail ( won’t compile ) because you loose precision. You could use a duration_cast to fix this, but you’ll loose the precision and end up with 0duration_cast is way of telling the compiler “yeah, I know this will loose precision, just do it!”

So instead we can create a duration of seconds represented as a double :

Output :

Count : 0.016

This is not the same as the predefined duration seconds because all the predefined durations uses int.

Unlike the previous example, this won’t fail because you don’t loose precision. In fact, you could change the ratio to store years :

This will convert the 16 ms to years. If you did yearsAsDouble.count()
you would get roughly 5.07356672 × 10^-9 ( 0.00000000507356672 ) years.

Clocks

Clocks are just objects that is used for finding the current time. They are static, which means that there will only be one of each clock type. There is also just one member function ( also static member function, now() . The function now() returns the current time as time_point. I will cover time_points later.

Clock also have a tick rate which state how accurate they are. For instance : a clock has a tick rate of seconds, it can’t be used to measure milliseconds. The tick rates are represented as ratios.

Clock types

There are three available clocks in the chrono library.

• system_clock
• Full name :  std::chrono::system_clock
• The wall clock, use this if you just want to know the current time and date
• This clock may be adjusted by either daylight saving time ( DST ) or leap seconds.
• Can be mapped to C-style points and can therefore be easily printed.
• Full name :  std::chrono::steady_clock
• This clock is monotonic, this means will never be adjusted, so it’ll never be affected by things like DST and leap seconds
• Best suited for measuring intervals
•  high_resolution_clock
• Full name :  std::chrono::high_resolution_clock
• Shortest tick available ( will be updated most often )
• Might be alias of std::chrono::system_clock or std::chrono::steady_clock, or a third, independent clock.
• This means it’s not guaranteed to be monotonic like steady_clock
• Use this for benchmarking

That’s really all you need to know about clocks, but in the next part we’ll be exploring them more.

time_point

time_point<( or std::chrono::time_point) is the central class of the chrono library. I’ll spare the implementation details for now and just say that it contains various information about the current point it in time.

Construction

The constructor for a time point looks something like this :

As you can see, its a templated class that takes both a clock, and a duration. The duration is the duration the time_point uses. This defaults to the duration of the clock ( as you can see from the  typename Clock::duration part. )

Simplified constructor

Luckily though don’t have to specify either of the arguments. So a really simple way to construct a time_point is :

You can use stady_clock or system_clock instead of high_resolution_clock.

This is equal to writing :

A bit more complex, but it means the exact same time : a time_point that uses a high_resolution_clock and has the same duration as the high_resolution_clock. I see no reason to use this method as opposed to the simpler one, but I want to explain the template arguments as well as I can.

Using custom ratio

But what if we wanted to specify our own duration? Well then we have to set the second template argument as well. Say we wanted to specify milliseconds as our duration time unit. Remember that duration has predefined constants for this.

This means we can simply do :

Full constructor

Now let’s do something even worse. Say we wanted a time_point that uses half minutes ( 30 seconds ) as the time units. I have no idea why anyone would want this, but it’s just a ( somewhat contrived ) example. As with some other examples, I do not encourage writing code like this. It’s horribly hard to read and very hard to understand unless you know the different part of the chrono libraries. Okay, here we go :

Yup, that’s a template argument, inside a template argument, inside a template argument! Don’t write code like this! If you need a specific time ratio, at least put the ratio and duration in separate objects ( I’ve shown you how to use the constructors above. ) Also make sure they’re well named like ratio30sec and duration30sec. That should give the reader at least a small hope at knowing what’s going on.

I added this example because if you understand this constructor and how it works, you understand the major parts of std::chrono

Initialization

As stated above, the static member function of clocks, now() returns a time_point of the current point in time.

That means we can just use auto to create a time_point too!

Simple as that, we’ve created a time point. The type of this object will be exactly the same as

Only it’s even simpler, and we’ve initialized it to the current point in time at the same time!

Difference between two time_points

And finally we can do some actual timing! Time points supports arithmetic operations. This means you can say time_point_x - time_point_y. This will result in a duration But what is the kind of duration. Seconds? Milliseconds? Years? Actually there is no one answer, it’s implementation defined. But the result is almost certain to be less than one second.

Since we can’t know what the resulting value is, we have two options. Say we have the following code :

And wanted to know the result of t1 - t2 Our two options are :

1. Use auto
• Nice and simple
• But we can’t control the type of result.
2. Use duration_cast
• Takes the result of t2 - t1 and casts it into a duration of milliseconds and uses it to set result
• This is a bit harder, but now we have full control over the type of duration.
• If you want higher precision, you can use microseconds or nanoseconds
• If you want higher precision, you can use microseconds or nanoseconds

Delta timer

So now let’s use all this knowledge and make a delta timer. A delta timer is used in games to tell the difference between two frames. The code is relatively simple and will show one ( of many ) ways to use the chrono library.

Notes

1. Get the current time
• We need this to calculate the difference in the next step
2. Take the dif and store it in a duration
• Stored in seconds ( since it’s the default )
• Represented as double
3. Reset time_prev
• We need this point because we always need to know the time_point of the previous frame
4. Return the results
• Finally we return the time since last frame as fractions of a second
• Can be a very small value like 0.000000001 ( 1ns )

This section just describes my reasoning for using seconds stored as double. It’s very focused around game programming and not crucial to understanding chrono.

I choose to use seconds as double here because double allows higher accuracy than int. And even though the game will almost certainly use less than 1 second on one frame, using seconds over milliseconds as time units means that the number will always be on the form 0.x. It also ensure that the delta won’t be exactly 0.

If the delta is 0 on one frame, no movement would happen ( I will get into this in the next SDL2 part ). If it only happens in one frame, the effect might not be that bad. But if it happens 100 frames in a row, that would be 100 frames without movements. And that would be bad!

So, in my opinion, it’s better to always have a delta of 0.x as it ensure that there will always be at least a tiny fraction of movement. The fact that the delta is a small number can be countered by multiplying with a great number in the function that calculates movement ( we’ll see this in the next SDL2 part too! )

Conclusion

The chrono library is very useful and makes it easy to deal with timing. It enables high precision timing, and makes it easy to find difference between two points in time. There are also other libraries that uses chrono like the threading library. I might write about the threading library later. There is also a post about timing in games coming up soon ( as mentioned in the above post. )

Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com

Introduction

In the last tutorial we learned how to load and render png files with alpha layers. This time we’re gonna dive into rotating textures.  Or more precisely ; rendering them rotated.

Today we’ll be making a simple, but working, analog clock. This will show how to rotate textures in SDL2. We’ll also improve how we represent textures

SDL_RenderCopyEx

Until now, we have been rendering using SDL_RencerCopy. But in order to rotate, we need a different function ;  int SDL_RenderCopyEx it takes a couple more arguments. I’ll try to explain all of them.

Parameters :

• renderer – the SDL_Renderer we always use for rendering
• texture  – the SDL_Texture we want to render
• srcrect  – which part of the SDL_Texture to render. null for everything.
• dstrect  – where to render it. Used exactly like in SDL_RenderFillRect)
• angle     – angle of rotation
• center    – the center of rotation
• flip      – flipping of texture ( vertical, horizontal, no flip )

Return value

• 0 on success

As you can see, the first four parameters are identical to SDL_RenderCopy you can read more about them in part 6.

Texture flip

Texture flip is represented as an SDL_TextureFlip

It is simply an enum with the following three values :

• SDL_FLIP_NONE         – don’t flip at all
• SDL_FLIP_HORIZONTAL   – flip horizontaly
• SDL_FLIP_VERTICAL     – flip vertically

For now, we will just be using SDL_FLIP_NONE.

Center of rotation

The center of rotation is given as a position seen from the top-left of the texture ( remember; in SDL 0,0 is the top-left of a texture. ) If the center of rotation is 0,0 you rotate it from the top-left corner.

Finding the center of rotation is usually quite simple, it’ll usually just be the center of the texture you are using. For a circle, like a spinning wheel, the center of rotation will simply be the center of the wheel. Or for a Tetris piece it will be the center of the Tetros piece. The center of a texture is easy to find. Since a center of any rectangle will be halfway along its x axis and halfway along its y axis, the position can be calculate as follows ;

The type of center is one we haven’t used before, SDL_Point. But an SDL_Point is simply just a struct with an x and y value.

In our case we are going to make a working analog wall clock. So we can’t rotate it around the middle ( that would be a weird clock! ) What we need to do, is find the base of the hands ( where they connect to the center of the clock )

Here is a picture of on our clock hands. The white hole in the middle is where we want the center of rotation to be. All three hands look very similar to this, all hands have a hole in the base, and all of them rotate around that point.

If you look closely at the green dots, you’ll see that the distance to the hole from either of the sides and the bottom is all the same ( three green dots. ) The green dots span the entire width of the base. So to find the center x value, we simply take half of the width. Looking at the picture, you’ll see that the distance from the bottom to the hole is the same as the distance from the sides subtract half of the width to find the y position of the hole.

So the code for finding the center of rotation will be as follows:

Putting things together

Previously we have worked with simply storing the SDL_Texture and SDL_Rect as separate objects in our main.cpp. But now we also need to store the center of rotation and the angle. So that’s four variables for each texture. With so many variables, it’s a good idea to split it into a separate struct :

We also need to change main.cpp to make the clock work :

As you can see, there is very little code needed in main since a lot of it is moved into Texture.h

Conclusion

The SDL_RenderCopyEx function can be very useful and is a very simple way of rotating textures. An by wrapping the SDL_Texture in a separate struct we can make the remaining code smaller and simpler while still keeping all the functionality we need.