If you’re enjoying this tutorial, please consider supporting it by purchasing a book through one of the links on my site, such as this one ->
This is part of an ongoing series where we write a complete 2D game engine in C++ and SFML. A new tutorial is released every Monday. You can find the complete list of tutorials here and download the source code from the projects GitHub page.
In this tutorial we are going to delve into the world of bits and bitwise operations. We will create a bitmask class that will be useful throughout our games engine (including in our input system that we will be starting in the next tutorial).
As we will be jumping straight into discussing operations we can perform on bits, it may be helpful to refresh your memory on what bits actually are. I recommend reading this tutorial.
Bitwise operations are any operations performed on ints and unsigned ints at the binary level, that change the values of individual bits.
It is easiest to explain what bitwise operators are by providing examples of each operation, therefore the table below outlines the bitwise operators we can make use of in C/C++ and provides an example of each one. I’ll provide additional examples when we discuss the implementation of our Bitmask class.
WHAT IT DOES
The result contains a bit only if it exists in both
0011 & 1010 = 0010
The result contains a bit if it exists in either
0011 | 1010 = 1011
XOR (Exclusive OR)
The result contains a bit if it exists in one but not both
0011 ^ 1010 = 1001
The bits are shifted left by the amount specified.
0011 << 2 = 1100
The bits are shifted right by the amount specified.
1010 >> 2 = 0010
Inverts/flips the bits i.e. 0 becomes 1 and 1 becomes 0
~1010 = 0101
You may notice that some bitwise operators look similar to there logical counterparts (for example & vs &&, and | vs ||), and they do perform a similar function just on a smaller scale.
Start by creating a class called Bitmask. This class will handle all of our bit manipulation.
1. We use uint32_t, a fixed-width 32-bit integer, to store our bitmask. This ensures that no matter what operating system our game is run on, it will always be 32 bits wide. More information on fixed-width integers can be found here.
1. Sometimes it is easier to explain how something works with an example.
Let’s say we call GetBit(2), so we want to know the true/false value of the bit at position 2. Let’s also assume the bitmask is 0101. The actual bitmask is 32 bits wide but for the example we’ll keep it simple and use 4 bits.
2. To set a bit to 1 we use the same shift to set a bit at the correct position as we did in the previous example, however this time we OR the result with our bitmask. For example, let’s say we call SetBit(1) and the bitmask is 0101:
We then OR with our bitmask. This will have one of two actions; firstly if our bitmask does not have a bit set in the position 1 then our new bitmask will not have that bit set (as we are using an OR), or if we already had the bit set the OR will do nothing and our bitmask will remain the same.
3. Clearing a bit uses the shift again, but this time we invert its bits, using ones complement, before creating a new bitmask by ANDing the result with our current bitmask. For example, let’s say we call ClearBit(0) and the bitmask is 0101:
Our new bitmask has the bit at position 0 converted from 1 to 0.
These are the only methods we’ll need for the foreseeable future, although as with everything we write at this stage, we will probably be extending it in future.
It may not be too obvious how we are going to make use of this class at the moment, but we will shortly find out as we look at creating an input system for our game engine.
As always, if you have any suggestions for what you would like covered or are having any trouble with the code then let me know in the comments.
Thank you for reading 🙂