![]() |
cppgfx
0.1.0
C++17 educational graphics library
|
This section of the cppgfx documentation contains many code example with the intention of teaching you how to do certain things. When learning programming, you will at one point encounter many of these problems and even if you don't, it's worth it to read through them to get a better understanding of what is happening.
This document tries to teach you programming concepts, and solutions using modern C++.
Many of the proposed solutions are not applicable if you program using plain C and you will have to write the algorithms by hand.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
cppgfx uses spdlog, which in turn uses fmt under the hood. fmt is a string formatting library that implement Python-like string formatting.
To find out how to format something, google how to do it in Python. The syntax is equivalent.
cppgfx provides the print()
and println()
functions, which will print formatted string to the console. print()
will only print the formatted string and println()
will additionally print a new-line character in order to move into the next line.
Example:
To find out how to format something, google how to do it in Python. The syntax is equivalent. Here is the original fmt documentation, but it is not so easy to read.
One last thing to note is that everything you can do with the print functions, can also be done with fmt::format()
, which is the function behind print. The difference is it returns the formatted string instead of printing to the console.
This is as easy as it sounds. Here is the simplest method:
Be careful! Removing multiple elements from an array sounds very trivial, but the devil is in the details.
Say you have a vector of objects and you want to remove all objects that match a certain condition. For example, you have an array of cars, and you want to remove all cars that have less than 100Hp. Easy, right?
array.erase(array.begin() + index)
can be used to remove an element from an array.
This loop has a significant flaw. The issue is that we are iterating over a container while modifying it. In this example, the first car is stronger, so we keep it. Now i is 1 (the second car), and it is weak, so we remove it. But now the third car shifts forward in place of the second car, leaving the array at length 4. Next, we look at the third car, which has 150Hp since it was shifted forwards. See, the third car was missed. But even worse when we look at the fourth car, we remove it too, and when we try to look at the fifth car (since the length was originally five), we get an out of bounds error since the array is only 3 elements long anymore.
This is why you should never modify a container while iterating over it.
One possible solution is to additionally move the index back to the front:
This solves the issue.
Another way using modern C++ functions:
This is very advanced and you should only use if you understand it. What happens is that we call std::remove_if
, which takes the iterator cars.begin()
, which is a pointer to the beginning of the array, and cars.end()
, which is a pointer to the end of the array. Lastly, it takes in a lambda function, which is called for every element in the array. You must return true if you want to remove the element, and false if you want to keep it. At the very end, we call cars.erase
which takes the result of std::remove_if
and the iterator cars.end()
which is a pointer to the end of the array.
This function does all of this index-shifting internally and we do not need to care about it. We can elevate our level of problem-solving to another level by not specifying WHAT to do and HOW to remove elements, instead we only provide a condition and the rest is done automatically.
At some point in time you will want to move an object around the screen. The simplest way is to move the object a specific amount of pixels every frame. A more advanced method is by giving the object a velocity and acceleration.
But all of these variants are flawed: The actual speed of the object is dependent on the framerate. In reality, the framerate will always fluctuate due to non-constant system load. This has the effect that the object will move faster and slower depending on how much work the computer has to do. Not great for games.
In this case, the position will change by Velocity-units per frame, most likely pixels/frame. But the rate of frames is not constant in the real world.
The solution is to use the elapsed frame time as a measure of how far to move the object.
The frameTime
variable can be used for this job. It represents the time that has elapsed since the last frame, in seconds.
Example:
Now, every frame, the velocity is multiplied with the time since the last frame. If a lot of time passed since the last frame, it moves a lot, and if only little time passed, the object only moves a little bit. This has the effect that the object will move the same distance every second, no matter how many frames are rendered.
The unit of the actual speed of the object now successfully changed from pixels/frame to pixels/second.
Whenever you want steady motion for something, remember to always compensate for time since you can never be sure at what rate your function is called. The frameTime
variable is your friend.