C++实现动态烟花代码
某一个轩 人气:0写在前面
首先,祝大家新年快乐!
即将迎来新的一年——癸卯兔年,祝大家成绩、事业“兔”飞猛进,必定红红火火!
在这篇文章中,将用烟花致以大家最好的祝福!
烟花代码将会用到 Easyx 图形库,可以去官网下载:easyx.cn
代码思路
1 烟花结构体
2 初始化烟花
3 烟花上升
4 烟花爆炸
5 绘制烟花
不需要任何图片、音效(本来想加的,你要加自己加吧)
开始编写
提前声明:代码纯原创!
需要用到的头文件以及宏:
#include <graphics.h> #include <math.h> #include <time.h> #include <stdio.h> #define MAXNUM 15 #define WIDTH 640 #define HEIGHT 480 #define PI 3.1415926
graphics.h Easyx图形库
math.h 计算烟花位置
time.h 选取随机种子
stdio.h 标准输入输出头文件
MAXNUM 烟花数量
WIDTH , HEIGHT 窗口的宽、高
PI 圆周率常量,结合数学库计算烟花位置
1 烟花结构体
定义的参数如下:
nowx , nowy 现在坐标
endy 爆炸高度
radio 爆炸半径
explode 爆炸进度
rgb[3] 烟花颜色rgb值
color 烟花颜色
struct Fire { int nowx; int nowy; int endy; int radio; int explode; int rgb[3]; COLORREF color; }fire[MAXNUM];
2 初始化烟花
nowx , nowy 窗口外的随机位置
endy 随即高度
radio 随即半径
explode 一开始设为0
rgb[3] 一些特定的颜色随机取
color 按照rgb值
void Init() { for (int i = 0; i < MAXNUM; i++) { fire[i].nowx = rand() % WIDTH; fire[i].nowy = HEIGHT + rand() % 250 + 50; fire[i].endy = rand() % 100 + 10; fire[i].radio = rand() % 50 + 120; fire[i].explode = 0; int c[][3] = { {255, 0, 0}, {210, 190, 255}, {255, 120, 0}, {255, 0, 150}, {255, 240, 100}, {10, 255, 255}, {160, 10, 255}, {255, 200, 60} }; int n = rand() % 8; fire[i].color = RGB(c[n][0], c[n][1], c[n][2]); fire[i].rgb[0] = c[n][0]; fire[i].rgb[1] = c[n][1]; fire[i].rgb[2] = c[n][2]; } }
3 烟花上升
y坐标 还没到达爆炸高度时一直上升
for (int i = 0; i < MAXNUM; i++) { if (fire[i].nowy > fire[i].endy) { fire[i].nowy -= 3; } }
4 烟花爆炸
爆炸进度 explode 不断增加,如果到达爆炸半径,就重新初始化。(接上面的if语句)
else { if (fire[i].explode >= fire[i].radio) { fire[i].nowx = rand() % WIDTH; fire[i].nowy = HEIGHT + rand() % 250 + 50; fire[i].endy = rand() % 100 + 10; fire[i].radio = rand() % 50 + 120; fire[i].explode = 0; int c[][3] = { {255, 0, 0}, {210, 190, 255}, {255, 120, 0}, {255, 0, 150}, {255, 240, 100}, {10, 255, 255}, {160, 10, 255}, {255, 200, 60} }; int n = rand() % 8; fire[i].color = RGB(c[n][0], c[n][1], c[n][2]); fire[i].rgb[0] = c[n][0]; fire[i].rgb[1] = c[n][1]; fire[i].rgb[2] = c[n][2]; } else fire[i].explode++; }
5 绘制烟花
上升
绘制5个圆,大小从大到小,颜色从深到浅(增加rgb值)
for (int i = 0; i < MAXNUM; i++) { if (fire[i].nowy > fire[i].endy) { for (int size = 5; size > 0; size--) { int temp[] = { fire[i].rgb[0], fire[i].rgb[1], fire[i].rgb[2] }; for (int k = 0; k < 3; k++) { temp[k] += 50 * (5 - size); if (temp[k] > 255) temp[k] = 255; } setfillcolor(RGB(temp[0], temp[1], temp[2])); solidcircle(fire[i].nowx, fire[i].nowy + 15*(10 - size), size); } } }
爆炸
重头戏!重头戏!重头戏!需要一些简(fù)单(zá)的数(gāo)学(děng)常(shù)识(xúe)!
颜色渐变的实现方式跟前面一样,只不过这里要用三角函数计算坐标,再用万有引力、抛物线等改变 y坐标,让它看得更真实!(牛顿:算你小子识相)
具体如何计算坐标,看我的文章,里面有说如何计算
然后是万有引力,大概需要高度乘以 0.98 ,这里就相当于减去 0.1
由于 easyx 坐标上方为 y = 0,所以,应该是:
y + (HEIGHT - y) * 0.1
再根据抛物线:y = x^2 ,修改一下就行了
else { for (int a = 0; a < 360; a += 30) { for (int size = 5; size > 0; size--) { int x = cos(a * PI / 180.0) * (fire[i].explode + size * 10) + fire[i].nowx; int y = sin(a * PI / 180.0) * (fire[i].explode + size * 10) + fire[i].nowy + fire[i].radio / 2; int temp[] = { fire[i].rgb[0], fire[i].rgb[1], fire[i].rgb[2] }; for (int k = 0; k < 3; k++) { temp[k] += 50 * (5 - size); if (temp[k] > 255) temp[k] = 255; } setfillcolor(RGB(temp[0], temp[1], temp[2])); solidcircle(x, y + (HEIGHT - y) * 0.1 + size * (size - 2), size); } } }
效果展示
还挺好看的,不是吗?
完整代码
最后,把函数封装一下,main 函数写出来(有手就行!):
/******************************* * 项目名称:新年烟花 * 开发环境:vs2022 + Easyx * 作者:轩 * 代码长度:137 行 * 完成时间:2023.1.20 * 用时:2.2 小时 *******************************/ #include <graphics.h> #include <math.h> #include <time.h> #include <stdio.h> #define MAXNUM 15 #define WIDTH 640 #define HEIGHT 480 #define PI 3.1415926 struct Fire { int nowx; int nowy; int endy; int radio; int explode; int rgb[3]; COLORREF color; }fire[MAXNUM]; void Init() { for (int i = 0; i < MAXNUM; i++) { fire[i].nowx = rand() % WIDTH; fire[i].nowy = HEIGHT + rand() % 250 + 50; fire[i].endy = rand() % 100 + 10; fire[i].radio = rand() % 50 + 120; fire[i].explode = 0; int c[][3] = { {255, 0, 0}, {210, 190, 255}, {255, 120, 0}, {255, 0, 150}, {255, 240, 100}, {10, 255, 255}, {160, 10, 255}, {255, 200, 60} }; int n = rand() % 8; fire[i].color = RGB(c[n][0], c[n][1], c[n][2]); fire[i].rgb[0] = c[n][0]; fire[i].rgb[1] = c[n][1]; fire[i].rgb[2] = c[n][2]; } } void Draw() { for (int i = 0; i < MAXNUM; i++) { if (fire[i].nowy > fire[i].endy) { for (int size = 5; size > 0; size--) { int temp[] = { fire[i].rgb[0], fire[i].rgb[1], fire[i].rgb[2] }; for (int k = 0; k < 3; k++) { temp[k] += 50 * (5 - size); if (temp[k] > 255) temp[k] = 255; } setfillcolor(RGB(temp[0], temp[1], temp[2])); solidcircle(fire[i].nowx, fire[i].nowy + 15*(10 - size), size); } } else { for (int a = 0; a < 360; a += 30) { for (int size = 5; size > 0; size--) { int x = cos(a * PI / 180.0) * (fire[i].explode + size * 10) + fire[i].nowx; int y = sin(a * PI / 180.0) * (fire[i].explode + size * 10) + fire[i].nowy + fire[i].radio / 2; int temp[] = { fire[i].rgb[0], fire[i].rgb[1], fire[i].rgb[2] }; for (int k = 0; k < 3; k++) { temp[k] += 50 * (5 - size); if (temp[k] > 255) temp[k] = 255; } setfillcolor(RGB(temp[0], temp[1], temp[2])); solidcircle(x, y + (HEIGHT - y) * 0.1 + size * (size - 2), size); } } } } } void Move() { for (int i = 0; i < MAXNUM; i++) { if (fire[i].nowy > fire[i].endy) { fire[i].nowy -= 3; } else { if (fire[i].explode >= fire[i].radio) { fire[i].nowx = rand() % WIDTH; fire[i].nowy = HEIGHT + rand() % 250 + 50; fire[i].endy = rand() % 100 + 10; fire[i].radio = rand() % 50 + 120; fire[i].explode = 0; int c[][3] = { {255, 0, 0}, {210, 190, 255}, {255, 120, 0}, {255, 0, 150}, {255, 240, 100}, {10, 255, 255}, {160, 10, 255}, {255, 200, 60} }; int n = rand() % 8; fire[i].color = RGB(c[n][0], c[n][1], c[n][2]); fire[i].rgb[0] = c[n][0]; fire[i].rgb[1] = c[n][1]; fire[i].rgb[2] = c[n][2]; } else fire[i].explode++; } } } int main() { srand(time(NULL)); initgraph(640, 480); Init(); BeginBatchDraw(); while (true) { cleardevice(); Draw(); Move(); FlushBatchDraw(); Sleep(2); } EndBatchDraw(); closegraph(); return 0; }
加载全部内容