C/C++新春烟花

系列文章

序号直达链接
1C/C++爱心代码
2C/C++跳动的爱心
3C/C++李峋同款跳动的爱心代码
4C/C++满屏飘字表白代码
5C/C++大雪纷飞代码
6C/C++烟花代码
7C/C++黑客帝国同款字母雨
8C/C++樱花树代码
9C/C++奥特曼代码
10C/C++精美圣诞树
11C/C++俄罗斯方块小游戏
12C/C++贪吃蛇小游戏
13C/C++孤单又灿烂的神-鬼怪
14C/C++闪烁的爱心
15C/C++哆啦A梦
16C/C++简单圣诞树
17C/C++小宇宙
18C/C++冰墩墩
19C/C++七彩花朵
20C/C++玫瑰花
21C/C++小猪佩奇
22C/C++简易爱心
23C/C++流星雨
24C/C++2048小游戏
25C/C++爱心圣诞树
26C/C++文字跑马灯
27C/C++教师工作量管理系统
28C/C++满天繁星
29C/C++漂浮爱心
30C/C++五子棋小游戏
31C/C++球球大作战小游戏
32C/C++走迷宫小游戏
33C/C++粉色爱心
34C/C++跨年烟花
35C/C++棕色小熊
36C/C++粉色动态爱心

目录

系列文章

写在前面

技术需求

环境搭建

1. EasyX是什么

2. 下载安装EasyX

完整代码

代码分析

1. 代码整体结构与框架

2. 数据结构

Jet 结构体

Fire 结构体

3. 关键函数分析

Load 函数

init 函数

Choose 函数

shoot 函数

Show 函数

Style 函数

clear 函数

4. 动画与性能优化

5. 总结

写在后面


写在前面

C/C++语言实现新春烟花动画的完整代码。

技术需求

1. EasyX 图形库

  • EasyX 是一个基于 Windows 的 C++ 图形库,适用于学生和初学者,能够轻松实现图形绘制、图像处理、动画制作等。代码中使用了 graphics.hIMAGE 类型来进行图形显示,加载和操作图像。
  • 使用 loadimage()putimage() 等函数加载和绘制图像,能方便地进行图形操作。

2. 多媒体控制接口 (MCI)

  • MCI (Media Control Interface) 是 Windows 提供的一种多媒体设备控制接口,能够对音频、视频等多媒体文件进行播放和控制。在这段代码中,通过 mciSendString() 函数来播放声音文件,如烟花发射和爆炸的音效。通过这种方式,程序能够与系统的音频设备进行交互。

示例代码:

mciSendString(c1, 0, 0, 0); // 播放音效
mciSendString(c2, 0, 0, 0); // 播放音效
mciSendString(c3, 0, 0, 0); // 关闭音效

3. 图形学中的动画与物理模拟

  • 烟花模拟:通过控制烟花弹和烟花爆炸的时间,使用坐标计算实现烟花的发射、爆炸和绽放效果。对于每个烟花弹,程序都计算了其发射位置、最高点、爆炸时的半径变化等物理特性,并通过循环更新这些属性来模拟烟花的运动轨迹和爆炸过程。
  • 分阶段渲染:烟花的每个阶段(如发射、上升、爆炸)都分开处理。通过设置时间间隔来控制不同阶段的图像绘制和爆炸效果,利用 putimage() 绘制图像,模拟烟花从发射到爆炸的过程。

4. 时间管理与定时

  • 系统时间管理:通过 timeGetTime()GetTickCount() 获取当前时间,用来计算烟花的不同阶段,以及控制烟花发射的间隔。时间差 t2 - t1 控制了烟花发射和绽放的速度,以及音效的播放时机。
  • 定时器:定时器(通过 Sleep()timeGetTime())确保程序的每一帧都有适当的时间间隔,从而产生平滑的动画效果。

5. 随机数与图像处理

  • 随机数生成:使用 rand() 函数生成随机数,用于决定烟花的发射位置、颜色、发射速度等。
  • 图像拆分与存储:通过 getimage() 获取烟花图像的部分内容,并存储在 Img 数组中。这是为了从一张大图中获取多个小的烟花图案,模拟不同烟花的效果。

6. 位段 (Bit-Field)

  • 位段是 C 语言中的一种结构体成员类型,允许使用部分位来存储数据。在代码中,byte n : 1; 使用位段来表示烟花的某个状态,节省内存空间。位段在处理小范围的状态标志时非常有用。

7. 内存操作与图像显示

  • 显存操作:通过 GetImageBuffer() 获取当前窗口的显存指针,直接操作每个像素点。通过这种方式,程序能够更细粒度地控制图形绘制,例如绘制烟花爆炸时的像素点,模拟烟花的扩散效果。
  • 批量绘制:通过 BeginBatchDraw()FlushBatchDraw() 函数,程序可以将多个图形绘制操作批量执行,从而提高绘图效率并确保绘制过程中的流畅性。

8. 位图绘制与颜色控制

  • 位图绘制:程序使用了 IMAGE 类型存储和操作位图,进行烟花图像的加载和绘制。通过 getpixel()setpixel() 等图像处理函数,程序能够精确地获取和修改图像中的像素值。
  • 颜色控制:通过位运算来解析和操作图像中的颜色,控制烟花的爆炸效果。具体来说,程序通过分离出 RGB 三个颜色通道的值,避免在绘制时显示过于暗淡的颜色。

9. 数学模型与物理运动

  • 烟花轨迹计算:程序通过数学函数(如 cos()sin())来计算烟花在二维空间中的运动轨迹。烟花的轨迹依赖于其发射角度和速度,使用了极坐标变换公式来确定烟花爆炸时的像素位置。
  • 爆炸效果:烟花爆炸模拟采用了半径逐渐增大的方式,通过不断增加爆炸半径(fire[i].r)来实现绽放效果。此外,通过控制时间间隔,爆炸的速度和图像渲染的速度也可以动态调整。

10. 声音效果与音频播放

  • 音频播放:通过 MCI 接口播放与烟花相关的音频文件。每个烟花弹发射时播放一个音效,烟花爆炸时播放另一个音效。音效通过 mciSendString() 控制,播放时机与烟花的动作同步。

环境搭建

环境:C/C++

软件:Visual Studio 2022

安装教程:C语言环境搭建教程(Visual Studio)_visual studio 2023-CSDN博客

1. EasyX是什么

EasyX是一个专为C++初学者和爱好者设计的图形库。该库以简洁易用、功能实用为宗旨,通过封装Windows GDI接口,极大降低了C++编程中图形界面设计的复杂度,使得用户能够快速上手并实现各类图形图像处理任务。

EasyX提供了一系列丰富的API函数,涵盖了绘制基本图形(如线段、圆形、矩形等)、填充图形、显示文本、加载与保存图片、颜色设置以及鼠标键盘事件处理等功能。通过简单的函数调用,开发者可以高效地进行2D图形绘制和交互式程序设计。

总的来说,EasyX以其友好的学习曲线和高效的图形处理能力,极大地激发了C++初学者对计算机图形学的兴趣,是广大编程入门者和教育领域广泛采用的一款图形库工具。

2. 下载安装EasyX

1.进入EasyX官网,点击下载按钮开始下载

2.下载完成后进入下载目录,双击.exe文件无脑安装即可

接下来,让我们一步步来实现这个跳动的爱心。首先,我们需要通过一系列的数学公式来定义爱心的形状,比如使用参数方程来描述爱心的轮廓。然后,我们可以使用C++的图形库来绘制出这个形状。当绘制好爱心后,就要想办法让它跳动起来了,这里我们可以使用C++的定时器功能,设置一个合适的时间间隔,让爱心在每个时间间隔内改变位置或大小,从而产生跳动的效果。

完整代码

#include<stdio.h>
#include<graphics.h>//之前要先安装EasyX,不然导入这个包会报错
#include<conio.h>
#include<math.h>
#include<time.h>//随机数
#include<mmsystem.h>//多媒体设备接口的头文件
#pragma comment(lib,"winmm.lib")//Media control interface
//这条指令和你在工程中添加"winmm.lib"的功能一样,告诉编译器要导入winmm库

#define NUM 13 //在整个屏幕内,最多出现13个烟雾弹
void Welcome();//进入程序运行界面
void init(int i);//初始化每个小烟花的属性值:比如x,y坐标值,是否发射等
void Load();//加载图片
void Choose(DWORD &t1);//选择要发送的烟花弹
void shoot();//发射烟花弹
void Show(DWORD*);		// 绽放烟花
void Style(DWORD& st1);
void write(DWORD&);
void clear(DWORD*);
struct Jet
{
	int x, y;//烟花弹的坐标
	int hx, hy;//最高点的坐标
	int height;//高:y-hy
	bool isshot;//是否发射
	DWORD t1, t2, dt;//DWORD是无符号的,相当于unsigned long ,
	//用t1,t2,dt控制速度
	IMAGE Img[2];//存放图片的数组
	byte n : 1;//下标	位段:/:指一个位来存放n
	//位段:(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间

}jet[NUM];//定义结构体数组
struct Fire
{
	int r;//当前爆炸半径
	int max_r;//爆炸中心距离边缘最大半径
	int x, y;//爆炸中心在窗口的坐标
	int cen_x,cen_y;//爆炸中心相对图片左上角的坐标
	int width;//图片的宽度
	int height;//图片的高度
	int xy[240][240];//储存图片像素点
	bool isshow;//是否显示
	bool isdraw;//是否画出
	DWORD t1, t2, dt;//绽放速度
}fire[NUM];
int main()
{
	initgraph(1000, 600);//初始化一个窗口
	srand((unsigned int)time(NULL));		//为了得到不一样的随机数
	
	Load();
	DWORD t1 = timeGetTime();			// 筛选烟花计时
	DWORD st1 = timeGetTime();			// 播放花样计时
	DWORD tm = timeGetTime();			//字体播放计时
	DWORD tn;
	DWORD TP;
	DWORD TC;

	DWORD* pMem = GetImageBuffer();		// 获取窗口显存指针,对每个像素点进行操作
	
	for (int i = 0; i < NUM; i++)
	{
		init(i);//初始化每个小烟花的相关数据

	}
	
	Load();								// 将烟花图片信息加载进相应结构中
	IMAGE img;
	loadimage(&img, "./file/image.jpg", 150, 266);
	BeginBatchDraw();					// 开始批量绘图
	while (!_kbhit())
	{
		Sleep(10);
		clear(pMem);
		TC = timeGetTime();
		if (TC - t1 > 0)
		{
			
			putimage(850, 334, &img);
		}
		Choose(t1);
		
		shoot();
		Show(pMem);
		Style(st1);
		FlushBatchDraw();	// 显示前面的所有绘图操作
	}
	getchar();

	return 0;
}

void Load()
{
/****储存烟花的像素点图片****/

	IMAGE fImg, gImg;
	loadimage(&fImg,"./file/flower.jpg",3120,240);
	for (int i = 0; i < NUM; i++)
	{
		SetWorkingImage(&fImg);
		getimage(&gImg, i * 240, 0, 240, 240);
		SetWorkingImage(&gImg);
		for (int a = 0; a < 240; a++)
		{
			for (int b = 0; b < 240; b++)
			{
				fire[i].xy[a][b] = getpixel(a, b);//获取点的颜色
			}
		}

	}
	IMAGE jetImg;//存放图片	
	loadimage(&jetImg,"./file/shoot.jpg",200,50);//加载图片,将图片保存到jetImage对象里面去
	//[2]拆分图片
	for (int i = 0; i < NUM; i++)
	{
		SetWorkingImage(&jetImg);//设置当前的设备,当前设备设为jetImg
		int n = rand() % 5;
		getimage(&jet[i].Img[0],n*20,0,20,50);//得到的是暗色图片
		//getimage()从当前设备获取图片
		//getimage()参数1指将得到的拆分出的图片存放的位置
		//参数2,3指得到的图片在原图片左上角的位置
		//参数4,5指的是新的到的图片的宽和高		下面类推
		getimage(&jet[i].Img[1], (n+5) * 20, 0, 20, 50);//得到的是明亮图片
	}
	SetWorkingImage(NULL);//重将当前设备设置为窗口

}//设置烟花小图片
……

代码分析

这段代码实现了一个烟花模拟效果,利用 C 语言和 EasyX 图形库制作了一个基于窗口的烟花展示程序。通过使用图像的加载、位置控制、动画效果、随机数生成、声音播放等技术,模拟了烟花从发射到爆炸的全过程。下面详细分析这段代码的工作原理、结构及实现的各个方面。

1. 代码整体结构与框架

这段代码主要包含了几个部分:初始化、加载图像、烟花弹的发射、烟花的爆炸和显示、花样的显示、以及清除显示内容等功能。其主要结构由以下几个函数组成:

  • 主函数 main:负责窗口的初始化,图像的加载,烟花发射、爆炸、显示的循环等。
  • Load 函数:加载烟花的图像和烟花弹的图像。
  • init 函数:初始化每个烟花和烟花弹的属性。
  • Choose 函数:控制烟花弹的发射,每100毫秒产生一个新的烟花弹。
  • shoot 函数:实现烟花弹的发射过程,即烟花从发射点向上升起的动画效果。
  • Show 函数:控制烟花的爆炸效果,逐步增加爆炸半径,模拟烟花的绽放过程。
  • Style 函数:播放花样的烟花,设置烟花弹的规律分布,并在适当时机播放爆炸效果。
  • clear 函数:清理屏幕上的像素,擦除已经绘制的烟花效果。

2. 数据结构

Jet 结构体

Jet 结构体表示一个烟花弹(或烟花飞行器),包含了烟花弹的位置信息、状态、时间戳等属性:

  • 坐标:包括烟花弹的当前位置 (x, y) 和最高点的坐标 (hx, hy),用来模拟烟花的飞行过程。
  • 高度height 表示烟花弹飞行的最大高度,即烟花弹的起始位置和目标位置之间的距离。
  • 发射状态isshot 用来标记烟花弹是否已经发射。
  • 时间管理t1t2dt 分别用来管理烟花弹的发射时刻、当前时间以及速度控制。
  • 图像Img 存储两张烟花弹的图像(暗色和明亮的烟花图像)。
  • 位段n 用来表示烟花弹的显示状态。

Fire 结构体

Fire 结构体表示烟花的爆炸效果,定义了烟花的爆炸半径、爆炸中心坐标、图片尺寸等属性:

  • 爆炸信息:包括爆炸的当前半径 r、最大半径 max_r 和爆炸中心的坐标 (x, y)
  • 图片数据:储存烟花爆炸时的图像像素点数据 xy,以及图片的宽高信息。
  • 显示控制isshowisdraw 用来控制烟花是否显示和是否绘制。
  • 时间管理:与烟花弹类似,使用 t1t2dt 来管理绽放过程中的时间间隔和速度。

3. 关键函数分析

Load 函数

Load 函数负责加载烟花的图片资源,并将其分解存储为结构体数据。首先加载了一个包含多个烟花图片的图像(如 flower.jpg)并将其切割成多个小图像存储到 fire 数组中。每个烟花爆炸的效果会从这些图像中获取像素数据,以便后续显示。接着加载烟花弹的图像 shoot.jpg,并将其分解为两张图片(暗色和明亮)分别存储在 jet 数组中。

init 函数

init 函数对每个烟花和烟花弹进行初始化,设置它们的初始位置、最大爆炸半径、爆炸中心坐标以及时间戳等。烟花的初始位置和爆炸半径是预先定义的,通过这些参数可以控制烟花爆炸的大小和分布。

Choose 函数

Choose 函数用于选择一个烟花弹进行发射。每100毫秒产生一个新的烟花弹,首先检查当前的烟花弹是否已经发射过(isshot)以及该烟花的爆炸是否已经开始(isshow)。如果烟花弹符合发射条件(未发射且未爆炸),则随机生成其初始坐标,并将其状态设置为“已发射” (isshot = true)。然后使用 mciSendString 播放发射的声音。

shoot 函数

shoot 函数实现烟花弹的飞行过程。每当烟花弹的飞行时间超过指定的时间间隔 (dt),烟花弹的图像会向上移动,并逐渐改变为明亮的状态。当烟花弹达到设定的最大高度时,触发烟花爆炸(即切换到爆炸状态)。在这一过程中,putimage 函数用于绘制烟花弹的图像。

Show 函数

Show 函数负责控制烟花的爆炸效果。它通过增加爆炸半径来模拟烟花的绽放,使用了变速效果来增加烟花的真实感。每次更新时,根据当前半径和爆炸速度来绘制烟花的爆炸效果。使用三角函数(cossin)来计算烟花的分布点,并将烟花的像素点显示到屏幕上。

Style 函数

Style 函数是一个特殊的烟花效果,用来显示更具规律的烟花形状。例如心形烟花的轨迹。函数通过修改烟花弹的起始位置,使其按照一定的模式(如心形)发射,同时播放发射的声音和爆炸效果。

clear 函数

clear 函数负责清除屏幕上绘制的烟花效果。它通过随机选择像素点并将其颜色重置为黑色来擦除已经显示的烟花效果,避免屏幕上留下遗留的图像,从而保持动画的流畅性。

4. 动画与性能优化

  • 多线程与批量绘制:代码中使用了 BeginBatchDrawFlushBatchDraw 来实现批量绘图,减少了单次绘制操作的开销,提高了动画的流畅度。
  • 时间管理与控制:通过 timeGetTime()GetTickCount() 来精确控制烟花弹的发射时间、飞行速度和爆炸时刻,确保烟花的动作具有一致性和节奏感。

5. 总结

这段代码通过利用 EasyX 图形库,结合了随机数、图像处理、声音播放等技术,模拟了烟花的发射、飞行和爆炸过程。它的结构清晰,功能分明,通过合理的时间控制和图像渲染,实现了较为生动的烟花效果。通过进一步优化,比如增加更多的烟花效果、改进图像加载与渲染性能等,可以让这个程序变得更加完善和有趣。

写在后面

我是一只有趣的兔子,感谢你的喜欢!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Want595

感谢小伙伴的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值