我设法创建了一个系统,允许游戏对象根据时间的变化(而不是帧数的变化)移动。为了实践起见,我现在试图强加一个FPS限制器。
我遇到的问题是游戏循环的数量是我预期的两倍。例如,如果我尝试将帧数限制为1 FPS,那么将在1秒内传递2帧 - 一个非常长的帧(~1秒)和1个极短的帧(~15毫秒)。这可以通过输出每个游戏循环之间的时间差(以毫秒为单位)来显示 - 示例输出可能是993,17,993,16 ......
我尝试更改代码,以便在FPS受限之前计算增量时间,但无济于事。
计时器类:
#include "Timer.h"
#include <SDL.h>
Timer::Timer(void)
{
_currentTicks = 0;
_previousTicks = 0;
_deltaTicks = 0;
_numberOfLoops = 0;
}
void Timer::LoopStart()
{
//Store the previous and current number of ticks and calculate the
//difference. If this is the first loop, then no time has passed (thus
//previous ticks == current ticks).
if (_numberOfLoops == 0)
_previousTicks = SDL_GetTicks();
else
_previousTicks = _currentTicks;
_currentTicks = SDL_GetTicks();
//Calculate the difference in time.
_deltaTicks = _currentTicks - _previousTicks;
//Increment the number of loops.
_numberOfLoops++;
}
void Timer::LimitFPS(int targetFps)
{
//If the framerate is too high, compute the amount of delay needed and
//delay.
if (_deltaTicks < (unsigned)(1000 / targetFps))
SDL_Delay((unsigned)(1000 / targetFps) - _deltaTicks);
}
(部分)游戏循环:
//The timer object.
Timer* _timer = new Timer();
//Start the game loop and continue.
while (true)
{
//Restart the timer.
_timer->LoopStart();
//Game logic omitted
//Limit the frames per second.
_timer->LimitFPS(1);
}
注意:我正在使用SMA计算FPS;此代码已被省略。
答案 0 :(得分:1)
问题是如何设置计时器结构的一部分。
_deltaTicks = _currentTicks - _previousTicks;
我看了几次代码并根据你如何设置定时器这似乎是问题。
在你的代码开始时走过它_currentTicks将等于0而_previousTicks将等于0所以对于第一个循环你的_deltaTicks将为0.这意味着无论你的游戏逻辑如何,LimitFPS都会行为不端。
void Timer::LimitFPS(int targetFps)
{
if (_deltaTicks < (unsigned)(1000 / targetFps))
SDL_Delay((unsigned)(1000 / targetFps) - _deltaTicks);
}
我们刚刚计算出循环开始时_deltaTicks为0,因此无论游戏逻辑中发生什么,我们都会等待整整1000毫秒。
在下一帧我们有这个,_previousTicks将等于0,_ currentTicks现在将等于大约1000ms。这意味着_deltaTicks将等于1000。
我们再次点击LimitFPS函数,但这次使用_deltaTicks为1000,这样我们等待0ms。
此行为将不断翻转。
wait 1000ms
wait 0ms
wait 1000ms
wait 0ms
...
那些等待0ms基本上是你的FPS的两倍。
您需要在游戏逻辑的开头和结尾测试时间。
//The timer object.
Timer* _timer = new Timer();
//Start the game loop and continue.
while (true)
{
//Restart the timer.
_timer->LoopStart();
//Game logic omitted
//Obtain the end time
_timer->LoopEnd();
//Now you can calculate the delta based on your start and end times.
_timer->CaculateDelta();
//Limit the frames per second.
_timer->LimitFPS(1);
}
希望有所帮助。
答案 1 :(得分:-1)
假设只有在SDL_Delay()过期时才会触发游戏循环,这不足以写:
void Timer::LimitFPS(int targetFps)
{
SDL_Delay((unsigned)(1000 / targetFps));
}
根据请求的目标FPS将游戏循环延迟适当的毫秒数?