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

news2024/11/26 10:31:20

🎆音乐分享 

New Boy —— 房东的猫


 

之前都用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

这是因为 

 

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

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

timeEndPeriod(1);

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

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

解决方法如下

 

 把winmm.lib添加到附加依赖项中

 当然,绘制画面也得加上下面的函数

BeginBatchDraw();
EndBatchDraw();

 🚥🚥🚥🚥🚥🚥

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

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

#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!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/333117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day3——有关java运算符的笔记

今天主要学习的内容有java的运算符 赋值运算符算数运算符关系运算符逻辑运算符位运算符&#xff08;专门写一篇笔记&#xff09;条件运算符运算符的优先级流程控制 赋值运算符 赋值运算符&#xff08;&#xff09;主要用于给变量赋值&#xff0c;可以跟算数运算符相结合&…

【✨十五天搞定电工基础】基本放大电路

本章要求1. 理解放大电路的放大作用和共发射极放大电路的性能特点&#xff1b; 2. 掌握静态工作点的估算方法和放大电路的微变等效电路分析法&#xff1b; 3. 了解放大电路输入、输出电阻和电压放大倍数的计算方法&#xff0c;了解放大电路的频率特性、 互补功率放大…

八、STM32串口通信

目录 一、串口通信 1.1串口通信物理层 1.2USB转串口模块 1.3串口通信的其他应用 1.4串口数据包的基本组成 二、串口的结构体与函数讲解 2.1串口讲解 2.2结构体讲解 2.3串口初始化函数讲解 三、串口发送字符 3.1如何配置串口的发送 3.2项目实战 四、串口的中断接收 …

一文搞懂 什么是CPU上下文?为什么要切换?如何减少切换?

最近经常有小伙伴问到的一些问题&#xff0c;比较集中的是关于CPU切换. 实际用C/C&#xff0c;go开发&#xff0c;你会特别注意内存和CPU的使用情况&#xff0c;那些对于CPU使用情况特别关注&#xff0c;或者性能特别关注的朋友可以看看这篇文章&#xff0c;相信看完结尾的示例…

二、Linux文件 - Open函数讲解实战

目录 1.Open函数讲解 2.open函数实战 2.1 man 1 ls 查询Shell命令 2.2 man 2 open 查看系统调用函数 2.3项目实战 2.3.1O_RDWR和O_CREAT 2.3.2O_APPEND的用法 1.Open函数讲解 高频使用的Linux系统调用&#xff1a;open write read close Linux自带的工具&#xf…

C语言实现五子棋(n子棋)

五子棋的历史背景&#xff1a; 五子棋起源于中国&#xff0c;是全国智力运动会竞技项目之一&#xff0c;是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子&#xff0c;下在棋盘直线与横线的交叉点上&#xff0c;先形成五子连珠者获胜。五子棋容易上手&#xff0c…

c/c++开发,无可避免的文件访问开发案例

一、缓存文件系统 ANSI C标准中的C语言库提供了fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等标准函数&#xff0c;这些函数在不同的操作系统中应该调用不同的内核API&#xff0c;从而支持开发者跨平台实现对文件的访问。 在Lin…

【九宫格坐标排列 Objective-C语言】

一、这个案例做好之后的效果如图: 1.这个下载是可以点击的,当你点击之后,弹出一个框,过一会儿,框框自动消失,这里变成“已安装” 2.那么,我现在先问大家一句话:大家认为在这一个应用里面,它包含几个控件, 3个,哪3个:一个是图片框,一个是Label,一个是按钮, 这…

python学习笔记-查看数据结构、均值、中位数、分位数、众数、离中趋势(标准差、方差、求和、偏态系数、风险系数)正态分布pdf、cdf、ppf

①引入pandas包&#xff0c;命名为pd。 import pandas as pd ②读入HR.csv数据 dfpd.read_csv(“./data/HR.csv”) ③查看是什么结构 type(df) ④查看单个类别satisfaction_level的数据结构 type(df[“satisfaction_level”]) ⑤查看均值的数据结构 type(df.mean()) …

运行Whisper笔记(1)

最近chatGPT很火&#xff0c;就去逛了一下openai的github项目。发现了这个项目。 这个项目可以识别视频中的音频&#xff0c;转换出字幕。 带着一颗好奇的心就尝试自己去部署玩一玩 跟着这篇文章一步步来进行安装&#xff0c;并且跟着这篇文章解决途中遇到的问题。 途中还会遇…

男,26岁,做了一年多的自动化测试,最近在纠结要不要转行,求指点。?

最近一个粉丝在后台问我&#xff0c;啊大佬我现在26了&#xff0c;做了做了一年多的自动化测试&#xff0c;最近在纠结要不要转行&#xff0c;求指点。首选做IT这条路&#xff0c;就是很普通的技术蓝领。对于大部分来说干一辈子问题不大&#xff0c;但是发不了什么财。如果你在…

第015天:将APP发布到应用商店(完结)

应用已经开发出来了&#xff0c;下一步我们需要思考推广方面的工作。那么如何才能让更多的用户知 道并使用我们的应用程序呢&#xff1f;在手机领域&#xff0c;最常见的做法就是将程序发布到某个应用商店中&#xff0c;这 样用户就可以通过商店找到我们的应用程序&#xff0c;…

前端修行 - 与后端配合的那些事情

最近总结一下个人作为前端&#xff0c;与后端、测试、以及产品经理、UI设计之间配合的那些事情&#xff0c;想到哪里说到哪里 1 关于正确认识项目研发一号位都是后端的这个事情 项目研发一号位&#xff0c;在有的公司可能会叫做SDM&#xff08;software development manger&am…

springboot 接入websocket实现定时推送消息到客户端

目录说明代码实现说明 如标题&#xff0c;举例需求场景&#xff1a; 前端与后端websocket连接上后&#xff0c;多用户登录&#xff0c;后端根据不同用户定时发消息给前端用于展示 代码实现 1、 <dependency><groupId>org.springframework.boot</groupId>…

vit-pytorch实现 MobileViT注意力可视化

项目链接 https://github.com/lucidrains/vit-pytorch 注意一下参数设置&#xff1a; Parameters image_size: int. Image size. If you have rectangular images, make sure your image size is the maximum of the width and heightpatch_size: int. Number of patches. im…

git:详解git rebase命令

背景 今天无意中打开 git 官网&#xff0c;发现 git 命令还是很多的&#xff0c;然而我们常用的就那几个&#xff0c;今天来学习一个也不怎么常用的命令 rebase 官网链接 都说学一个东西最好的方式就是读他的 官方文档&#xff0c;这里我读了一遍&#xff0c;把一些核心的地…

读书思考:步步惊心的《技术陷阱》

《技术陷阱》这本书450页&#xff0c;43万字之巨&#xff0c;信息量密密麻麻&#xff0c;采集的资料极其丰富&#xff0c;复习了一遍大停滞、大分流、大平衡、大逆转时代&#xff0c;并展望未来。看完了有很多想法&#xff0c;随手写了下来&#xff0c;希望不是蹭热点。&#x…

vue 最详细教学篇(一)

文章目录前言前景Vue 的长期技术支持 (LTS)、终止支持 (EOL) 及其延长版服务学习vue 要掌握那些技能-为什么学习 vue走进vueHello World 起手提示&#xff1a;示例&#xff1a;示例解析编辑器 VSCodevsCode 插件正式使用 vue.js要使用 vue 就绕不开生命周期 下面是生命周期图&a…

全国青少年编程等级考试scratch一级真题2022年9月(含题库答题软件账号)

青少年编程等级考试scratch真题答题考试系统请点击电子学会-全国青少年编程等级考试真题Scratch一级&#xff08;2019年3月&#xff09;在线答题_程序猿下山的博客-CSDN博客_小航答题助手1点击绿旗&#xff0c;下列哪个选项可以实现播放马叫声并在声音全部播放完后&#xff0c;…

Java常见数据结构的排序与遍历(包括数组,List,Map)

数组遍历与排序 数组定义 //定义 int a[] new int[5]int[] a new int[5];//带初始值定义 int b[] {1,2,3,4,5};赋值 //定义时赋值 int b[] {1,2,3,4,5};//引用赋值 a[6] 1 a[9] 9 //未赋值为空取值 //通过下表取值&#xff0c;从0开始 b[1] 1 b[2] 2遍历 Test p…