渲染时间仅等于 fps 的一半

Render time only equal half of fps

我正在做一个重制马里奥 3 (NES) 的项目。在我的游戏循环中,我遇到了一件奇怪的事情。这是我的代码:

 while (true)
{
    if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        if (msg.message == WM_QUIT)
        {
            break;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        //Game logic
        c1++;
        _Mario.Update(1.0 / FPS);

        //Render
        _Timer.SetBeginTick();
        _LpD3dDevice9->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(102, 255, 255), 1.0f, 0);
        if (_LpD3dDevice9->BeginScene())
        {
            c2++;
            _Mario.Render();
            _LpD3dDevice9->EndScene();
        }
        _Keyboard->GetState();
        _Mario.Move(_Keyboard);
        _LpD3dDevice9->Present(0, 0, 0, 0);
        _Timer.SetCurrTick();
        _Timer.UpdateGameTIme();
        if (_Timer.ElapsedTime < (1.0 / FPS))
        {
            Sleep(1000.0 / FPS - _Timer.ElapsedTime * 1000);
        }
    }
}

更新功能:

void ImageMove::Update(float t)
{
    _Image_X += _Image_Vx * t;
    _Image_Y -= _Image_Vy * t;
    _SpriteTimer.SetCurrTick();
    _SpriteTimer.UpdateGameTIme();
    if (_SpriteTimer.ElapsedTime >= 1.0 / ANIMATE_RATE)
    {
        if (_Image_Vx > 0) _Image_Right.Next(); //change to next sprite
        if (_Image_Vx < 0) _Image_Left.Next(); // change to next sprite
        _SpriteTimer.SetBeginTick();
    }
}

渲染函数:

void ImageMove::Render()
{
    int vpx = _Image_X - 400;
    int VIEW_PORT_Y = _Image_Y + 500;
    _SpriteHandler->Begin(D3DXSPRITE_ALPHABLEND);
    if (_Image_Vy > 0 && _Image_Vx_Last > 0) _Image_Jump_Right.Render(_Image_X, _Image_Y);
    else if (_Image_Vy > 0 && _Image_Vx_Last < 0) _Image_Jump_Left.Render(_Image_X, _Image_Y);
    else
    if (_Image_Vx > 0)_Image_Right.Render(_Image_X, _Image_Y);
    else if (_Image_Vx < 0)_Image_Left.Render(_Image_X, _Image_Y);
    else if (_Image_Vx_Last < 0)_Image_Left.Render(_Image_X, _Image_Y);
    else _Image_Right.Render(_Image_X, _Image_Y);
    _SpriteHandler->End();
}

我将 c1 和 c2 放在我的游戏循环中以测量调用 Update 和 Render 的次数。我设置 fps = 60,在调试时,我让我的游戏循环 运行 5 秒,然后设置断点查看 c1 和 c2。 c1 = 320 和 c2 = 160(当然 = 1/2 c1,我有很多次 运行,所以渲染时间只调用 ~1/2 fps,我认为 fps = 60 ,它应该是 ~300 5 秒,不是吗?)。

如果我使用 F10 进行调试(在 Visual studio 上),我可以看到一个循环将执行 _LpD3dDevice9->BeginScene() 成功,而下一个循环中的 _LpD3dDevice9->BeginScene() 总是失败。

是不是错误?因为我在另一个小项目上测试过,c2 = 1/2 c1 也是。 这个问题导致我的游戏出现问题。在 Update() 函数中,我在这里更改我的精灵,并在 Render() 中绘制它,所以我总是会错过一些精灵。因为它只渲染 = 1/2 时间游戏更新。

如果出现错误我该如何修复我的游戏循环?如果这不是错误,我该怎么做才能防止丢失精灵?

P/S : 抱歉英语不好。

根据您的 DirectX 初始化,Present() 可能会同步到您显示器的垂直同步。 您放置的 Sleep() 没有错误的余地,并且 Sleep 通常不是很准确。如果它只休眠了一点,你的下一个绘制调用可能错过了下一个垂直同步,因此 Present() 将等到另一个垂直同步到来。

尝试为您的 Sleep() 函数添加一点余量,让它比所需的睡眠时间少几毫秒。