浪漫烟花


废话不多说,先上代码 其实没啥好说的

参考文献:https://zhuanlan.zhihu.com/p/333503066

(3条消息) 3分钟用C语言教你写个‘浪漫烟花‘---特别漂亮_尘客-追梦的博客-CSDN博客

用c语言编写动态烟花的方法 - 编程语言 - 亿速云 (yisu.com)

视频文献:【C/C++】C语言实现浪漫烟花表白程序,表白必备的满天花海!_哔哩哔哩_bilibili

代码挑战——烟花特效制作_哔哩哔哩_bilibili

【C语言链表】尽毕生所学教会你C语言链表,看完保准会。_哔哩哔哩_bilibili

//编写环境vs2019
#include<graphics.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>

#pragma comment(lib,"winmm.lib")

#define NUM 10			 

//烟花弹
struct jet
{
	int x, y;			 
	int hx, hy;			 

	bool shoot;			 
	DWORD t1, t2, dt;	 
	IMAGE img[2];		 
	byte n : 1;			 
}jet[NUM];			 

//烟花
struct Fire
{
	int x, y;				 
	int r;					 
	int max_r;				 
	int cen_x, cen_y;		 
	int width, height;		 
	int xy[240][240];		 

	bool draw;				 
	bool show;				 
	DWORD t1, t2, dt;		 
}fire[NUM];

 
void FireInit(int i)
{
	 
	jet[i].t1 = GetTickCount();	 
	jet[i].shoot = false;		 
	jet[i].dt = 10;				 
	jet[i].n = 0;				 

	//初始化烟花
	fire[i].show = false;		//未引爆
	fire[i].r = 0;
	fire[i].dt = 5;				//上升时间
	fire[i].t1 = GetTickCount();
	fire[i].max_r = rand() % 50 + 100;	 
	fire[i].cen_x = rand() % 30 + 80;	  
	fire[i].cen_y = rand() % 30 + 80;	 
	fire[i].width = 240;				 
	fire[i].height = 240;				 
}

//加载
void Load()
{
	//加载烟花弹
	IMAGE jetimg;
	loadimage(&jetimg, L"./fire/shoot.jpg", 200, 50);
	SetWorkingImage(&jetimg);
	for (int i = 0; i < NUM; i++)
	{
		int n = rand() % 5;			//01234
		getimage(&jet[i].img[0], n * 20, 0, 20, 50);
		getimage(&jet[i].img[1], (n + 5) * 20, 0, 20, 50);
	}
	SetWorkingImage(NULL);

	//加载烟花
	IMAGE fireimage, Fireimage;
	loadimage(&Fireimage, L"./fire/flower.jpg", 3120, 240);
	for (int i = 0; i < NUM; i++)
	{
		SetWorkingImage(&Fireimage);
		getimage(&fireimage, i * 240, 0, 240, 240);
		SetWorkingImage(&fireimage);
		for (int a = 0; a < 240; a++)
		{
			for (int b = 0; b < 240; b++)
			{
				fire[i].xy[a][b] = getpixel(a, b);
			}
		}
	}
	SetWorkingImage(NULL);
}

//选择烟花弹
void ChoiceJet(DWORD& t1)
{
	DWORD t2 = GetTickCount();

	if (t2 - t1 > 100)		 
	{
		 
		int i = rand() % 10;

		 
		if (jet[i].shoot == false && fire[i].show == false)
		{
			 
			jet[i].x = rand() % 1000;
			jet[i].y = rand() % 100 + 450;	 
			jet[i].hx = jet[i].x;
			jet[i].hy = rand() % 300;		 
			jet[i].shoot = true;			 

			putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
		}
		t1 = t2;
	}
}

//判断发射
void Shoot()
{
	for (int i = 0; i < NUM; i++)
	{
		jet[i].t2 = GetTickCount();

		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);

			if (jet[i].y <= jet[i].hy)
			{
				putimage(jet[i].x, jet[i].y, &jet[i].img[jet[i].n], SRCINVERT);
				jet[i].shoot = false;
				 
				fire[i].x = jet[i].hx;
				fire[i].y = jet[i].hy;
				fire[i].show = true;
			}
		}
		jet[i].t1 = jet[i].t2;
	}
}

//显示烟花
void ShowFire(DWORD* pMem)
{
	int drt[16] = { 5,5,5,5,5,10,25,25,25,25,55,55,55,55,55,65 };

	for (int i = 0; i < NUM; i++)
	{
		fire[i].t2 = GetTickCount();
		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;
				FireInit(i);
			}
			fire[i].t1 = fire[i].t2;

		 
			if (fire[i].draw)
			{
				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 < 1000 && yy >0 && yy < 600)
						{
							pMem[yy * 1000 + xx] = BGR(fire[i].xy[x1][y1]);
						}
						fire[i].draw = false;
					}
				}
			}
		}
	}
}

//主函数
int main()
{ 
	initgraph(1000, 600);

 
	srand((unsigned int)time(NULL));

	 
	mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0);	 
	mciSendString(L"play music", 0, 0, 0);
	 
	DWORD t1 = GetTickCount();
	DWORD* pMem = GetImageBuffer();

	for (int i = 0; i < NUM; i++)
	{
		FireInit(i);
	}

	Load();
	BeginBatchDraw();

	while (1)
	{
		 
		for (int clr = 0; clr < 200; clr++)
		{
				int px1 = rand() % 1000;
				int py1 = rand() % 600;
 
				if (py1 < 599)  
				{ 
					pMem[py1 * 1000 + px1] = pMem[py1 * 1000 + px1 + 1] = BLACK; 
				}
		}
		ChoiceJet(t1);
		Shoot();
		ShowFire(pMem);
		FlushBatchDraw();
	}

 

	system("pause");
	return 0;
}

 

好好听讲 开讲

基本代码

<graphics.h>头文件需要自己下载。

下载网址:https://easyx.cn/


graphics.h实例

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
int main()
{
initgraph(700,700);//初始化窗口 也就是设定我们的程序框大小
setcolor(RED);//设置绘图的颜色
circle(200,200,100);//圆心(200,200),半径100
rectangle(200,200,400,400);//绘制一个矩形
line(200,200,500,500);//画线
getch();
closegraph;//关闭绘图程序界面
}

头文件与结构体

#include<graphics.h>//图形界面
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>

#pragma comment(lib,"winmm.lib")//可能会报错

#define NUM 10//烟花弹个数			 

//烟花弹
struct jet
{
	int x, y;//烟花弹坐标			 
	int hx, hy;//烟花弹最高点坐标	 

	bool shoot;	//记录烟花弹是否处于发射		 
	DWORD t1, t2, dt;//t1发射时间;t2引爆时间;dt:间隔时间
	IMAGE img[2];//用来存图片。两张(一明一暗)
	byte n : 1; 
}jet[NUM];			 

//烟花
struct Fire
{
	int x, y;//烟花的坐标				 
	int r;	//烟花的半径				 
	int max_r;		//烟花的最大半径		 
	int cen_x, cen_y;		//中心距离左上角的距离(也就是中心距理原点的距离) 
	int width, height;	//烟花的长和宽	 
	int xy[240][240];	//像素,矩阵	 

	bool draw;				//记录是否画出 
	bool show;				 //记录是否显示
	DWORD t1, t2, dt;		 //发射时间 引爆时间 间隔时间
}fire[NUM];

bool类型


C语言并没有彻底从语法上支持“真”和“假”,只是用 0 和非 0 来代表。这点在 C++ 中得到了改善,C++ 新增了 bool 类型(布尔类型),它一般占用 1 个字节长度。bool 类型只有两个取值,true 和 false:true 表示“真”,false 表示“假”。

bool 是类型名字,也是 C++ 中的关键字,它的用法和 int、char、long 是一样的,请看下面的例子:

#include <iostream>
using namespace std;
int main(){
    int a, b;
    bool flag;  //定义布尔变量
    cin>>a>>b;
    flag = a > b;
    cout<<"flag = "<<flag<<endl;
    return 0
}

10 20
flag = 0

遗憾的是,在 C++ 中使用 cout 输出 bool 变量的值时还是用数字 1 和 0 表示,而不是 true 或 false。JavaPHPJavaScript 等也都支持bool类型,但输出结果为 true 或 false,我武断地认为这样更科学。

你也可以使用 true 或 false 显式地对 bool 变量赋值,例如:

#include <iostream>
using namespace std;

int main(){
    bool flag = true;
    if(flag){
        cout<<"true"<<endl;
    }else{
        cout<<"false"<<endl;
    }

    flag = false;
    if(flag){
        cout<<"true"<<endl;
    }else{
        cout<<"false"<<endl;
    }

    return 0;
}

运行结果:
true
false

注意,true 和 false 是 C++ 中的关键字,true 表示“真”,false 表示“假”。

DOWRD类型

在Visual C++ 6.0中,BYTE与WORD,DWORD本质上都是一种无符号整型,它们在WINDEF.H中被定义,定义如下:

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;

​ 也就是说BYTE是无符号的char型(char型本质上也是一种1个字节的整型),WORD是无符号short型,DWORD是无符号long型。

​ 而在Visual C++ 6.0中,char型长度为1字节,short型长度为2字节,int和long型长度都为4字节,因此可以认为BYTE与WORD,DWORD定义的变量分别获得了1字节,2字节,4字节内存,正与BYTE与WORD,DWORD的字面意义相符。

即:BYTE=unsigned char(完全等同)
WORD=unsigned short(完全等同)
DWORD=unsigned long(完全等同)

IMAGE

IMAGE img[2]存入了两张图片。//IMAGE是一个关于存入图片的结构体,只是开辟了一个空间让图片可以存进去,但还没存进去。

byte n : 1;

BYTE=unsigned char(完全等同)

C结构体 位段 //n 变量 1个位 0,1 n++ 0,1,0,1

函数统计

void ChoiceJet()//用来选择烟花弹
void FireInit()//对程序进行初始化
void Load()//加载
void shoot()//判断发射
void ShowFire()//显示烟花

主函数

int main()
{
	//初始界面(1000,600)
	initgraph(1000, 600);

	//初始化种子,使用rand前一定要初始化,不然之后rand出的数都相同
	srand((unsigned int)time(NULL)); 

	 
  mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0);	//send(发送)	string(字符串 // 音乐要放在程序代码文件夹更目录下
mciSendString(L"play music", 0, 0, 0);
    
	

	DWORD t1 = GetTickCount();
	DWORD* pMem = GetImageBuffer();

	for (int i = 0; i < NUM; i++)
	{
		FireInit(i);
	}

	Load();
	BeginBatchDraw();

	while (1)
	{
		// 随机选择像素点擦除
		for (int clr = 0; clr < 200; clr++)
		{
				int px1 = rand() % 1000;
				int py1 = rand() % 600;

				// 防止越界
				if (py1 < 599)  
				{
					//对显存赋值擦除像素点
					pMem[py1 * 1000 + px1] = pMem[py1 * 1000 + px1 + 1] = BLACK; 
				}
		}
		ChoiceJet(t1);
		Shoot();
		ShowFire(pMem);
		FlushBatchDraw();
	}

	/*
	putimage(0, 0, &jet[3].img[0]);
	putimage(100, 0, &jet[3].img[1]);
	*/

	system("pause");
	return 0;
}


mciSendString()函数

mciSendString(L"open ./fire/bk1.mp3 alias music", 0, 0, 0); //send(发送) string(字符串)

mciSendSrting()函数只支持打开MP3音频文件,若需要打开wav音频文件可以使用PlaySound函数

当使用mciSendSrting()函数时,一定要确定好文件的位置,文件夹名用/号隔开,向我这里的文件就在当前文件的根目录下,音乐的全名便是叫做bk1.MP3。bk1.MP3 alias music的意思是给bk1取一个叫做music的别名

mciSendString(L"play music", 0, 0, 0);的意思是播放别名为music的音乐。后面三个参0,0,0则表示默认

//0,0,0 音乐播放器时:播放设备,快进设备 快退 暂停


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM