6

I program currently something with SDL2. All works fine, but I have a problem with the SDL_GetTicks() method. Normally it should return the total application time in milliseconds, but it always returns most of the time the value 0 and sometimes the value 1.

I initialized SDL with SDL_INIT_EVERYTHING flag.

The problem with the following code is the loop is too fast, so the delta time is smaller than 1 ms. Is there a method to achieve a higher precision?

#include "Application.hpp"

void Application::Initialize()
{
    int sdl_initialize_result = SDL_Init(SDL_INIT_EVERYTHING);
    if(sdl_initialize_result < 0)
    {
        std::cerr << "Failed to initialize SDL !" << std::endl << SDL_GetError() << std::endl;
    }

    window = SDL_CreateWindow("Project Unknown", 100, 100, 800, 600, SDL_WINDOW_SHOWN);
    if(window == nullptr)
    {
        std::cerr << "Failed to create  SDL window !" << std::endl << SDL_GetError() << std::endl;
    }

    last_update_time = SDL_GetTicks();
}

void Application::Dispose()
{
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void Application::Render()
{
}

void Application::Update()
{
    Uint32  current_time = SDL_GetTicks();
    Uint32  delta_time = current_time - last_update_time;


    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_QUIT:
            {
                should_close = true;
            }
            break;

            default:
            {

            }
            break;
        }
    }

    // Update game objects with delta_time

    last_update_time = current_time;
}


void Application::Run()
{
    Initialize();

    should_close = false;
    do
    {
        Render();
        Update();
    }
    while(should_close == false);

    Dispose();
}
Martin G
  • 17,357
  • 9
  • 82
  • 98
user3325226
  • 329
  • 2
  • 5
  • 10
  • 2
    Some code could help us solve the problem. – benbot Oct 18 '14 at 14:40
  • and, which use it causing you problems? what type is last_update_time? – Brad Allred Oct 18 '14 at 15:50
  • The problem is, that SDL_GetTicks() return values, that make no sense. Always 0 and sometimes 1. But in every documentation and tutorial this method should return the time in milliseconds since SDL was initialized. – user3325226 Oct 18 '14 at 15:54
  • try changing Uint32 to regular int. It works fine for me when just using int. Also, if you're compiling SDL2 for yourself, make sure there isn't a bug in the current commit. – benbot Oct 18 '14 at 20:12
  • I used a pre compiled stable build. And to change the type to int doesen't hepled :( – user3325226 Oct 18 '14 at 20:16
  • 1
    your question is entirely misleading. you state that the problem is with the return value of `SDL_GetTicks()`, but its clear from your edit that this is not the case. you should revise your question so it addresses the actual issue you are having. – Brad Allred Oct 18 '14 at 20:38
  • .. I rephrased your title and question to state that the *current* shown code works "as designed" but you need a higher accuracy. Please check if this is indeed what you want to know. – Jongware Oct 18 '14 at 22:11
  • http://stackoverflow.com/questions/16275444/how-to-print-time-difference-in-accuracy-of-milliseconds-and-nanoseconds – Ciro Santilli OurBigBook.com Apr 01 '16 at 19:58
  • This is quite ridiculous. Many libraries use the highest resolution clock available, it should be a time returned as a double. On my PC I can get it through the Windows API, through the C++ std library, or any other number of ways, yet SDL which claims to be generalised cross-platform games media library can't handle this simple task, and returns a uint32 as milliseconds. Congratulations to them and to Steam who backed them. – Zebrafish Dec 17 '16 at 16:22

2 Answers2

8

You cannot use SDL_GetTicks() if you want higher precision but there are many other alternatives. If you want to be platform independant you need to be careful though, but here is a portable C++11 example that will get you started:

#include <iostream>
#include <chrono>
typedef std::chrono::high_resolution_clock Clock;

int main()
{
    auto t1 = Clock::now();
    auto t2 = Clock::now();
    std::cout << "Delta t2-t1: " 
              << std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count()
              << " nanoseconds" << std::endl;
}

Running this on ideone.com gave me:

Delta t2-t1: 282 nanoseconds
Martin G
  • 17,357
  • 9
  • 82
  • 98
  • 2
    Entirely compiler-and-OS-dependent. Will not work under GCC, windows, or MSVC 2013, for example. – metamorphosis Feb 20 '16 at 23:05
  • 4
    It's not OS dependent, but yes you need a compiler capable of compiling C++11 which i guess you don't have. – Martin G Feb 21 '16 at 07:16
  • 2
    It actually is OS-dependent, because different OS's have different internal counters, some better than others. None of the major compilers on Windows at this point have a functioning chrono which is capable of actual nanosecond timing. – metamorphosis Feb 22 '16 at 03:43
  • 1
    `std::chrono::high_resolution_clock` is implementation-defined. Stick to `std::chrono::steady_clock` – Casey Apr 01 '20 at 14:16
3

Well, of course, you need to actually wait until >=1ms has passed before updating your last tick count

void Application::Update()
{
    Uint32  current_time = SDL_GetTicks();
    Uint32  delta_time = current_time - last_update_time;

    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_QUIT:
            {
                should_close = true;
            }
            break;

            default:
                break;
        }
    }

    if (delta_time >= 1)
    {
        // Update game objects with delta_time

        last_update_time = current_time;
    }   
}