服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++实现动态烟花效果

C++实现动态烟花效果

2022-09-01 11:40Zlb_Rose C/C++

这篇文章主要介绍了利用C++实现的放烟花程序,用到了EGE图形库,文中的示例代码讲解详细,对我们学习C++有一定帮助,需要的可以参考一下

一、前言

C++实现的放烟花程序

用到了EGE图形库,没有的需要自行安装

可调项:背景图和背景音乐、粒子模糊度、亮度以及上升速度的参数。

实现的动态烟花非常好看,可以做给女朋友或者表白用hhh

自己做出来玩玩也挺有意思的

二、代码

fire.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#pragma once
#ifndef  FIREWORKS_H_
#define FIREWORKS_H_
#define myrand(m) ((float)rand() * m / 36565)
#include <graphics.h>
 
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_

main.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
在这里插入代码片
#include <time.h>
#include <graphics.h>
#include "fire.h"
#define NUM_FIREWORKS 10    //烟花数量
int main()
{
    initgraph(1080, 720, INIT_RENDERMANUAL);
    srand((unsigned)time(NULL));
    //烟花
    Fireworks* fireworks = new Fireworks[NUM_FIREWORKS];
    PIMAGE bgPimg = newimage();
    getimage(bgPimg, "夜晚.jpg");
    //先绘制一下,不然前面有空白期
    putimage(0, 0, bgPimg);
    delay_ms(0);
    //背景音乐
    MUSIC bgMusic;
    bgMusic.OpenFile("MELANCHOLY.mp3");
    bgMusic.SetVolume(1.0f);
    if (bgMusic.IsOpen()) {
        bgMusic.Play(0);
    }
    
    //图像缓存, 因为要加背景图,直接加模糊滤镜会把背景图模糊掉
    //所以另设一个图像缓存来绘制烟花并加模糊滤镜,再绘制到窗口
    PIMAGE cachePimg = newimage(800, 800);
    
    //计时用,主要用来定时检查音乐播放
    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);
        //imagefilter_blurring(cachePimg, 0x03, 0xff);
        //imagefilter_blurring(cachePimg, 0x0b, 0xe0);
        //imagefilter_blurring(cachePimg, 0xff, 0xff);
        //imagefilter_blurring(cachePimg, 0x01, 0xff);
        imagefilter_blurring(cachePimg, 0x0b, 0xff);
        //缓存绘制到窗口,模式为(最终颜色 = 窗口像素颜色 Or 图像像素颜色), 这样颜色会叠加起来
        putimage(0, 0, cachePimg, SRCPAINT);
    }
    delete[] fireworks;
    delimage(bgPimg);
    delimage(cachePimg);
    bgMusic.Close();
    closegraph();
    return 0;
}

fire.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <cmath>
#define SHOW_CONSOLE
#include "fire.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();
    }
}

三、实现效果

由于烟花是动态的,截图出来不是很好看,但是做出来动态的烟花其实是很好看的,大家可以去试试

C++实现动态烟花效果

到此这篇关于C++实现动态烟花效果的文章就介绍到这了,更多相关C++烟花内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_45813739/article/details/121566058

延伸 · 阅读

精彩推荐
  • C/C++C语言中一些将字符串转换为数字的函数小结

    C语言中一些将字符串转换为数字的函数小结

    这篇文章主要介绍了C语言中一些将字符串转换为数字的函数小结,分别为atoi()函数和atol()函数以及atof()函数,需要的朋友可以参考下...

    C语言教程网6822021-03-07
  • C/C++C++实例输入多行数字到数组

    C++实例输入多行数字到数组

    这篇文章主要介绍了C++实例输入多行数字到数组的相关资料,这里提供实例代码帮助大家学习理解,需要的朋友可以参考下...

    marcusxu3752021-04-21
  • C/C++浅析C++标准库元组(tuple)源码

    浅析C++标准库元组(tuple)源码

    这篇文章主要介绍了C++标准库元组(tuple)源码,介绍了什么是元组以及用法,并进行了源码分析,需要的朋友可以参考下...

    独立风华9662021-03-05
  • C/C++QT串口通信的实现方法

    QT串口通信的实现方法

    如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用到qt中的串口通信了。本文介绍了QT串口通信的实现方法,感兴趣的小伙伴们可以...

    菜头大大5122021-11-08
  • C/C++C++ CTreeview的checkbox使用方法

    C++ CTreeview的checkbox使用方法

    这篇文章主要介绍了C++ CTreeview的checkbox使用方法的相关资料,需要的朋友可以参考下...

    C++教程网10992021-02-28
  • C/C++C++实现raw_input的方法

    C++实现raw_input的方法

    这篇文章主要介绍了C++实现raw_input的方法,通过C++来实现Python中发raw_input的方法,非常具有实用价值,需要的朋友可以参考下...

    C++教程网8562021-02-04
  • C/C++C++从txt文件中读取二维的数组方法

    C++从txt文件中读取二维的数组方法

    今天小编就为大家分享一篇C++从txt文件中读取二维的数组方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    申小远10482021-06-28
  • C/C++C++实现链表版本通讯录

    C++实现链表版本通讯录

    这篇文章主要为大家详细介绍了C++实现链表版本通讯录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    素心暮年6522021-08-09