关于游戏帧率的总结
看一下以下几种游戏循环:
// 方法1
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
if(bActive && !bPaused)
{
this_tick=GetTickCount();
if(this_tick-last_tick>GAME_DELAY)
{
last_tick=this_tick;
GameLoop();
}
}
}
//方法2
int count=0;
int fps=0;
float this_tick,last_tick;
last_tick=GetTickCount();
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
if(bActive && !bPaused)
{
this_tick=GetTickCount();
if(this_tick-last_tick>=1000)
{
last_tick=this_tick;
fps=count;
count=0;
}
else
count ++ ;
Sleep(delay_time);
GameLoop();
}
}
// ·方法3
float fps=30;
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
if(bActive && !bPaused)
{
this_tick=GetTickCount();
if(this_tick-last_tick>1000/fps)
{
last_tick=this_tick;
GameLoop();
}
}
}
方法3 还可以根据实际情况在游戏里动态地修改FPS。(据说有种技术就是根据屏幕上的精灵数来动态计算FPS的)
//方法4
影响游戏速度的最大因素是什么?我认为主要是往屏幕上贴图片的速度。而游戏逻辑----处理各种精灵的逻辑不会占用很多的时间。为了不使图象刷新的快慢影响精灵的逻辑速度,我们把二者分开,也就是说,精灵---或者说整个游戏逻辑---的逻辑不再受图象刷新速度的制约,而受它自身的制约----对,我们为每个精灵加一个它自己拥有的FPS-----其实应该叫逻辑处理时间间隔。而对于图象刷新呢?我们就可以不限制它,而让它以最高的速度来刷新自己!
看一下我在别人的一份原代码里读到的东西:
“通观整个流程,作者确实没有对游戏逻辑进行时间限制(直接地),但是精灵的移动是跟时间有关系的----而且作者特地把时间单位从毫秒转换为秒----通常都在0.00f---0.005f---这就使得角色的移动受到了限制。而对于屏幕图象刷新,作者没做任何限制。------对了,这就是那种把游戏逻辑和图象显示分开的方法。!哈哈~我也想的是这样的方法!
这里有个注意的地方:在每一次游戏循环中,都有这么一句:
if( time > 0.05f ) time = 0.05f;
而角色的移动为:m_xv += m_xa * time; m_x += m_xv * time; 这样看来,显然当游戏运行速度慢时----大部分时间都用消耗在刷新屏幕上---time 就会增大,角色的运动步长就会增加----看上去就角色的移动就不是很平滑了,反应到屏幕上,那就会出现图象跳动的现象,但是他限制了time的最大值,也就是限制了图象跳动的最大范围,相反,如果游戏运行速度足够快,我们看到的角色的运动就会越平滑!对,就是这个意思。但是我觉得更好的方法是为每一个角色设置其自己的逻辑处理时间间隔-----就相当于FPS---即每次要处理角色逻辑时,看其时间间隔是否满足限制,满足的话就更新其逻辑,不满足的话就不更新,而画面的刷新上还是一直刷。“
确实,timeGetTime()的精确度比GetTickCount() 要高一些。
#include <iostream>
#include <windows.h>
#pragma comment(lib,"winmm.lib")
#define GETTICKCOUNT
//#undef GETTICKCOUNT
int main()
{
float last_time,this_time;
#ifdef GETTICKCOUNT
last_time=GetTickCount();
#else
last_time=timeGetTime();
#endif
Sleep(100);
#ifdef GETTICKCOUNT
this_time=GetTickCount();
#else
this_time=timeGetTime();
#endif
std::cout << "last_time=" << last_time << std::endl;
std::cout << "this_time=" << this_time << std::endl;
std::cout << "this_time-last_time=" << this_time-last_time << std::endl;
return 0;
}
Kevin Lynx
2006-4-5