纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

C语言 烟花 给喜欢的人用C语言写烟花

MAX在码字   2021-11-20 我要评论
想了解给喜欢的人用C语言写烟花的相关内容吗,MAX在码字在本文为您仔细讲解C语言 烟花的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:C语言,烟花,C语言,实例,下面大家一起来学习吧。

嗨!这里是狐狸~~

我之前有发过一篇有关程序员相亲的文章,今天突然翻起,又陷入了沉思,现在不会大家都觉得程序员不懂浪漫吧,真的大错特错,今天就让你们看看什么是程序员的浪漫!

我们今天就来写写《烟花》表白程序,不要惊讶,不要激动,学会了快去拿给心中的那个人看!!!

煽情的话就不要我说了吧,直接上代码

一、结构体

首先当然是我们的老朋友结构体,其中艺术字结构体不用我多说,该写什么内容自己应该知道哈

// 烟花结构
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];
 
// happy birthday 艺术字结构
struct HAPPY				// 储存 Happy Birthday 艺术字图片
{
	int x, y;				// 每个字的图片的左上角坐标
	IMAGE img;				// 储存单个字图片
	static int num;			// 字母序号
}Happy[NUM];

二、初始化

初始化烟花参数,把一切准备工作完成好

// 初始化烟花参数
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 ( 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 );
	}
 
	IMAGE hm;
	loadimage( &hm, "./fire/happy.jpg", 689, 115 );
	SetWorkingImage( &hm );
 
	for ( i = 0; i < 13; i++ )
	{
		Happy[i].x = i * 90;
		Happy[i].y = rand() % 100 + 500;
		getimage( &Happy[i].img, i * 53, 0, 53, 115 );
	}
 
	Wish.x		= 0;
	Wish.y		= 100;
	Wish.t1		= timeGetTime();
	Wish.dt		= 46;
	Wish.dir	= 0;
	Wish.dxy	= rand() % 8 + 1;
	loadimage( &Wish.img, "./fire/yaojing.jpg", 490, 100 );
	putimage( Wish.x, Wish.y, &Wish.img, SRCINVERT );
 
	SetWorkingImage();
}

四、烟花发射函数

扫描烟花弹并发射,控制开始与停止发射

// 扫描烟花弹并发射
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;					// 停止发射
 
				// 显示对应字母
				putimage( Happy[HAPPY::num].x, Happy[HAPPY::num].y, &Happy[HAPPY::num].img, SRCINVERT );
				HAPPY::num++;
 
				if ( HAPPY::num > 12 )
					HAPPY::num = 0;
			}
			Jet[i].t1 = Jet[i].t2;
		}
	}
}

五、烟花显示函数

显示花样,如何让烟花变得更好看

// 显示花样
void Style( DWORD& st1 )
{
	DWORD st2 = timeGetTime();
 
	if ( st2 - st1 > 266000 )		// 一首歌的时间
	{
		// 心形坐标
		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 )
		{
			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;
		}
	}
}

七、主函数

// 主函数
void main()
{
	initgraph( 1200, 800 );
	srand( time(0) );
 
	// 播放背景音乐
	mciSendString( "open ./fire/bk.mp3 alias bk", 0, 0, 0 );
	mciSendString( "play bk repeat", 0, 0, 0 );
 
	setfillstyle( 0	);
	setfont		( 36, 0, "楷体"	);
	setcolor	( YELLOW );
	outtextxy	( 370, 100, "yy滺滺__出厂 .... ^_^" );
 
	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	);		// 绽放烟花
		Wishing	(		);		// 滚动字符
		Style	( st1	);		// 花样发射
		FlushBatchDraw(	);		// 显示前面的所有绘图操作
	}
}

总结

好了,大家学废了嘛,这不是很难,效果还不错,大家可以尝试的去写一下,程序员的浪漫不止于此哦,哈哈哈,如果急切的想给心中的某个人看可以进群直接领取,当然啦,最好还是自己去写,去完成,网上的素材也是一大把,如何去优化,去改良就要看自己的本领了!嘻嘻,希望大家可以在这里得到自己想要的知识以及快乐吧,也希望大家可以给UP主一个关注,非常感谢大家了!!!

对了,说一件特别重要的事

我特意为此编了一个短视频,为了让大家知道程序员的浪漫我是豁出去了,希望大家可以给予我以及还在单身的程序员们一点小小的赞,谢谢大家了!!!

视频入口:

烟花再美也不及你

https://www.bilibili.com/video/BV1XS4y1d7CQ/


相关文章

猜您喜欢

  • MySQL中的group by 浅谈MySQL中的group by

    想了解浅谈MySQL中的group by的相关内容吗,李子捌在本文为您仔细讲解MySQL中的group by的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:MySQL中的group,by,group,by,下面大家一起来学习吧。..
  • C# Volatile C# Volatile的具体使用

    想了解C# Volatile的具体使用的相关内容吗,dotNet源计划在本文为您仔细讲解C# Volatile的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:C#,Volatile,下面大家一起来学习吧。..

网友评论

Copyright 2020 www.gamecatcher.cn 【绿色软件园】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式