渲染时间仅等于 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() 函数添加一点余量,让它比所需的睡眠时间少几毫秒。
我正在做一个重制马里奥 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() 函数添加一点余量,让它比所需的睡眠时间少几毫秒。