You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++短时间延迟实现及Windows平台Pong游戏帧率优化咨询

问题描述

我正在通过使用windows.h库编写基础Pong游戏学习C++ Windows应用开发。但程序资源占用过高,因更新频率远超显示器刷新率,多数生成的帧无法显示。尝试用Sleep()函数延迟,但实际延迟约15ms,而理想需求是约5ms。使用timeBeginPeriod(1)和timeEndPeriod(1)提升时钟精度时出现编译错误。请问是否有其他方法小幅增加帧时间,或是将帧率设置为与显示器刷新率一致?

错误代码

#include <windows.h>

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){
   timeBeginPeriod(1);
   while (game_running){
       // main code goes here
       Sleep(1);
   }
   timeEndPeriod(1);
}

编译错误

undefined reference to __imp_timeBeginPeriod 和 undefined reference to __imp_timeEndPeriod


解决方案

1. 修复timeBeginPeriod的编译错误

timeBeginPeriod和timeEndPeriod属于winmm.lib库,编译时必须链接该库:

  • 若使用VS编译器,在项目设置的「附加依赖项」中添加winmm.lib;
  • 若使用g++编译,添加链接参数-lwinmm。

另外注意:你提供的代码中timeBeginPeriod(1)和Sleep(1)缺少分号,这也会导致编译失败,需要补全。

2. 实现帧率与显示器同步(推荐方案)

比起手动加延迟,更合理的方式是让游戏帧率和显示器刷新率绑定,彻底避免无效渲染,同时降低资源占用,有两种可行方式:

方式一:开启垂直同步(VSync)

如果使用DirectX渲染,创建SwapChain时开启垂直同步选项,每次调用Present时会自动等待显示器垂直刷新,将帧率锁定到显示器刷新率。

方式二:手动计算帧间隔

通过高精度计时器计算每帧耗时,然后等待到目标帧时间,精准匹配显示器刷新率:

#include <windows.h>

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){
    // 获取主显示器当前刷新率
    DEVMODE dm;
    dm.dmSize = sizeof(DEVMODE);
    EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
    DWORD refreshRate = dm.dmDisplayFrequency;
    // 计算单帧目标耗时(毫秒)
    const DWORD targetFrameTime = 1000 / refreshRate;

    LARGE_INTEGER freq, start, end;
    QueryPerformanceFrequency(&freq);
    double ticksPerMs = (double)freq.QuadPart / 1000;

    while (game_running) {
        QueryPerformanceCounter(&start);

        // 游戏逻辑、渲染代码
        // ...

        QueryPerformanceCounter(&end);
        DWORD elapsedMs = (DWORD)((end.QuadPart - start.QuadPart) / ticksPerMs);
        // 等待到目标帧耗时
        if (elapsedMs < targetFrameTime) {
            Sleep(targetFrameTime - elapsedMs);
        }
    }
    return 0;
}

3. 替代Sleep的高精度延迟方案

如果确实需要小于15ms的延迟,除了timeBeginPeriod,还可以用CreateWaitableTimer实现高精度等待(无需依赖winmm.lib):

void HighPrecisionSleep(DWORD ms) {
    HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);
    LARGE_INTEGER li;
    li.QuadPart = -( (__int64)ms * 10000 ); // 转换为100纳秒单位的相对时间
    SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE);
    WaitForSingleObject(timer, INFINITE);
    CloseHandle(timer);
}

内容的提问来源于stack exchange,提问作者Daniel Wilson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:25:04