C++ 我可以在c+;上检索微秒或非常精确的毫秒吗+;在窗户上?

C++ 我可以在c+;上检索微秒或非常精确的毫秒吗+;在窗户上?,c++,windows,time,timer,C++,Windows,Time,Timer,因此,我制作了一个游戏循环,它使用SDL_Delay函数来限制每秒的帧数,如下所示: //While the user hasn't qui while( stateID != STATE_EXIT ) { //Start the frame timer fps.start(); //Do state event handling currentState->handle_events(); //Do state logic curre

因此,我制作了一个游戏循环,它使用
SDL_Delay
函数来限制每秒的
帧数,如下所示:

//While the user hasn't qui

while( stateID != STATE_EXIT )
{
    //Start the frame timer
    fps.start();

    //Do state event handling
    currentState->handle_events();

    //Do state logic
    currentState->logic();

    //Change state if needed
    change_state();

    //Do state rendering
    currentState->render();

    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
        return 1;    
    }

    //Cap the frame rate
    if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
    {
        SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
    }
}
//当用户还没有
while(stateID!=状态_退出)
{
//启动帧计时器
fps.start();
//执行状态事件处理
当前状态->处理事件();
//做状态逻辑
当前状态->逻辑();
//如果需要,请更改状态
改变状态();
//进行状态渲染
currentState->render();
//更新屏幕
如果(SDL_翻转(屏幕)=-1)
{
返回1;
}
//限制帧速率
if(fps.get_ticks()<1000/帧/秒)
{
SDL_延迟((1000/帧/秒)-fps.get_ticks());
}
}
因此,当我以每秒60帧的速度运行游戏时(我假设这是“眼罩”),我仍然可以看到滞后类型的运动,这意味着我看到独立出现的帧会导致不平滑的运动。
这是因为显然
SDL_Delay
函数不太准确,导致
+、-15毫秒
或帧之间的差异大于我想要的值。
(所有这些都只是我的假设)

所以,我只是在寻找一个好的和准确的计时器,将帮助我解决这个问题


有什么建议吗?

这是我使用
QueryPerformanceCounter
为midi序列计时创建的一个小等待函数:

void wait(int waitTime) {
    LARGE_INTEGER time1, time2, freq;

    if(waitTime == 0)
        return;

    QueryPerformanceCounter(&time1);
    QueryPerformanceFrequency(&freq);

    do {
        QueryPerformanceCounter(&time2);
    } while((time2.QuadPart - time1.QuadPart) * 1000000ll / freq.QuadPart < waitTime);
}
void wait(int waitTime){
大整数time1,time2,freq;
如果(waitTime==0)
返回;
QueryPerformanceCounter(&time1);
QueryPerformanceFrequency(&freq);
做{
QueryPerformanceCounter(&time2);
}而((time2.QuadPart-time1.QuadPart)*10000000000ll/freq.QuadPart
要将滴答声转换为微秒,请计算滴答声的差值,乘以1000000(微秒/秒),然后除以每秒滴答声的频率

请注意,有些事情可能会导致这种情况,例如,高分辨率计数器的精度不可能降至一微秒。例如,如果您希望等待10微秒,且精度/频率为每6微秒一个滴答声,那么您的10微秒等待实际上将不少于12微秒。同样,该频率取决于系统,并因系统而异


此外,Windows不是实时操作系统。进程可以在任何时候被抢占,由Windows决定何时重新调度该进程。该应用程序可以在该函数的中间被抢占,而在预期等待时间过去后很久不再重启。对此,您确实无能为力,但如果发生这种情况,您可能永远不会注意到。

这里有一个我创建的小等待函数,用于使用
QueryPerformanceCounter对midi序列计时:

void wait(int waitTime) {
    LARGE_INTEGER time1, time2, freq;

    if(waitTime == 0)
        return;

    QueryPerformanceCounter(&time1);
    QueryPerformanceFrequency(&freq);

    do {
        QueryPerformanceCounter(&time2);
    } while((time2.QuadPart - time1.QuadPart) * 1000000ll / freq.QuadPart < waitTime);
}
void wait(int waitTime){
大整数time1,time2,freq;
如果(waitTime==0)
返回;
QueryPerformanceCounter(&time1);
QueryPerformanceFrequency(&freq);
做{
QueryPerformanceCounter(&time2);
}而((time2.QuadPart-time1.QuadPart)*10000000000ll/freq.QuadPart
要将滴答声转换为微秒,请计算滴答声的差值,乘以1000000(微秒/秒),然后除以每秒滴答声的频率

请注意,有些事情可能会导致这种情况,例如,高分辨率计数器的精度不可能降至一微秒。例如,如果您希望等待10微秒,且精度/频率为每6微秒一个滴答声,那么您的10微秒等待实际上将不少于12微秒。同样,该频率取决于系统,并因系统而异


此外,Windows不是实时操作系统。进程可以在任何时候被抢占,由Windows决定何时重新调度该进程。该应用程序可以在该函数的中间被抢占,而在预期等待时间过去后很久不再重启。对此,您确实无能为力,但如果发生这种情况,您可能永远不会注意到。

请使用QueryPerformanceCounter/Frequency

LARGE_INTEGER start, end, tps; //tps = ticks per second
QueryPerformanceFrequency( &tps );
QueryPerformanceCounter( &start );
QueryPerformanceCounter( &end );
int usPassed = (end.QuadPart - start.QuadPart) * 1000000 / tps.QuadPart;

使用QueryPerformanceCounter/频率进行此操作

LARGE_INTEGER start, end, tps; //tps = ticks per second
QueryPerformanceFrequency( &tps );
QueryPerformanceCounter( &start );
QueryPerformanceCounter( &end );
int usPassed = (end.QuadPart - start.QuadPart) * 1000000 / tps.QuadPart;

我认为这方面也有类似的问题

但作为一名游戏程序员,我并不依赖睡眠函数来管理帧速率(它们所采用的参数只是一个最小值)。我只是尽可能快地在屏幕上画东西。我在我的游戏循环中有很多函数调用,然后我会记录调用它们的频率。例如,我经常检查输入(1000次/秒),以使游戏更具响应性,但我检查网络收件箱的次数不会超过100次/秒

例如:

#define NW_CHECK_INTERVAL    10
#define INPUT_CHECK_INTERVAL  1
uint32_t last_nw_check = 0, last_input_check = 0;

while (game_running) {
    uint32_t now = SDL_GetTicks();

    if (now - last_nw_check > NW_CHECK_INTERVAL) {
        check_network();
        last_nw_check = now;
    }

    if (now - last_input_check > INPUT_CHECK_INTERVAL) {
        check_input();
        last_input_check = now;
    }

    check_video();

    // and so on...
}

我认为这方面也有类似的问题

但作为一名游戏程序员,我并不依赖睡眠函数来管理帧速率(它们所采用的参数只是一个最小值)。我只是尽可能快地在屏幕上画东西。我在我的游戏循环中有很多函数调用,然后我会记录调用它们的频率。例如,我经常检查输入(1000次/秒),以使游戏更具响应性,但我检查网络收件箱的次数不会超过100次/秒

例如:

#define NW_CHECK_INTERVAL    10
#define INPUT_CHECK_INTERVAL  1
uint32_t last_nw_check = 0, last_input_check = 0;

while (game_running) {
    uint32_t now = SDL_GetTicks();

    if (now - last_nw_check > NW_CHECK_INTERVAL) {
        check_network();
        last_nw_check = now;
    }

    if (now - last_input_check > INPUT_CHECK_INTERVAL) {
        check_input();
        last_input_check = now;
    }

    check_video();

    // and so on...
}

在美国,每秒60次的成名率只是电源频率(欧洲、非洲和亚洲的50次是混合的),而且是出于硬件舒适的原因而刷新视频的频率(在更复杂的显示器上可以是整数倍)。这是CRT显示的一个强制性约束,对于LCD来说仍然是一个舒适的参考(这就是帧缓冲区上传到显示器的频率)

眼帽的速度不超过20-25 fps——不要与视网膜的持续性相混淆,大约是一半——这就是为什么每次刷新时电视都会交错两个正方形

独立地