前提是为Dev-C++配置EGE绘图库,详见
Dev-C++ 使用EGE绘图库编程入门 https://blog.csdn.net/cnds123/article/details/109982100
灿烂烟花程序的目录结构:
背景图片:
背景音乐自己找个吧,文件名 背景音乐.mp3
燃放烟花.cpp 文件内容如下:
- #include
- #include
- #include "fireworks.cpp"
- #include "fireworks.h"
- #define NUM_FIREWORKS 12 //烟花数量,12左右比较好,多了太密集
-
- int main()
- {
- initgraph(860, 660, INIT_RENDERMANUAL);
-
- srand((unsigned)time(NULL));
-
- //烟花
- Fireworks* fireworks = new Fireworks[NUM_FIREWORKS];
-
- //背景图(860 x 660)
- PIMAGE bgPimg = newimage();
- getimage(bgPimg, "背景图片.jpg");
- //先绘制一下,不然前面有空白期
- putimage(0, 0, bgPimg);
- delay_ms(0);
-
- //背景音乐
- MUSIC bgMusic;
- bgMusic.OpenFile("背景音乐.mp3");
- bgMusic.SetVolume(1.0f);
- if (bgMusic.IsOpen()) {
- bgMusic.Play(0);
- }
-
-
- //图像缓存, 因为要加背景图,直接加模糊滤镜会把背景图模糊掉
- //所以另设一个图像缓存来绘制烟花并加模糊滤镜,再绘制到窗口
- PIMAGE cachePimg = newimage(860, 660);
-
- //计时用,主要用来定时检查音乐播放
- int timeCount = 0;
-
- for (; is_run(); delay_fps(60))
- {
- //隔1秒检查一下,如果播放完了,重新播放
- if ((++timeCount % 60 == 0) && (bgMusic.GetPlayStatus() == MUSIC_MODE_STOP)) {
- bgMusic.Play(0);
- }
- //更新位置
- for (int i = 0; i < NUM_FIREWORKS; i++) {
- fireworks[i].update();
- }
-
- //绘制背景
- putimage(0, 0, bgPimg);
-
- //绘制烟花到图像缓存中
- for (int i = 0; i < NUM_FIREWORKS; i++) {
- fireworks[i].draw(cachePimg);
- }
-
- //模糊滤镜,拖尾效果
- //第二个参数,模糊度,越大越模糊,粒子也就越粗
- //第三个参数,亮度,越大拖尾越长
- //可以试试一下其它参数搭配,例如以下几组:
- //0x03, 0xff
- //0x0b, 0xe0
- //0xff, 0xff
- imagefilter_blurring(cachePimg, 0x0a, 0xff);
-
- //缓存绘制到窗口,模式为(最终颜色 = 窗口像素颜色 Or 图像像素颜色), 这样颜色会叠加起来
- putimage(0, 0, cachePimg, SRCPAINT);
-
- }
-
- delete[] fireworks;
-
- delimage(bgPimg);
- delimage(cachePimg);
-
- bgMusic.Close();
-
- closegraph();
-
- return 0;
- }
fireworks.cpp 文件内容如下:
- #include
- #define SHOW_CONSOLE
- #include "fireworks.h"
-
- const double Fireworks::particleSpeed = 3.0f;
-
- Fireworks::Fireworks()
- {
- init();
- }
-
- void Fireworks::init()
- {
- 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;
- }
- }
- }
-
- void Fireworks::draw(PIMAGE pimg)
- {
- //未开始
- if (delayTime > 0)
- return;
- //烟花上升阶段
- else if (riseTime > 0) {
- setfillcolor(color, pimg);
- //画四个点,这样大一些
- bar(risePos.x, risePos.y, risePos.x + 2, risePos.y + 2, pimg);
- }
- //烟花绽放阶段
- else {
- setfillcolor(color, pimg);
- for (int i = 0; i < NUM_PARTICLE; i++) {
- bar(p[i].pos.x, p[i].pos.y, p[i].pos.x + 2, p[i].pos.y + 2, pimg);
- }
- }
- }
-
- //更新位置等相关属性
- void Fireworks::update()
- {
- if (delayTime-- > 0)
- return;
- //处于上升阶段,只更新烟花位置
- else if (riseTime > 0) {
- risePos.x += riseSpeed.x;
- risePos.y += riseSpeed.y;
-
- //重力作用
- riseSpeed.y += 0.005;
-
- //上升完毕,到达爆炸阶段
- if (--riseTime <= 0) {
- //设粒子初始位置为烟花当前位置
- for (int i = 0; i < NUM_PARTICLE; i++) {
- p[i].pos.x = risePos.x;
- p[i].pos.y = risePos.y;
- }
- }
- }
- //烟花绽放阶段
- 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 {
- //烟花重新开始
- init();
- }
- }
fireworks.h 文件内容如下:
- #pragma once
-
- #ifndef FIREWORKS_H_
- #define FIREWORKS_H_
-
- #include
-
- #define myrand(m) ((float)rand() * m / 36565)
-
- struct Speed {
- double x, y;
- };
-
- struct Pos {
- double x, y;
- };
-
- struct Particle
- {
- Pos pos;
- Speed speed;
- };
-
-
- #define GROUND 580 //地面位置
-
- class Fireworks//烟花类
- {
- private:
-
- static const int NUM_PARTICLE = 200;
- static const double particleSpeed;
- Particle p[NUM_PARTICLE];
-
- color_t color;
-
- int delayTime; //延迟时间
- int riseTime; //上升时间
- int bloomTime; //爆炸时间
-
- Pos risePos; //上升阶段位置
- Speed riseSpeed; //上升速度
-
- public:
- //初始化
- Fireworks();
-
- void init();
-
- //更新位置等相关属性
- void update();
-
- //根据属性值绘画
- void draw(PIMAGE pimg = NULL);
- };
-
- #endif // ! FIREWORKS_H_
使用菜单命令“Execute -> Compile”编译之,
若没有错误,得到可执行程序:燃放烟花.exe
新建一个文件夹,我这里是“灿烂烟花发布”,将前面得到的可执行程序“燃放烟花.exe”,和资源文件,这里是 “背景音乐.mp3” 和 “背景图片.jpg” 复制到,这个文件夹中。然后复制“灿烂烟花发布”文件夹给好朋友试试吧。
双击“燃放烟花.exe”,运行效果如下:
OK !