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