MFC学习之新年烟花效果代码实例
2022已到尾声,不知过去的这一年你过的如何。新年将至,万象更新,有仪式感的来迎接新的一年吧!
一、EGE的介绍、安装和使用
先从EGE官网(http://www.xege.org )下载安装包文件
把安装包内 include 文件夹内所有文件,复制到你的编译器安装目录下的include目录内再把lib目录下的文件,根据自己的编译器,复制对应的东西到你的编译器安装目录下的lib目录内,具体编译器所依赖的文件情况:
本实例用的vc2015 + ege20.08,include目录:D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;lib目录:D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib。
官方的安装教程:EGE安装使用教程
二、程序设计需要注意的问题:需要考虑的内容
烟花包含多个粒子,粒子数,爆炸时粒子速度大小,粒子颜色
设置一些时间变量,用来控制烟花上升的时刻,时长和绽放的时间
上升速度和位置,这个速度需要注意坐标系里y是向下为正。
烟花初始随机设定好本次的发射位置,和时间,速度等相关属性,绽放完后重新开始。
每次都会先更新烟花位置再绘制。
考虑一下重力因素(有往下的加速度),空气阻力因素(速度衰减),爆炸时的球状散开(速度大小相等,方向不同),可以求x, y分速度。
稍微考虑一下水平动量守恒,做一对速度相反的粒子,因为是随机的,怕有时太随机了偏向一边
(1)、对烟花进行 初始化 ,设置烟花从准备到发射,再到绽放的一整个流程的参数,比如三个时间,爆炸时每个粒子的速度。
其中粒子爆炸速度比较难计算,因为要设置爆炸成球状,速度大小都是相等的,只是速度的方向不同。随机得到方向后,就 将速度投影到xOy平面上,然后想分别投影到x轴和y轴。 可以参考空间向量如何获得其两个x, y方向的分量
delayTime = rand() % 300 + 20;
riseTime = rand() % 80 + 160;
bloomTime = 160;
risePos.x = rand() % 450 + 300.0f;
risePos.y = GROUND;
riseSpeed.y = myrand(1.0f) - 3.0f; //上升速度,根据坐标系需要是负的
riseSpeed.x = myrand(0.4f) - 0.2f; //可稍微倾斜
//随机颜色
color = HSVtoRGB(myrand(360.0f), 1.0f, 1.0f);
//给每一个粒子设置初始速度
for (int i = 0; i < NUM_PARTICLE - 1; i += 2)
{
//为了球状散开,设初始速度大小相等
//初始随机速度水平角度和垂直角度,因为看到是平面的,所以求x, y分速度
double levelAngle = randomf() * 360;
double verticalAngle = randomf() * 360;
//速度投影到xOy平面
double xySpeed = particleSpeed * cos(verticalAngle);
//求x, y分速度
p[i].speed.x = xySpeed * cos(levelAngle);
p[i].speed.y = xySpeed * sin(levelAngle);
//动量守恒,每对速度反向
if (i + 1 < NUM_PARTICLE)
{
p[i + 1].speed.x = -p[i].speed.x;
p[i + 1].speed.y = -p[i].speed.y;
}
}
(2)、每一帧里对烟花的位置以及粒子的位置进行更新。上升时只更新烟花的位置就行了,因为粒子都在一起,爆炸时就要分别计算粒子的位置了。从上升到爆炸的过渡阶段,要给每一个粒子设置位置,因为之前更新的都是烟花的位置,粒子的位置没有给,设置为当前位置就好了。每一次对位置进行更新,都会将对应的时间值减1
阶段的判断:
准备阶段 :延迟时间 大于0, 不更新位置
上升阶段 :延迟时间 不大于0,并且 上升时间 大于0, 更新烟花位置,如果到达爆炸阶段,就给粒子当前位置。
爆炸阶段 :前面两个时间都不大于0,爆炸时间 大于0, 更新粒子位置
结束阶段 :前面三个时间都为0,这时就对烟花重新初始化
if (delayTime-- > 0)
return;
//处于上升阶段,只更新Fire位置
else if (riseTime > 0)
{
risePos.x += riseSpeed.x;
risePos.y += riseSpeed.y;
//重力作用
riseSpeed.y += 0.005;
//上升完毕,到达爆炸阶段
if (--riseTime <= 0)
{
//设粒子初始位置为Fire当前位置
for (int i = 0; i < NUM_PARTICLE; i++)
{
p[i].pos.x = risePos.x;
p[i].pos.y = risePos.y;
}
}
}
//Fire绽放阶段
else if (bloomTime-- > 0)
{
//粒子散开,更新粒子位置
for (int i = 0; i < NUM_PARTICLE; i++)
{
p[i].pos.x += p[i].speed.x;
p[i].pos.y += p[i].speed.y;
//重力作用
p[i].speed.y += 0.005;
//速度减慢
p[i].speed.x *= 0.982;
p[i].speed.y *= 0.982;
}
}
else
{
//Fire重新开始
init();
}
注意事项:
因为涉及模糊滤镜,又有背景图,所以不可能在有背景的窗口加模糊滤镜,这样背景会糊掉,所以只能另外设个图像缓存,在里面做。
将图像缓存绘制到窗口时,要特别注意,我们需要的是光叠加的效果,所以绘制时需要到三元光栅操作码 SRCPAINT, 即 目标图像和源图像颜色位或,这个请参考官网源文档,这个码还挺难找的,因为码很多
三、大家看效果吧,个人感觉还可以,细节问题可以多调整参数进行测试。
MFC学习之新年烟花测试实例
实例代码:https://download.csdn.net/download/u014740628/87368242
参考地址:https://www.jb51.net/article/235389.htm
相关文章
- JavaScript动画实例:转呀转
- Python类变量、实例(成员)变量和局部变量
- 【JAVA】对异常的理解及实例(不断学习,不断更新)。
- NGUI 的使用教程与实例(入门)(1 )
- Jquery中把一段html代码动态写入到DIV中(简单实例)
- 实例学习 Linux 的 cd 命令,及对内部命令的解释
- Oracle 数据库灾难性环境下恢复实例
- c#使用System.Windows.Forms.DataVisualization.Charting.dll绘制图表实例
- 《HTML5 开发实例大全》——1.16 使用< html >根元素显示文字
- 蓝牙学习笔记之实例广播数据的解析
- Java反射学习总结四(动态代理使用实例和内部原理解析)
- Redis学习手册(实例代码)
- JAVA小项目实例源码—学习娱乐小助手
- 转 pt-query-digest 使用实例
- JMeter学习-042-JMeter BeanShell 脚本应用实例之正则应用:正则提取,批量获取测试数据
- JMeter学习-026-JMeter 分布式(远程)参数化测试实例
- Java学习-039-源码 jar 包的二次开发扩展实例(源码修改)
- Selenium2学习-023-WebUI自动化实战实例-021-获取浏览器显示区域大小,通过 WebDriver 截图功能
- Selenium2学习-032-WebUI自动化实战实例-030-JavaScript 在 Selenium 自动化中的应用实例之五(高亮标示元素)
- Selenium2学习-028-WebUI自动化实战实例-026-获取页面元素值或者元素属性值
- Selenium2学习-027-WebUI自动化实战实例-025-JavaScript 在 Selenium 自动化中的应用实例之三(页面滚屏,模拟鼠标拖动滚动条)
- Selenium2学习-008-WebUI自动化实战实例-006-易迅登录之 frame 处理
- Selenium2学习-004-WebUI自动化实战实例-002-百度登录
- Qt之运行一个实例进程
- Nginx反向代理配置配置实例
- vue项目中 如何让外部引入的js模块 的this值 指向vue实例
- 路径分析之NetworkX实例
- GDI+学习笔记(九)带插件的排序算法演示器(MFC中的GDI+实例)
- 三层实例--加入信息
- 排查Java线上服务故障的方法和实例分析
- 【机器学习】神经网络BP理论与python实例系列
- NPOI2.2.0.0实例详解(九)—设置EXCEL单元格【时间格式】