#include#include #include #include #include"resource.h"//导入资源之后有一个resource.h头文件 记得加上 #include
#include #pragma comment(lib,"winmm.lib") long ret_useless = 0; // Capture the _getwch() return value to eliminate warnings const int GW = 640; // Screen width屏幕的宽度 const int GH = 480; // Screen height屏幕的高度 const double g = 9.8; // Acceleration of gravity重力 const double PI = 3.1415926; const int len_max = 80; // The maximum length of LightLine光线的最大长度 const int h_max = GH - len_max; // The maximum height that LightLine can reach光线能到达的最高高度 const double v_max = sqrt(2 * g * h_max / 10); // Maximum initial velocity of LightLine最大初速度 mgh=mv^2 重力势能=动能 //除以10的缘故是公式是用m做单位,1m代表10个像素点 const int n_max = 5; // Maximum number of fireworks on the screen烟花在屏幕上同时存在最多的数量 class LightLine { public: LightLine(int, double); void Draw() const; void Move(); bool Stopped() const { return v == 0; } bool OverLine() const { return py < h_max* n_max / (n_max + 1); } // Necessary condition for the next fireworks to rise int GetX() const { return px; } int GetY() const { return py; } private: int px; // Position_x int py; // Position_y int len; // Length double v; // Velocity (The -y axis is positiva)速度(Y轴是正的) clock_t ct = 0; // Recording time }; LightLine::LightLine(int x = rand() % (GW - 80) + 40, double vv = (rand() % 20 + 80.0) / 100 * v_max) :px(x), py(h_max) { v = vv; // The initial velocity determines the height can be reached初始速度决定了可以达到的高度 len = int(v / v_max * len_max); // v : v_max = len : len_max速度快的,尾影会拖得长一些 } void LightLine::Draw() const { srand((unsigned)(time)(NULL)); int Light_color = rand() % 360; //绘制上升曲线,是一列圆的绘制,第一个圆形亮度最高,后面的亮度逐渐减少,达到渐变的效果 for (int j = py; j < py + len; ++j) { float hsv_v = 0.8f * (len - (j - py)) / len + 0.2f; // Gradient color这是亮度 setfillcolor(HSVtoRGB(float(Light_color), 1.0f, hsv_v)); solidcircle(px, j, 1); } } void LightLine::Move() { if (v == 0) return; if (ct == 0) { ct = clock(); Draw(); return; } clock_t t = clock() - ct; ct = clock(); double v_cur = v - g * t / 1000.0; // The -y axis is positiva for the velocity //除以1000的原因是,公式是以s做单位,程序里是ms作为单位,1s=1000ms if (v_cur > 0) { py += int(10 * (v_cur * v_cur - v * v) / 2 / g);//上升运动高度 vt^2-v0=2gh v = v_cur; } else { //如果v_cur<0,则表示可以到顶点了。 py -= int(10 * v * v / 2 / g);//自由落体的高度 0-vt^2=2gh v = 0;//因为顶点烟花爆炸 } len = int(v / v_max * len_max); Draw(); } class ParticleSwarm { struct Particle { int x; //表示粒子的运动过程的x坐标 int y; //表示粒子的运动过程的y坐标 int z = 0; // Z axis vertical screen inword Z轴垂直屏幕输入 double vy; // The y axis is positiva for the velocity结构体里面的vy是每个粒子的y方向速度 Particle(int xx, int yy, double vv) :x(xx), y(yy), vy(vv) {} }; public: ParticleSwarm(int, int, float); void Draw() const; void Move(); bool Finish() const { return vec.size() <= 1; } private: double vx; double vz = 0; float hsv_h; // Color parameter clock_t ct = 0; std::list vec; // For saving particles }; ParticleSwarm::ParticleSwarm(int x, int y, float colorh = float(rand() % 256)) { // Cylindrical coordinate to xyz (parameters: len, radian_xz, radian_yx) hsv_h = colorh + rand() % 20; hsv_h = hsv_h > 255 ? hsv_h - 256 : hsv_h; //Z轴的负向对着人,即人对着屏幕的方向为Z轴的正向 double vm = v_max / 2 * (rand() % 5 + 15.0) / 25.0; double radian_xz = (rand() % 360) * PI / 180;//X轴偏向Z轴的角度0--2*PI double radian_xy = (rand() % 90) * PI / 180 + PI / 2;//X轴偏向Y轴的角度PI/2--PI vx = vm * cos(radian_xy) * cos(radian_xz);//向量在X轴的投影 vz = vm * cos(radian_xy) * sin(radian_xz);//向量在Z轴的投影 double vy = vm * sin(radian_xy); //向量在Y轴的投影 //len表示粒子运动轨迹的长度,也可以认为是装填粒子的数量 int len = rand() % 30 + 50;//rand() % 30 + 50这个是源代码的数值,数值越大,烟花爆炸的范围,散开的范围就越大。 //这一段刻画的是爆炸花束粒子中的其中一条线 while (len) { // Use len as time parameter //目标像素位置=初始像素位置+偏移米×10 int xx = x + int(10 * vx * len / 200.0); //int zz = int(10 * vz * len / 200.0); double cvy = vy - g * len / 200.0; int yy = y + int(10 * (cvy * cvy - vy * vy) / 2 / g); vec.push_back(Particle(xx, yy, cvy)); --len; } } void ParticleSwarm::Draw() const { int n = 0; auto size = vec.size(); for (auto& x : vec) { if (x.x >= 0 && x.x < GW && x.y >= 0 && x.y < GH) { //烟花线条的尾端亮度最低,反之首端是比较亮的 float cv = 0.2f + 0.8f * (size - n) / size - x.z; //原来的float cv = 0.2f + 0.8f * (size - n) / size - x.z / 40 * 0.1f auto color = HSVtoRGB(hsv_h, 1.0f, cv > 0 ? cv : 0); if (x.z < 0) // Z axis vertical screen inword如果烟花是往屏幕外扩散的话,就把像素点变大 { setfillcolor(color); solidcircle(x.x, x.y, abs(x.z) / 80 > 1 ? 2 : 1); } else putpixel(x.x, x.y, color); } ++n; } } void ParticleSwarm::Move() { if (ct == 0) { ct = clock(); Draw(); return; } for (int i = 0; i < 3 && vec.size() > 1; i++)// vec.pop_back(); // Delete particles for shortening length画面每次刷新删除3个末尾粒子 clock_t t = clock() - ct; ct = clock(); for (auto& x : vec)//爆炸花束之中一条光纤的粒子持续运动 { double vy_cur = x.vy - g * t / 1000.0; x.x += int(10 * vx * t / 1000.0); x.y += int(10 * (vy_cur * vy_cur - x.vy * x.vy) / 2 / g); x.z += int(10 * vz * t / 1000.0); x.vy = vy_cur; } Draw(); } class Fireworks { public: Fireworks(int, int); void Move(); bool Empty() const { return vec.empty(); } private: std::list vec; }; Fireworks::Fireworks(int x, int y) { bool colorful = rand() % 100 < 20 ? true : false;//1/5的几率判断 float h = float(rand() % 256); int n = rand() % 5 + 45;//烟花升到顶点后,爆炸出来的光线量 for (int i = 0; i < n; i++) { if (colorful)//决定烟花的爆炸光线,每一条是否是同一颜色的。1/5的几率判断 vec.push_back(ParticleSwarm(x, y)); else vec.push_back(ParticleSwarm(x, y, h)); } } void Fireworks::Move() { std::list toDel; for (auto it = vec.begin(); it != vec.end(); ++it) { if (it->Finish())//如果该粒子群里的粒子数只剩下一个,则跳过 { toDel.push_back(it); continue; } it->Move();//如果粒子群里的粒子数不只是剩下一个,则继续描画它的轨迹 } for (auto& x : toDel) vec.erase(x); } void settextstyle( int nHeight, int nWidth, LPCTSTR lpszFace ); int main() { PlaySound(LPWSTR(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC | SND_LOOP);//这个需要加入一段wav格式的音频,CSDN上传不了,可以不要这一个 //outtextxy(10, 10,'a'); //Sleep(200000); initgraph(GW, GH); setrop2(R2_MERGEPEN); srand((unsigned)time(nullptr)); settextcolor(RGB(0, 255, 13)); outtextxy(10, 10, L"新年好"); Sleep(200); outtextxy(20, 20, L"新年好"); Sleep(200); outtextxy(30, 30, L"新年好"); Sleep(200); outtextxy(40, 40, L"新年好"); Sleep(200); outtextxy(50, 50, L"新年好"); Sleep(200); outtextxy(590, 10, L"新年好"); Sleep(200); outtextxy(580, 20, L"新年好"); Sleep(200); outtextxy(570, 30, L"新年好"); Sleep(200); outtextxy(560, 40, L"新年好"); Sleep(200); outtextxy(550, 50, L"新年好"); Sleep(1000); settextcolor(RED); settextstyle(50, 20, 0); outtextxy(50, 80, L"新年好啊!"); Sleep(1000); outtextxy(275, 80, L"祝愿我的好友"); Sleep(1000); outtextxy(50, 130, L"新一年暴富暴帅,快乐多好运多"); Sleep(1000); outtextxy(50, 180, L"平平安安,团团圆圆幸福年"); Sleep(1000); outtextxy(50, 230, L"身体健康,万事如意"); Sleep(1000); outtextxy(50, 280, L"平安喜乐,早日脱单"); Sleep(1000); outtextxy(50, 330, L"我的祝福早到!送给最漂亮 最美丽 "); outtextxy(45, 380, L"最温柔 最大方 最体贴 最天真的您"); Sleep(1000); Sleep(5000); Sleep(2000); // Refresh once in 50ms clock_t ct = clock(); // LightLine list std::list vec; vec.push_back(LightLine()); // Fireworks list std::list vec2; BeginBatchDraw(); while (!(GetAsyncKeyState(VK_ESCAPE) & 0x8000)) { if (clock() - ct > 50) { cleardevice(); ct = clock(); // LightLine list std::list toDel; if (vec.size() == 0) vec.push_back(LightLine()); else if (vec.size() < n_max && rand() % 100 < 20 && (--vec.end())->OverLine()) vec.push_back(LightLine()); for (auto it = vec.begin(); it != vec.end(); ++it) { if (it->Stopped()) { vec2.push_back(Fireworks(it->GetX(), it->GetY())); toDel.push_back(it); continue; } it->Move(); } for (auto& it : toDel) vec.erase(it); // Fireworks list std::list toDel2; for (auto it = vec2.begin(); it != vec2.end(); ++it) { if (it->Empty()) { toDel2.push_back(it); continue; } it->Move(); } for (auto& it : toDel2) vec2.erase(it); FlushBatchDraw(); } Sleep(1); } EndBatchDraw(); closegraph(); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)