本篇文章主要讲解 如何使用Eazyx库进行烟花动效的制作,这里可能较为复杂,请入坑者三思后行
定义一个烟花绽放的类并进行实例化
class Fire
{
public:
int r; // 当前爆炸半径
int max_r; // 爆炸中心距离边缘最大半径
int x, y; // 爆炸中心在窗口的坐标
int cent2LeftTopX, cent2LeftTopY; // 爆炸中心相对图片左上角的坐标
int width, height; // 图片的宽高
int pix[240][240]; // 储存图片像素点
bool show; // 是否绽放
bool draw; // 开始输出像素点
DWORD t1, t2, dt; // 绽放速度
}fires[NUM];
定义一个烟花弹结构的类同样进行实例化
class Bullet
{public:
int x, y; // 烟花弹的当前坐标
int topX, topY; // 最高点坐标------将赋值给 FIRE 里面的 x, y
int height; // 烟花高度
bool shoot; // 是否可以发射
DWORD t1, t2, dt; // 发射速度
IMAGE img[2]; // 储存花弹一亮一暗图片
unsigned char n : 1; // 图片下标 n++
}bullets[NUM];
实现函数主要有以下几个(由于代码太多,先展示部分代码)
void initFire(int i)//初始化烟花代码
void loadFireImages()//加载烟花图片读入像素点
void drawFire(int i)//展示烟花
void testFire()//
void chose(DWORD t1)//随机发射烟花弹
void init()//初始化烟花弹
void clearImage()//清屏
void shoot()//发射烟花弹
void welcome()//表白字幕
void showFire()//绽放
void heartFire(DWORD& st1)//花样绽放
初始化部分
// 项目初始化
void init() {
// 创建窗口
initgraph(1200, 800);
// 播放背景音乐
mciSendString("play fire/bg.mp3 repeat", 0, 0, 0);
for (int i = 0; i < NUM; i++) { // 初始化烟花和烟花弹
initFire(i);
}
loadFireImages();
// 这个函数用于获取绘图设备的显示缓冲区指针。
pMem = GetImageBuffer(); // 获取窗口显存指针
// 打开音效并设置别名
char cmd[128];
for (int i = 0; i < 13; i++) {
sprintf_s(cmd, sizeof(cmd), "open fire/shoot.mp3 alias s%d", i);
mciSendString(cmd, 0, 0, 0); // 打开13次
sprintf_s(cmd, sizeof(cmd), "open fire/bomb.wav alias f%d", i);
mciSendString(cmd, 0, 0, 0); // 打开13次
}
}
花样展示部分
void heartFire(DWORD& st1)
{
DWORD st2 = timeGetTime();
if (st2 - st1 > 20000) // 20秒
{
// 先擦除正在发送的烟花弹
for (int i = 0; i < 13; i++) {
if (bullets[i].shoot)
putimage(bullets[i].x, bullets[i].y, &bullets[i].img[bullets[i].n], SRCINVERT);
}
// 心形坐标
int x[13] = { 600, 750, 910, 1000, 950, 750, 600, 450, 250, 150, 250, 410, 600 };
int y[13] = { 650, 530, 400, 220, 50, 40, 200, 40, 50, 220, 400, 530, 650 };
for (int i = 0; i < NUM; i++)
{
bullets[i].x = x[i];
bullets[i].y = y[i] + 750; //每个烟花弹的发射距离都是750,确保同时爆炸
bullets[i].topX = x[i];
bullets[i].topY = y[i];
bullets[i].height = bullets[i].y - bullets[i].topY;
bullets[i].shoot = true;
bullets[i].dt = 7;
// 显示烟花弹
putimage(bullets[i].x, bullets[i].y, &bullets[i].img[bullets[i].n], SRCINVERT);
/**** 设置烟花参数 ***/
fires[i].x = bullets[i].x + 10;
fires[i].y = bullets[i].topY;
fires[i].show = false;
fires[i].r = 0;
}
st1 = st2;
}
}
主函数各功能的实现
int main(void) {
init();
welcome(); // 绘制表白字幕
//testFire();
DWORD t1 = timeGetTime(); // 筛选烟花计时
DWORD ht1 = timeGetTime(); // 播放花样计时
BeginBatchDraw();
// kbhit()判断有没有按键输入
while (!kbhit())
{
// 帧等待
Sleep(10);
clearImage();
chose(t1); //点火
shoot(); //升空
showFire();
heartFire(ht1);
FlushBatchDraw(); // 显示前面的所有绘图操作
// 烟花
// to do...
}
return 0;
}
总结如下几点:1.烟花弹是通过读取图片再写入像素点显示的
2.用到了BeginBatchDraw();FlushBatchDraw();函数,这两个函数主要用于动态效果展示,防止闪屏
3.如果使用多线程效果会比这更好,不过eazyx库只用来做简单效果,复杂效果不推荐使用
4.源码后期补上
效果展示