渲染时间仅相当于fps的一半

时间:2015-10-22 09:35:55

标签: c++ game-physics directx-9

我正在制作一个重拍马里奥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分钟,shoudn&#t; tt?)。

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

是错误吗?因为我已经测试了另一个小项目,c2 = 1/2 c1。 这个问题在我的游戏中引起了问题。在Update()函数中,我在这里更改了我的精灵,并在Render()中绘制它,所以我总是想念一些精灵。因为它只渲染= 1/2次游戏更新。

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

P / S:抱歉英语不好。

1 个答案:

答案 0 :(得分:0)

根据您的DirectX初始化,可能会将Present()同步到监视器的vsync。 您放置的Sleep()不会留下任何错误,睡眠通常不是很准确。如果它只睡了一会儿,你的下一个绘图调用可能只是错过了下一个vsync,因此Present()会等到另一个vsync到来。

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