我已经创建了一个系统,允许游戏对象根据时间的变化(而不是帧数的变化)移动。为了练习的缘故,我现在正试图强加FPS限制器。
我遇到的问题是,是游戏循环数量的两倍,比我预期的要多。例如,如果我试图将帧数限制为1个FPS,那么在这一秒内就会有两个帧--一个非常长的帧(~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;这段代码被省略了。
发布于 2013-09-03 14:36:34
这个问题是如何设置计时器结构的一部分。
_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 at,而不管游戏逻辑中发生了什么。
在下一个框架中,_previousTicks将等于0,而_currentTicks现在将大约等于1000 On。这意味着_deltaTicks将等于1000。
我们再次命中了LimitFPS函数,但这次的_deltaTicks值为1000,这使得我们等待0ms。
这种行为会像这样不停地翻转。
wait 1000ms
wait 0ms
wait 1000ms
wait 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);
}希望这能有所帮助。
发布于 2013-09-03 13:44:42
假设只有在SDL_Delay()过期时才触发gameloop,那么只编写以下内容是不够的:
void Timer::LimitFPS(int targetFps)
{
SDL_Delay((unsigned)(1000 / targetFps));
}要根据请求的目标FPS将游戏延迟正确的毫秒数吗?
https://stackoverflow.com/questions/18593506
复制相似问题