EasyX精准帧率控制&&打气球小游戏

音乐分享 

New Boy —— 房东的猫


EasyX精准帧率控制&&打气球小游戏_第1张图片

 

之前都用Sleep()来控制画面帧率,忽略了绘制画面的时间

如果绘制画面需要很长的时间,那么就不能忽略了。

并且Sleep()函数也不是特别准确,那么就要精准控制帧率了

开始时间 结束时间 频率F

LARGE_INTEGER startCount,endCount,F;

 获取计数器累加频率

QueryPerformanceFrequency(&F);

获取当前的计数值

QueryPerformanceCounter(&startCount);//获取起始计数,并保存在startCount里面

获取终止计数

QueryPerformanceCounter(&endCount);

 计算时差

long long elapse=(endCount.QuadPart-startCount.QuadPart)*1000000/F.QuadPart;//根据LARGE_INTEGER的定义,elapse必须是long long 类型的

 查询是否超时

while (elapse < 1000000 / 60){//最长等待时间为60帧每秒

	Sleep(1);//先休眠1ms,防止CPU使用率过高
    QueryPerformanceCounter(&endCount);
    elapse = (endCount.QuadPart - startCount.QuadPart) * 1000000 / F.QuadPart;
		
}

这时候如果执行代码会发现,虽然我们指定了Sleep(1),但是还是休眠了15ms

这是因为 EasyX精准帧率控制&&打气球小游戏_第2张图片

 

要解决这个问题,就要加上 

timeBeginPeriod(1);//改变定时器时钟分辨率为1ms

timeEndPeriod(1);

 这里如果运行的话会报错,因为

timeBeginPeriod()和 timeEndPeriod()的实现在 库winmm.lib中

解决方法如下

EasyX精准帧率控制&&打气球小游戏_第3张图片 

EasyX精准帧率控制&&打气球小游戏_第4张图片 把winmm.lib添加到附加依赖项中

EasyX精准帧率控制&&打气球小游戏_第5张图片 当然,绘制画面也得加上下面的函数

BeginBatchDraw();
EndBatchDraw();

 

下面咱们来看一个打气球小游戏,把上面的帧率控制代码进行实操

//看着气球在画面中是分散的,其实可以把他们想象成是在一个数组里面的,然后进行操作
#include
#include
#include

#define WIDTH 800//窗体宽度
#define HEIGHT 600//窗体高度
#define NUM 5//窗体中的气球数量
#define RADIUS 30//气球半径

//保存气球的各项数据
typedef struct {
	int x;
	int y;
	int r;//半径
	int v;//速度
	COLORREF color;
}balloon;

//生成气球,并初始化
balloon generateBalloon()//因为arrBalloons[]是balloon类型的,所以generateBalloon()也应该是balloon类型的
{
	balloon b;
	int m, n;
	m = 100;
	n = 700;
	b.x = rand() % (n - m + 1) + m;
	b.y = HEIGHT;
	b.r = RADIUS;
	m = 1;
	n = 3;
	b.v = rand() % (n - m + 1) + m;
	b.color = RGB(rand() % 256, rand() % 256, rand() % 256);
	return b;
}

int main()
{
	initgraph(WIDTH, HEIGHT);
	setbkcolor(WHITE);
	cleardevice();

	balloon arrBalloons[NUM];//保存目前窗体出现的气球数量

	for (int i = 0; i < NUM; i++)//给每一个气球赋值(大小,颜色)
	{
		arrBalloons[i] = generateBalloon();
	}

	int current = NUM;//当前出现的气球数量
	int mouseX = 0, mouseY = 0;//鼠标位置

	timeBeginPeriod(1);
	LARGE_INTEGER startCount, endCount, F;
	QueryPerformanceFrequency(&F);

	BeginBatchDraw();
	while (1)
	{
		QueryPerformanceCounter(&startCount);

		cleardevice();
		for (int i = 0; i < NUM; i++)//绘制气球
		{
			setfillcolor(arrBalloons[i].color);
			solidcircle(arrBalloons[i].x, arrBalloons[i].y, arrBalloons[i].r);
		}

		for (int i = 0; i < NUM; i++)//移动气球
		{
			arrBalloons[i].y -= arrBalloons[i].v;
		}

		int i = 0;
		while (i < current)
		{
			int y = arrBalloons[i].y;
			if (y < -RADIUS)//气球飞出窗体
			{
				for (int j = i; j < current - 1; j++)//删除飞出的气球
				{
					arrBalloons[j] = arrBalloons[j + 1];
				}
				current--;
			}
			else
			{
				i++;
			}
		}
		if (current < NUM)//新增气球
		{
			arrBalloons[current] = generateBalloon();
			current++;
		}

		//绘制准心
		setlinecolor(RGB(237, 178, 29));
		setlinestyle(PS_SOLID, 3);
		circle(mouseX, mouseY, 20);
		line(mouseX - 20, mouseY, mouseX + 20, mouseY);//准心使用了mouseX,mouseY,便于准心可以与鼠标指针一起移动
		line(mouseX, mouseY - 20, mouseX, mouseY + 20);

		QueryPerformanceCounter(&endCount);
		long long elapse = (endCount.QuadPart - startCount.QuadPart) * 1000000 / F.QuadPart;
		while (elapse < 1000000 / 60)//最长等待时间为60帧每秒
		{
			Sleep(1);

			ExMessage msg;
			bool isOK = peekmessage(&msg, EX_MOUSE);
			if (isOK = true)
			{
				if (msg.message == WM_MOUSEMOVE)//鼠标移动消息
				{								//更新鼠标位置
					mouseX = msg.x;
					mouseY = msg.y;
				}
				else if (msg.message == WM_LBUTTONDOWN)//鼠标点击消息
				{
					int i = 0;
					while (i < current)
					{
						int ballX = arrBalloons[i].x;
						int ballY = arrBalloons[i].y;
						int distance = (int)sqrt(pow(ballY - msg.y, 2) + pow(ballX - msg.x, 2));
						if (distance < RADIUS)//如果点击到了气球,就把气球删除
						{
							for (int j = i; j < current - 1; j++)
							{
								arrBalloons[j] = arrBalloons[j + 1];
							}
							current--;
						}
						else
						{
							i++;
						}
					}
				}
			}

			QueryPerformanceCounter(&endCount);
			elapse = (endCount.QuadPart - startCount.QuadPart) * 1000000 / F.QuadPart;
		
		}
		FlushBatchDraw();
	}
	EndBatchDraw();

	timeEndPeriod(1);
	
	closegraph();
	return 0;
}
//看着气球在画面中是分散的,其实可以把他们想象成是在一个数组里面的,然后进行操作

Code over!

你可能感兴趣的:(EasyX,c语言,c++,开发语言)