效果图(有背景音乐呦)
项目链接
https://download.csdn.net/download/weixin_45525272/18558896
搞起来
编译环境:vs2017 & EasyX
没有EasyX的小伙伴可以点击下面网盘链接进行下载安装,点击exe运行,选择你对应的vs版本点击安装即可
链接:https://pan.baidu.com/s/1pQbktxBd9u2gObg84eGRxg
提取码:za2k
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V4的分享
代码
注释比较详细,就不进行讲解了
#include <stdio.h> #include <windows.h> #include <mmsystem.h> #include <time.h> #include <math.h> #include <stdlib.h> #include <graphics.h> // 头文件 #pragma comment(lib,"Winmm.lib") #define NUM 13 // 烟花弹的结构体 struct Jet { int x, y; // 当前的坐标 int hx, hy; // 最高点的x y bool shoot; // 是否发射 DWORD t1, t2, dt; // 发射速度!! t1 t2 发射速度 IMAGE img[2]; // 两张小图片 byte n : 1; // 位段 n是一个变量 1个位。 }jet[NUM]; // 烟花去图片里截取 struct Fire { int r; int max_r; int cen_x, cen_y; // 圆心 int x, y; // 图片在界面中的 坐标 int width, height; // 图片的宽度 高度 int xy[240][240]; // 像素矩阵 bool show; bool draw; DWORD t1, t2, dt; // 绽放的速度 就可以相当于像素 }fire[NUM]; void LoadImg() { // EasyX 中的图片类型 IMAGE allflowers, flower; loadimage(&allflowers, L"flower.jpg", 3120, 240); for (int i = 0; i < NUM; i++) { SetWorkingImage(&allflowers); // 设置当前绘图设备 为 所有的烟花 getimage(&flower, i * 240, 0, 240, 240); // 截取小烟花 SetWorkingImage(&flower); // 从flower 像素点保存在一个二维数组 并 设置为当前绘图设备 for (int x = 0; x < 240; x++) { for (int y = 0; y < 240; y++) { fire[i].xy[x][y] = getpixel(x, y); // 获取点的颜色 到每个小flower矩阵中 } } } IMAGE jetImg; // 图片类型 loadimage(&jetImg, L"shoot.jpg", 200, 50); SetWorkingImage(&jetImg); // 从jetImg去获取小图片 // 13种 for (int i = 0; i < NUM; i++) { int n = rand() % 5; // 0-4 getimage(&jet[i].img[0], n * 20, 0, 20, 50); getimage(&jet[i].img[1], (n + 5) * 20, 0, 20, 50); } SetWorkingImage(NULL); } void GameInit(int n) { // 13个烟花的半径 中心坐标 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[n].cen_x = x[n]; fire[n].cen_y = y[n]; fire[n].max_r = r[n]; fire[n].show = false; fire[n].width = 240; fire[n].height = 240; fire[n].dt = 5; fire[n].r = 0; fire[n].t1 = GetTickCount(); // 简单的初始化了一些数据 jet[n].dt = rand() % 10 + 1; // 1-10ms jet[n].n = 0; jet[n].t1 = GetTickCount(); jet[n].shoot = false; } // 选择烟花弹 void Chiosejet(DWORD& t1) // t1 t2做产生新的烟花弹的间隔。 { DWORD t2 = GetTickCount(); if (t2 - t1 > 100) // 100ms 产生一个新的 烟花弹 { // rand()%13; 0-12 int n = rand() % NUM; // 随机选一个 if (jet[n].shoot == false && fire[n].show == false) // 判断是否发射 未发射的状态 { jet[n].x = rand() % 1200; jet[n].y = rand() % 100 + 600; // 600-699 jet[n].hx = jet[n].x; jet[n].hy = rand() % 400; // 0-399 jet[n].shoot = true; // 选中 putimage(jet[n].x, jet[n].y, &jet[n].img[jet[n].n], SRCINVERT); } t1 = t2; } } // 显存 void Shootjet() { for (int n = 0; n < NUM; n++) { jet[n].t2 = GetTickCount(); if (jet[n].t2 - jet[n].t1 >= jet[n].dt&&jet[n].shoot == true) { putimage(jet[n].x, jet[n].y, &jet[n].img[jet[n].n], SRCINVERT); if (jet[n].y >= jet[n].hy) { jet[n].y -= 5; // 上升 jet[n].n++; // 闪烁 } putimage(jet[n].x, jet[n].y, &jet[n].img[jet[n].n], SRCINVERT); if (jet[n].y <= jet[n].hy) // 说明已经上升到最高点 { putimage(jet[n].x, jet[n].y, &jet[n].img[jet[n].n], SRCINVERT); jet[n].shoot = false; fire[n].x = jet[n].hx; fire[n].y = jet[n].hy; fire[n].show = true; // 爆炸 } jet[n].t1 = jet[n].t2; } } } // 烟花显示 void ShowFire(DWORD* pmem) { int drt[16] = { 5, 5, 5, 5, 5, 6, 25, 25, 25, 25, 55, 55, 55, 55, 65, 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; GameInit(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 (b > 0x20 && g > 0x20 && r > 0x20 && xx > 0 && xx < 1200 && yy>0 && yy < 800) { pmem[yy * 1200 + xx] = BGR(fire[i].xy[x1][y1]); } } } fire[i].draw = false; } } } int main() { // 初始化图形界面 打开一个窗口。1200 800 initgraph(1200, 800); // 1200*800 mciSendString(L"open 小幸运.mp3 alias bgm", 0, 0, 0); mciSendString(L"play bgm", 0, 0, 0); DWORD t1 = GetTickCount(); DWORD *pmem = GetImageBuffer(); // 获取绘图设备的显存指针 // 随机数的种子 srand((unsigned int)time(NULL)); // 处理加载图片 LoadImg(); for (int i = 0; i < NUM; i++) { GameInit(i); } BeginBatchDraw(); // 开始批量绘制 while (1) { Chiosejet(t1); Shootjet(); ShowFire(pmem); FlushBatchDraw(); } return 0; }