【2D割草类游戏 - 01】游戏中帧率控制
游戏中的主程序通常是一个死循环,由于程序运行速度较快,如果不进行帧率控制,就会占用大量资源在无效的循环中,导致游戏卡顿,同时会使游戏在不同设备上的表现不一致。
直接使用Sleep函数
#include <windows.h>
void Sleep(DWORD ms);
// ms - 程序休眠的时间,以毫秒为单位
sleep函数传入的是毫秒,于是直接使用sleep函数就能做到对游戏的延时,计算延时为1000/帧率。但是直接使用sleep得到的仅为理论延时,并没有考虑到游戏本身的运行的时间。由于游戏中每轮循环运行的时间都不同,这样直接使用静态延时时间会导致每轮循环的时间都不同,观感上就会感觉到游戏时不时的卡顿。
使用Clock函数
#include <time.h>
clock_t clock(void);
clock函数返回自程序开始运行后处理器时钟使用的时间,如果失败返回-1
使用clock函数计算程序运行的秒数时,需要除以CLOCKS_PER_SEC
常量,该常量是处理器每秒的周期数
clock配合sleep就能达到不错的延时效果,具体为:
1.定义一个静态变量存储上一次循环的时间
2.每次循环都计算出当前循环的用时
3.用每帧间隔时间减去当前循环用时即为当前循环需要休眠的时间
这里给出一个示例函数:
// by yangw80<yw80@qq.com>, 2011-5-4
void HpSleep(int ms)
{
static clock_t oldclock = clock(); // 静态变量,记录上一次 tick
oldclock += ms * CLOCKS_PER_SEC / 1000; // 更新 tick
if (clock() > oldclock) // 如果已经超时,无需延时
oldclock = clock();
else
while(clock() < oldclock) // 延时
Sleep(1); // 释放 CPU 控制权,降低 CPU 占用率,精度 10~16ms
}
使用GetTickCount函数
#include <Windows.h>
#pragma comment(lib, "Winmm.lib")
DWORD GetTickCount();
使用该函数需要链接库
该函数返回程序自开始运行后的时间,单位是毫秒
该函数的最大返回值为49.7天,如果需要计时更长时间,还有一个64位版本的函数GetTickCount64
下面是使用示例:
static int FRAME_RATE = 144; // 游戏帧率
DWORD start_time = GetTickCount();
{
// 游戏全部逻辑
}
DWORD end_time = GetTickCount();
DWORD delta_time = end_time - start_time;
if (delta_time < 1000 / FRAME_RATE)
{
Sleep(1000 / FRAME_RATE - delta_time);
}
sleep函数的精度
Windows API函数Sleep的精度大约在10~16ms,如果要求较高,可以通过timeBeginPeriod函数临时提升Sleep的精度,需要链接库
#include <Windows.h>
#pragma comment(lib, "Winmm.lib")
MMRESULT timeBeginPeriod(
UINT uPeriod
);
MMRESULT timeEndPeriod(
UINT uPeriod
);
// uPeriod - 最小计时器分辨率,以ms为单位
使用示例:
#pragma comment(lib,"winmm.lib") // 1. 链接多媒体库
int main()
{
timeBeginPeriod(1); // 2. 临时提升 Sleep 精度为 1ms
///////////////////////////////////////
// 其它代码,期间会调用若干次 Sleep() 函数
///////////////////////////////////////
timeEndPeriod(1); // 3. 恢复 Sleep 精度
return 0;
}
评论区