C++ EasyX 动态烟花模拟源码与实现解析
本文介绍如何利用 C++ 的 EasyX 图形库实现动态烟花特效。通过定义数据结构管理烟花状态,结合三角函数计算爆炸轨迹及简易物理算法,模拟粒子上升与绽放过程。文章解析了从初始化到绘制的核心逻辑,并提供完整可运行代码。
项目准备与环境配置
开发本案例需要 C++ 基础以及 EasyX 图形库的支持。该库为初学者提供了简便的图形界面操作接口,无需复杂处理即可实现绘图功能。
- 依赖库:下载并安装
graphics.h(EasyX)。 - 开发环境:Visual Studio 或其他支持 C++11 及以上标准的编译器。
- 宏定义参数:根据预设窗口大小调整常量,例如宽度
WIDTH为 640,高度HEIGHT为 480,同时设定烟花最大数量MAXNUM。
核心逻辑解析
第1步:构建烟花对象结构体
使用 struct 封装单个烟花粒子的属性,便于批量管理。
nowx / nowy:当前坐标位置。endy:目标爆炸高度 Y 轴阈值。explode:爆炸进度值,用于驱动后续扩散逻辑。radio:爆炸的最大半径范围。rgb[3]:颜色数组,记录红绿蓝分量。
第2步:随机初始化与资源分配
在启动阶段,为每个烟花实例赋予随机属性。
- 入口:调用
Init()函数。 - 动作:生成随机的 X 轴初始位置(屏幕宽度内),Y 轴起始位置位于可视区域下方(
HEIGHT + rand() % 250 + 50),确保动画开始时烟花从底部升起。 - 颜色选择:从预设的颜色矩阵中随机抽取一组 RGB 值并赋值给实例。
第3步:运动逻辑与状态判断
在每一帧刷新时更新位置,决定是继续上升还是进入爆炸阶段。
- 上升:当当前 Y 坐标大于设定的爆炸高度
endy时,Y 轴数值递减(模拟向上飞行)。 - 爆炸触发:一旦越过临界点,切换逻辑分支,让
explode变量自增,并检测是否达到radio最大值。若已达上限,则重新初始化该烟花实例。
第4步:可视化渲染与数学模拟
利用图形库绘制圆形,并通过数学函数模拟真实物理效果。
- 上升阶段绘制:以多层同心圆形式绘制,通过调整 RGB 值的透明度或亮度差来体现光晕效果。
- 爆炸阶段计算:核心在于将时间(爆炸进度)转化为角度坐标。
- 使用cos()和sin()结合explode值计算 X、Y 偏移量。
- 引入重力加速度近似算法:y + (HEIGHT - y) * 0.1,模拟粒子在下落过程中的抛物线轨迹。
完整源码
以下是完整的 C++ 实现代码,包含主循环、批次绘制优化(防闪烁)以及上述所有逻辑:
/*******************************
* 项目名称:新年烟花
* 开发环境:vs2022 + Easyx
* 作者:轩
* 代码长度:137 行
* 完成时间:2023.1.20
*******************************/
#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;
}
总结
通过该方案,我们实现了基于几何计算的简单粒子系统。掌握坐标变换和物理模拟基础后,可以进一步扩展为更复杂的特效程序。以上就是 C++ EasyX 实现动态烟花效果的详细内容,更多关于 C++ 图形化编程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













