C语言如何实现烟花表白程序
发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章将为大家详细讲解有关C语言如何实现烟花表白程序,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。效果图烟花爆炸效果思路不能直接把烟花图片贴到窗口中,需要把烟花的
千家信息网最后更新 2025年01月19日C语言如何实现烟花表白程序
这篇文章将为大家详细讲解有关C语言如何实现烟花表白程序,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
效果图
烟花爆炸效果思路
不能直接把烟花图片贴到窗口中,需要把烟花的像素点保存到二维数组中,以相同的半径大小把烟花输出到窗口中爆炸的位置,r从0开始,不断增大,一圈圈输出,从而达到爆炸的效果
烟花在窗口中爆炸的位置为(x,y)即烟花弹上升的最大高度
烟花圆心为(cx,cy),烟花半径为r,已知圆心和半径,求得圆上的每一个点的坐标:圆的参数方程:x=a+r*cosθ y=b+r*sinθ(θ∈ [0,2π) ) (a,b) 为圆心坐标,r 为圆半径,θ 为参数,(x,y) 为经过点的坐标
注意方程坐标系和窗口坐标系的区别,窗口坐标系圆参数方程应为:x=a+r*cosθ y=b-r*sinθ
代码
#include#include #include #include #include #include #pragma comment ( lib, "Winmm.lib" )/***** 宏定义区 ******/#define NUM 13 // 烟花种类数量宏定义#define PI 3.1415926548/***** 结构定义区 **********/// 烟花结构struct FIRE{ int r; // 当前爆炸半径 int max_r; // 爆炸中心距离边缘最大半径 int x, y; // 爆炸中心在窗口的坐标 int cen_x, cen_y; // 爆炸中心相对图片左上角的坐标 int width, height; // 图片的宽高 int xy[240][240]; // 储存图片像素点 bool show; // 是否绽放 bool draw; // 开始输出像素点 DWORD t1, t2, dt; // 绽放速度}Fire[NUM];// 烟花弹结构struct JET{ int x, y; // 喷射点坐标 int hx, hy; // 最高点坐标------将赋值给 FIRE 里面的 x, y int height; // 烟花高度 bool shoot; // 是否可以发射 DWORD t1, t2, dt; // 发射速度 IMAGE img[2]; // 储存花弹一亮一暗图片 byte n : 1; // 图片下标}Jet[NUM];/**** 函数申明区 ****/void welcome();void Init(int); // 初始化烟花void Load(); // 加载烟花图片void Shoot(); // 发射烟花void Chose(DWORD&); // 筛选烟花void Style(DWORD&); // 发射样式void Show(DWORD*); // 绽放烟花// 主函数void main(){ initgraph(1200, 800); srand(time(0)); DWORD t1 = timeGetTime(); // 筛选烟花计时 DWORD st1 = timeGetTime(); // 播放花样计时 DWORD* pMem = GetImageBuffer(); // 获取窗口显存指针 for (int i = 0; i < NUM; i++) // 初始化烟花 { Init(i); } Load(); // 将烟花图片信息加载进相应结构中 BeginBatchDraw(); // 开始批量绘图 while (!kbhit()) { Sleep(10); // 随机选择 4000 个像素点擦除 for (int clr = 0; clr < 1000; clr++) { for (int j = 0; j < 2; j++) { int px1 = rand() % 1200; int py1 = rand() % 800; if (py1 < 799) // 防止越界 pMem[py1 * 1200 + px1] = pMem[py1 * 1200 + px1 + 1] = BLACK; // 对显存赋值擦出像素点 } } Chose(t1); // 筛选烟花 Shoot(); // 发射烟花 Show(pMem); // 绽放烟花 Style(st1); // 花样发射 FlushBatchDraw(); // 显示前面的所有绘图操作 }}// 初始化烟花参数void Init(int i){ // 分别为:烟花中心到图片边缘的最远距离、烟花中心到图片左上角的距离 (x、y) 两个分量 int r[13] = { 120, 120, 155, 123, 130, 147, 138, 138, 130, 135, 140, 132, 155 }; int x[13] = { 120, 120, 110, 117, 110, 93, 102, 102, 110, 105, 100, 108, 110 }; int y[13] = { 120, 120, 85, 118, 120, 103, 105, 110, 110, 120, 120, 104, 85 }; /**** 初始化烟花 *****/ Fire[i].x = 0; // 烟花中心坐标 Fire[i].y = 0; Fire[i].width = 240; // 图片宽 Fire[i].height = 240; // 图片高 Fire[i].max_r = r[i]; // 最大半径 Fire[i].cen_x = x[i]; // 中心距左上角距离 Fire[i].cen_y = y[i]; Fire[i].show = false; // 是否绽放 Fire[i].dt = 5; // 绽放时间间隔 Fire[i].t1 = timeGetTime(); Fire[i].r = 0; // 从 0 开始绽放 /**** 初始化烟花弹 *****/ Jet[i].x = -240; // 烟花弹左上角坐标 Jet[i].y = -240; Jet[i].hx = -240; // 烟花弹发射最高点坐标 Jet[i].hy = -240; Jet[i].height = 0; // 发射高度 Jet[i].t1 = timeGetTime(); Jet[i].dt = rand() % 10; // 发射速度时间间隔 Jet[i].n = 0; // 烟花弹闪烁图片下标 Jet[i].shoot = false; // 是否发射}// 加载图片void Load(){ /**** 储存烟花的像素点颜色 ****/ IMAGE fm, gm; loadimage(&fm, "./fire/flower.jpg", 3120, 240); for (int i = 0; i < 13; i++) { SetWorkingImage(&fm); getimage(&gm, i * 240, 0, 240, 240); SetWorkingImage(&gm); for (int a = 0; a < 240; a++) for (int b = 0; b < 240; b++) Fire[i].xy[a][b] = getpixel(a, b); } /**** 加载烟花弹 ************/ IMAGE sm; loadimage(&sm, "./fire/shoot.jpg", 200, 50); for (int i = 0; i < 13; i++) { SetWorkingImage(&sm); int n = rand() % 5; getimage(&Jet[i].img[0], n * 20, 0, 20, 50); // 暗 getimage(&Jet[i].img[1], (n + 5) * 20, 0, 20, 50); // 亮 } SetWorkingImage(); // 设置回绘图窗口}// 在一定范围内筛选可发射的烟花,并初始化发射参数,输出烟花弹到屏幕,播放声音void Chose(DWORD& t1){ DWORD t2 = timeGetTime(); if (t2 - t1 > 100) { int n = rand() % 20; if (n < 13 && Jet[n].shoot == false && Fire[n].show == false) { /**** 重置烟花弹,预备发射 *****/ Jet[n].x = rand() % 1200; Jet[n].y = rand() % 100 + 600; Jet[n].hx = Jet[n].x; Jet[n].hy = rand() % 400; Jet[n].height = Jet[n].y - Jet[n].hy; Jet[n].shoot = true; putimage(Jet[n].x, Jet[n].y, &Jet[n].img[Jet[n].n], SRCINVERT); /**** 播放每个烟花弹的声音 *****/ char c1[50], c2[30], c3[30]; sprintf(c1, "open ./fire/shoot.mp3 alias s%d", n); sprintf(c2, "play s%d", n); sprintf(c3, "close n%d", n); mciSendString(c3, 0, 0, 0); mciSendString(c1, 0, 0, 0); mciSendString(c2, 0, 0, 0); } t1 = t2; }}// 扫描烟花弹并发射void Shoot(){ for (int i = 0; i < 13; i++) { Jet[i].t2 = timeGetTime(); if (Jet[i].t2 - Jet[i].t1 > Jet[i].dt && Jet[i].shoot == true) { /**** 烟花弹的上升 *****/ putimage(Jet[i].x, Jet[i].y, &Jet[i].img[Jet[i].n], SRCINVERT); if (Jet[i].y > Jet[i].hy) { Jet[i].n++; Jet[i].y -= 5; } putimage(Jet[i].x, Jet[i].y, &Jet[i].img[Jet[i].n], SRCINVERT); /**** 上升到高度的 3 / 4,减速 *****/ if ((Jet[i].y - Jet[i].hy) * 4 < Jet[i].height) Jet[i].dt = rand() % 4 + 10; /**** 上升到最大高度 *****/ if (Jet[i].y <= Jet[i].hy) { // 播放爆炸声 char c1[50], c2[30], c3[30]; sprintf(c1, "open ./fire/bomb.wav alias n%d", i); sprintf(c2, "play n%d", i); sprintf(c3, "close s%d", i); mciSendString(c3, 0, 0, 0); mciSendString(c1, 0, 0, 0); mciSendString(c2, 0, 0, 0); putimage(Jet[i].x, Jet[i].y, &Jet[i].img[Jet[i].n], SRCINVERT); // 擦掉烟花弹 Fire[i].x = Jet[i].hx + 10; // 在烟花弹中间爆炸 Fire[i].y = Jet[i].hy; // 在最高点绽放 Fire[i].show = true; // 开始绽放 Jet[i].shoot = false; // 停止发射 } Jet[i].t1 = Jet[i].t2; } }}// 显示花样void Style(DWORD& st1){ DWORD st2 = timeGetTime(); if (st2 - st1 >20000) // 一首歌的时间 { // 心形坐标 int x[13] = { 60, 75, 91, 100, 95, 75, 60, 45, 25, 15, 25, 41, 60 }; int y[13] = { 65, 53, 40, 22, 5, 4, 20, 4, 5, 22, 40, 53, 65 }; for (int i = 0; i < NUM; i++) { //cleardevice(); /**** 规律分布烟花弹 ***/ Jet[i].x = x[i] * 10; Jet[i].y = (y[i] + 75) * 10; Jet[i].hx = Jet[i].x; Jet[i].hy = y[i] * 10; Jet[i].height = Jet[i].y - Jet[i].hy; Jet[i].shoot = true; Jet[i].dt = 7; putimage(Jet[i].x, Jet[i].y, &Jet[i].img[Jet[i].n], SRCINVERT); // 显示烟花弹 /**** 设置烟花参数 ***/ Fire[i].x = Jet[i].x + 10; Fire[i].y = Jet[i].hy; Fire[i].show = false; Fire[i].r = 0; /**** 播放发射声音 ***/ char c1[50], c2[30], c3[30]; sprintf(c1, "open ./fire/shoot.mp3 alias s%d", i); sprintf(c2, "play s%d", i); sprintf(c3, "close n%d", i); mciSendString(c3, 0, 0, 0); mciSendString(c1, 0, 0, 0); mciSendString(c2, 0, 0, 0); } st1 = st2; }}// 绽放烟花void Show(DWORD* pMem){ // 烟花个阶段绽放时间间隔,制作变速绽放效果 int drt[16] = { 5, 5, 5, 5, 5, 6, 25, 25, 25, 25, 55, 55, 55, 55, 55 }; for (int i = 0; i < NUM; i++) { Fire[i].t2 = timeGetTime(); // 增加爆炸半径,绽放烟花,增加时间间隔做变速效果 if (Fire[i].t2 - Fire[i].t1 > Fire[i].dt && Fire[i].show == true) { if (Fire[i].r < Fire[i].max_r) { Fire[i].r++; Fire[i].dt = drt[Fire[i].r / 10]; Fire[i].draw = true; } if (Fire[i].r >= Fire[i].max_r - 1) { Fire[i].draw = false; Init(i); } Fire[i].t1 = Fire[i].t2; } // 如果该号炮花可爆炸,根据当前爆炸半径画烟花,颜色值接近黑色的不输出。 if (Fire[i].draw) { //628次 2π x1 y1 得到628个来自图片的像素点坐标 for (double a = 0; a <= 6.28; a += 0.01) { int x1 = (int)(Fire[i].cen_x + Fire[i].r * cos(a)); // 相对于图片左上角的坐标 int y1 = (int)(Fire[i].cen_y - Fire[i].r * sin(a)); if (x1 > 0 && x1 < Fire[i].width && y1 > 0 && y1 < Fire[i].height) // 只输出图片内的像素点 { int b = Fire[i].xy[x1][y1] & 0xff; int g = (Fire[i].xy[x1][y1] >> 8) & 0xff; int r = (Fire[i].xy[x1][y1] >> 16); // 烟花像素点在窗口上的坐标 int xx = (int)(Fire[i].x + Fire[i].r * cos(a)); int yy = (int)(Fire[i].y - Fire[i].r * sin(a)); // 较暗的像素点不输出、防止越界 if (r > 0x20 && g > 0x20 && b > 0x20 && xx > 0 && xx < 1200 && yy > 0 && yy < 800) pMem[yy * 1200 + xx] = BGR(Fire[i].xy[x1][y1]); // 显存操作绘制烟花 } } Fire[i].draw = false; } }}
素材
关于"C语言如何实现烟花表白程序"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
烟花
坐标
图片
烟花弹
发射
爆炸
像素
半径
参数
高度
输出
最大
左上角
效果
时间
结构
圆心
坐标系
方程
显存
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
服务器显卡点不亮的原因
学校网络安全抄报
GISAlD数据库
软件开发风险分析怎么写
畅捷链接服务器失败什么原因
此网络安全配置已过时
深圳saas管理软件开发商
数据库显示链接出错
经典数据库面试题
服务器抓sftp包
应用层对网络安全的影响
数据库第二版考试简答题
湖北专业网络技术工程
多节点服务器管理器
历下区 网络安全 服务合同
数据库的server是什么意思
数据库中常见的数据模型
之前关于网络安全的电影
手机服务器选项
方舟服务器管理删档
技术级网络技术学什么
达梦数据库是非关系型数据库吗
苹果tv显示等待更新服务器
银川市网络安全竞赛
阿里云服务器在线客服
本服务器架构与美国
设某一数据库有四个表
智能制造要搞软件开发吗
云服务器防护安全
天津服务器机房销售公司云主机