Точность SDL_GetTicks() ниже уровня миллисекунды

В настоящее время я программирую что-то с SDL2. Все работает нормально, но у меня проблема с методом SDL_GetTicks(). Обычно он должен возвращать общее время приложения в миллисекундах, но в большинстве случаев он всегда возвращает значение 0, а иногда и значение 1.

Я инициализировал SDL с флагом SDL_INIT_EVERYTHING.

Проблема со следующим кодом заключается в том, что цикл слишком быстрый, поэтому дельта-время меньше 1 мс. Есть ли способ достичь более высокой точности?

#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();
}

person user3325226    schedule 18.10.2014    source источник
comment
Некоторый код может помочь нам решить проблему.   -  person benbot    schedule 18.10.2014
comment
и какое использование вызывает у вас проблемы? какой тип last_update_time?   -  person Brad Allred    schedule 18.10.2014
comment
Проблема в том, что SDL_GetTicks() возвращает бессмысленные значения. Всегда 0, а иногда и 1. Но в каждой документации и руководстве этот метод должен возвращать время в миллисекундах с момента инициализации SDL.   -  person user3325226    schedule 18.10.2014
comment
попробуйте изменить Uint32 на обычный int. Он отлично работает для меня, когда я просто использую int. Кроме того, если вы компилируете SDL2 для себя, убедитесь, что в текущем коммите нет ошибки.   -  person benbot    schedule 19.10.2014
comment
Я использовал предварительно скомпилированную стабильную сборку. А поменять тип на int не помогает :(   -  person user3325226    schedule 19.10.2014
comment
ваш вопрос полностью вводит в заблуждение. вы заявляете, что проблема связана с возвращаемым значением SDL_GetTicks(), но из вашего редактирования ясно, что это не так. вам следует пересмотреть свой вопрос, чтобы он касался реальной проблемы, с которой вы столкнулись.   -  person Brad Allred    schedule 19.10.2014
comment
.. Я перефразировал ваш заголовок и вопрос, указав, что показанный текущий код работает так, как задумано, но вам нужна более высокая точность. Пожалуйста, проверьте, действительно ли это то, что вы хотите знать.   -  person Jongware    schedule 19.10.2014
comment
stackoverflow.com/questions/16275444/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 01.04.2016
comment
Это довольно смешно. Многие библиотеки используют часы с самым высоким доступным разрешением, это должно быть время, возвращаемое как двойное. На моем ПК я могу получить его через Windows API, через стандартную библиотеку C++ или любым другим способом, но SDL, который утверждает, что является обобщенной медиа-библиотекой кросс-платформенных игр, не может справиться с этой простой задачей и возвращает uint32 как миллисекунды. Поздравляем их и Steam, который их поддержал.   -  person Zebrafish    schedule 17.12.2016


Ответы (2)


Вы не можете использовать SDL_GetTicks(), если вам нужна более высокая точность, но есть много других альтернатив. Если вы хотите быть независимым от платформы, вам нужно быть осторожным, но вот переносимый пример C++11, который поможет вам начать:

#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;
}

Запуск этого на ideone.com дал мне:

Delta t2-t1: 282 nanoseconds
person Martin G    schedule 30.10.2014
comment
Полностью зависит от компилятора и ОС. Например, не будет работать под GCC, Windows или MSVC 2013. - person metamorphosis; 21.02.2016
comment
Это не зависит от ОС, но да, вам нужен компилятор, способный компилировать С++ 11, которого, я думаю, у вас нет. - person Martin G; 21.02.2016
comment
На самом деле это зависит от ОС, потому что разные ОС имеют разные внутренние счетчики, некоторые лучше, чем другие. На данный момент ни один из основных компиляторов для Windows не имеет функционирующего хронографа, который способен измерять наносекунды. - person metamorphosis; 22.02.2016
comment
std::chrono::high_resolution_clock определяется реализацией. Придерживайтесь std::chrono::steady_clock - person Casey; 01.04.2020

Ну, конечно, вам нужно подождать, пока не пройдет> = 1 мс, прежде чем обновлять последний счетчик тиков.

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;
    }   
}
person Gunther Van Butsele    schedule 30.10.2014