Viser innlegg med etiketten chrono. Vis alle innlegg
Viser innlegg med etiketten chrono. Vis alle innlegg

tirsdag 8. juli 2014

Contents of this blog

Contents


Below you'll find a list of all the tutorials with a list of part and a short description of each part.

Game programming in SDL2


A tutorial about making games. Focuses a lot on SDL 2, but also other topics related to game programming. Some parts are pretty extensive so that you'll get a deeper understanding about what's going on.

Part 1 - Setting up SDL 2


This part gives you a quick introduction to SDL 2. It'll help you set up SDL2 including header files, linking and everything you need to get SDL 2 up and running. It also contains a bare-boned SDL2 program.

Part 2 - Your first SDL 2 application


Here we take a look at the two basic structs of SDL 2, SDL_Window and SDL_Renderer. It'll help you understand what these do and how to initialize them and the basics of SDL2 correctly. We also take a look at how to set the render color ( which also works as background color )

Part 3 - Drawing rectangles


Here we take a look at SDL_Rect and how to render it with SDL_RenderDrawRect and SDL_RenderFillRect.

Part 4 - Making things happen


About events in SDL 2. How to get the events, how the event structure, SDL_Event laid out, and how we do we handle the event.

Part 5 - Collision detection and our first game!


We learn how to check for collisions and make a simple game out of it.

Part 6 - Let's load some textures!


In this part we take a look at SDL_Textures and how to create them from image files ( bmp. ) We also look at how to render SDL_Textures.

Part 7 - Using PNG files


We look at, and set up, SDL_Image library. This is used to load png files which then can be rendered with the transparency layer.

Part 8 - It's TIME for another update!


Here we look at a new rendering function, SDL_RenderCopyEx. The function lets us render textures rotated. We use it to make a simple analog clock.

Part 9 - No more delays!


Up until now we've used SDL_Delay to limit framerate to ~16 FPS. We look at how to render using a delta time.

Part 10 - Text Rendering


Text rendering in games can be tricky. Luckily, SDL2_TTF does this for us. This part talks about SDL2_TTF, how to set it up and how to use it.

C++11 Features


A series about the new features of C++11. I will try to explain everything thoroughly and extensively. The goal is to learn about C++11, how the various parts of it works and why you should use them.

I will cover both minor features like enum classes and larger ones like chrono


Part 1 - Enum classes


This is a very short part about the new version of enums, enum classes. It covers what they are and why you should use them as much as possible

Part 2 - Timing with chrono


This part is very extensive and covers the new timing features of C++11, chrono. It will help you when you're dealing with timing in games and other applications.

My SDL2 Tutorial part 9 ( No more delays! ) also deals with chron but this part covers it more extensively.

Part 3 - Smart pointers in C++11


About smart pointers in C++11 ( unique_ptr, shared_ptr and weak_ptr ) what they are, how they work and how to use them. You should always use smart pointers unless you have a really good to.

mandag 7. juli 2014

[ C++11 - Part 2 ] Timing with chrono

std::chrono


The chrono library is a new part of C++11. It's used for timing functionality. It supports a variety of different operations and can be quite daunting in the beginning. I wrote a little about it in the previous part of my SDL2 tutorial, but I thought I'd add some more details and try to explain things a bit more throughly here. 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.

Some helpful tips


My first recommendation is that you write using namespace std::chrono somewhere your code ( preferably at the top ). Usually, using namespace statements are discouraged to avoid name collisions, but this is less likely to occur when you write using namespace std::[something] where something can be anything like string or cout or indeed chrono. The reason why we use this is quite simple. If we didn't use it, we'd end up with code with std::chrono all over the place. It's a lot easier ( at least for me ) to read

time_point p = high_resolution_clock::now();

Than it is to read

std::chrono::time_point p = std::chrono::high_resolution_clock::now();

Includes


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

#include
#include

using namespace std::chrono: // So we don't have to write std::chrono everywhere!

About this part


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 to.

If you want more information, you can look at the en.cppreference documentation for chrono.

en.cppreference covers most, if not all of the features in C++11 with details 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 genera. ration is define in it's own header file, simply called ratio

The class is self is template. The definition looks like the following :

template
<
    std::intmax_t Num,
    std::intmax_t Denom = 1
>
class ratio;
Even though this is a templated class, which can be complicated and hard to understand, this one is quite simple. The first part ( Num )is the numerator, or simply the top part of a fraction. And naturally, the second one, ( Denom ) is the denomerator. 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.

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

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.
  • period
    • a ration containing the type of unit rep stores. In effects this means "how many seconds is one tick."

Constructing a duration


The constructor for a duration is rather complex as it involves both rep ( the type of the variable to hold the tick ) And setting the period i.e. how long each tick is ( millisecond, second, minute, ... )

The actual constructor looks like this :
template
<
    class Rep,
    class Period = std::ratio<1>
>
class duration;
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

So to create a duration for containing seconds, you can do :
duration< int64_t > durSec( 10 );
This duration is for 10 seconds. Nice and simple!

To create different durations we can use the ration like above.  For example 10 millisecond becomes :
duration< int64_t, std::ratio< 1, 1000 > > durMSec( 10 );
Okay, but how about 10 minutes? This is quite similar to the above :
duration< int64_t, std::ratio< 60, 1 > > durMin( 10 );

We do std::ratio< 60, 1 > because a minute is 60 / 1 seconds which is the same as 60 seconds.

As I mentioned above, there are predefined ratios already in C++11. So you can simplify a duration of 10 milliseconds to :
duration< int32_t, std::milli > dur( 10 );
But there is an 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 :
milliseconds mSec( 10 );

Member functions


Duration has a few functions, but I'll just cover two of them now
  • count
    • Returns the number of ticks (rep , see the documentation above )
  • duration_cast 
    • Converts a duration of duration into another.

    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.

    minutes min( 3 );
    seconds sec( 36 );
    minutes minToSec = duration_cast< std::chrono::seconds > ( min );
    This simply casts our 3 minutes into 180 seconds. After doing that, you can simply do

    seconds result = minToSec - sec;
    And you'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 :

    Create a duration of milliseconds represented as int :
    duration< int32_t, std::milli > msAsInt( 16 );c
    This is equal to the std::milliseconds

    Create a duration of seconds represented as int :
    duration< int32_t, std::ratio< 1, 1> > secAsInt( msAsInt );c
    This is equal to std::seconds. 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 0. duration_cast is way of telling the compiler "yeah, I know this will fail loose precision, just do it!"

    Create a duration of seconds represented as a double :
    duration< double, std::ratio< 1, 1> > secAsDouble(msAsInt);
    This is not the same as std::seconds because std::second uses int. If you did secondsAsFloat.count() you would get 0.016, because ticks are stored in a double.

    Unlike the previous line, this won't fail because you don't loose precision. In fact, you could change the std::ratio to store years :
    duration< double, std::ratio< 60 * 60 * 24 * 365, 1 > > yearsAsDouble( millisecondsAsInt ); // 0.016 sec
    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


    In order to set the time for a time_point you use clocks. Clocks are just object that has a starting point ( or epoch ) and a tick rate. The starting point is often 1.1.1970 ( UNIX timestamp ) and the tick rate can be 1 second for instance.

    There are three available clocks in the chrono library.
    • 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.
    •  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
      • 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

    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 :

    template
    <
        class Clock,
        class Duration = typename Clock::duration
    >
    class time_point;
    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 n = typename Clock::duration part. ) Luckily though don't have to specify either of the arguments. SO a really simple way to construct a time_point is :
    high_resolution_clock::time_point timePoint1;
    You can use stady_clock or system_clock instead of high_resolution_clock.

    This is equal to writing :
    time_point < high_resolution_clock > timePoint1;
    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.

    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 :
    time_point < high_resolution_clock, milliseconds >
    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 librarer. Okay, here we go :
    time_point
    <
        high_resolution_clock,
        std::chrono::duration
        <
            int64_t,
            std::ratio
            <
                30,
                1000
            >
         >
    >
    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 ration, at least put the ration 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.

    Functions


    With that out of the way, let's move on to some functions, shall we? Well actually there's just one member function in the three different clocks :
    now()
    The function returns the current time as a time_point. As a time_point, you say? Well that means we can just use auto to create one!
    auto time = high_resolution_clock::now()

    Simple as that, we've created a time point. The type of this object will be exactly the same as
    high_resolution_clock::time_point timePoint1;

    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


    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 :

    clock::time_point t1 = std::chrono::system_clock::now() ;
    // ...
    clock::time_point t2 = std::chrono::system_clock::now() ;

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

    1. Use atuto
      •  auto result = t2 - t1 ;
        • Nice and simple
        • But we can't control the type of result.
    2. Use duration_cast
      •  milliseconds result =  duration_cast< milliseconds > ( t2 - t1 ) ;
        • 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.


      For a full list of my tutorials / posts, click here.

      Feel free to comment if you have anything to say, any suggestion or any questions. I always appreciate getting comments.


      fredag 20. juni 2014

      [ SDL2 - Part 8 ] It's TIME for another update!

      Introduction


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

      Today e'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.

      SDL_RenderCopyEx
      (
         SDL_Renderer* renderer,
         SDL_Texture* texture,
         const SDL_Rect* srcrect,
         const SDL_Rect* dstrect
         const double angle,
         const SDL_Point* center,
         const SDL_RendererFlip flip
      )

      • 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. ) So a center of 0,0 will mean you rotate it from the top-left corner.

      Finding the center of rotation is usualy 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 retris 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 rect of the texure.
      // Assume it is filled out with pos(x, y) and size( w, h )
      SDL_Rect textureRect;
      SDL_Point center;

      // Calculate center pos by setting
      // ->x pos to half of witdh
      // ->y pos to half of height
      center.x = textureRect.w / 2;
      center.y = textureRect.h / 2;

      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.


      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 something like this :


      // Assume textureRect is filled out with pos and size
      SDL_Rect textureRect;
      SDL_Point textureCenter;

      int halfWidth = textureRect.w / 2;
      textureCenter.x = halfWidth;

      // Center.y  = half of the width above texture bottom.
      textureCenter.y = textureRect.h - halfWidth;

      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 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 full code can be downloaded here.


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

      For a full list of my tutorials / posts, click here.