一.深蓝色的天空中布满了璀璨的星星,突然天空滑过一颗流星,流星拖着长长的尾巴,悄无声息地落在空旷的原野中,之后,许多流星飞快地从眼前划过

二.我们应该如何用c++写一场流星雨呢?
一颗颗流星飞下,我们把它抽象一下,把流星作为一个对象;
同理,一闪一闪的星星,我们把星星也作为一个对象。
在此之前我们需要创建一个窗口(1200,700)(窗口的大小随意,合适就好)
流星在黑窗口下不断滑过,似乎欠缺了什么,那我们加入一个背景

好了,我们现在有了流星和星星两个对象,那它们分别应该具有什么属性?
首先是流星:
流星要有一张图,我们准备两张,交替出现,到达闪烁的效果。


2.流星要能移动,而且是斜着移动,那我们给它x,y,speed三个属性,
每次移动时让x和y都加上speed。
3.那流星该在哪里出现呢?如果全出现在窗口中好像会有点突兀,
那我们把x初始成负数,y也初始成负数,speed初始成正数,
这样这个流星有从高处滑下的效果。
4.那流星滑到右下角,出了窗口怎么办?要析构掉它吗?
不不不,我们给这个流星重新初始化,让它重新滑。
5.流星速度太快了该怎么办?用Sleep这个函数睡一会吗?
那可不行,程序会卡在那。那我们就再给流星一个属性meteor_move_stay=0,
每次绘制流星时meteor_move_stay++,当绘制了五次流星时再移动流星,然后重置meteor_move_stay。
6.流星雨,应该有很多流星,那我们就构建一个流星数组,这个数组该有多大呢?
我取的是128个流星,另外每个流星的每个属性在一定范围内随机。
接下来就是星星:
星星该有什么属性呀?动态的和静态的相比哪个更好看?
我觉得还是动态的好看,那就先给星星x,y,speed这三个属性。
星星以什么形式输出到窗口上?
星星在远处看就是一个点,那我们要怎么表示这个点呢?
输出一个像素点吗,这样好像太小了;那我们调用solidcicle这个函数画填充⚪,
再给星星加个属性r。五颜六色的星星似乎更好看,那我们再给星星加个属性color,
再画填充⚪前调用setfillcolor,给它上色。
星星该怎么移动呢?
每次星星移动时,让x+speed就好了,纵向再移动就显得有些乱了。
4.星星移动地太快怎么办
那我们再给他加个属性star_move_stay,参考上面流星。
5.有多少星星呢?
我们构建一个星星数组,每个星星的每个属性在一定范围内随机,我取的大小是666,感觉吉利。
我们总结一下:
流星和星星它们分别都需要三个成员函数,构造函数来初始化,一个函数来绘制,一个函数来移动。
好像还有最后一个问题,流星和星星不断移动靠的是把图片输出到窗口上,下次移动是需要擦除
上次输出的图片,那我们调用cleardevice清屏,再把流星和星星的绘制和移动放到一个循环中。
不过这又产生了一个问题,闪屏太严重了,那我们就调用BeginBatchDraw, FlushBatchDraw,EndBatchDraw这三个专门解决闪屏问题的函数。
三.流星雨写好了,我们再加个前言引出它会不会更好
首先我们再找一个背景图,
然后调用outtextxy,settextcolor,settextstyle, setbkmode这些函数在窗口上输出文字,
最后过了一定时间就切换到流星雨。

四.下面是具体的代码,我们遵循模块化编程的思想,将一定功能的代码封装成一个函数
#include<iostream>
#include<easyx.h>
#include<conio.h>
#pragma comment(lib,"winmm.lib")
#define STAR_NUM 666
#define METEOR_NUM 128
#define WIDTH 1200//窗口宽度
#define HEIGHT 700//窗口高度
using namespace std;
IMAGE bk[2];//背景图片
IMAGE Meteor[2];//流星图片
class STAR
{
public:
int x, y, r, speed, star_move_stay;
COLORREF color;
STAR()
{
x = rand() % WIDTH;
y = rand() % HEIGHT;
r = rand() % 1 + 1;
speed = rand() % 4 + 1;
color = RGB(rand() % 256, rand() % 256, rand() % 256);
star_move_stay = 0;
}
void DrawStar()
{
setfillcolor(color);
solidcircle(x, y, r);
star_move_stay++;
}
void MoveStar()
{
star_move_stay = 0;
x += speed;
if (x > WIDTH)
x = 0;
}
}star[STAR_NUM];
class METEOR
{
public:
int x, y, speed,meteor_move_stay;
METEOR()
{
x = rand() % (WIDTH*2) - WIDTH;//-1200~1200
y = 20 - 200;
speed = rand() % 10 + 1;
}
void DrawMeteor()
{
putimage(x, y, &Meteor[rand() % 2], SRCPAINT);
meteor_move_stay++;
}
void MoveMeteor()
{
meteor_move_stay = 0;
x += speed;
y += speed;
if ((x >= WIDTH) || (y >= HEIGHT))
{
x = rand() % (2 * WIDTH) - WIDTH;//-1200~1200
y = 20 - 200;
speed = rand() % 15 + 1;
}
}
}meteor[METEOR_NUM];
void Init();
void Introduce();
void Move();
int main()
{
initgraph(1200, 700);
Init();
Introduce();
Move();
}
void Init()
{
loadimage(&Meteor[0], "./star1.jpg", 50, 50);
loadimage(&Meteor[1], "./star2.jpg", 50, 50);
loadimage(&bk[0], "./bk.jpg", WIDTH, HEIGHT);
loadimage(&bk[1], "./star_sky.jpeg", WIDTH, HEIGHT);
}
void Introduce()
{
putimage(0, 0, &bk[0]);
srand(time(0));
setbkmode(TRANSPARENT);
BeginBatchDraw();
while (true)
{
settextstyle(200, 0, "宋体");
settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
outtextxy(200, 66, "新年快乐");
settextstyle(100, 0, "宋体");
settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
outtextxy(66, 286, "让我们一起看场流星雨吧");
settextstyle(88, 0, "宋体");
settextcolor(RGB(rand() % 256, rand() % 256, rand() % 256));
outtextxy(888, 450, "-水镜Q");
Sleep(500);
if (clock() < 1000)
outtextxy(128, 456, "6");
else if ((clock() < 2000) && (clock() > 1000))
outtextxy(208, 456, "5");
else if ((clock() < 3000) && (clock() > 2000))
outtextxy(288, 456, "4");
else if ((clock() < 4000) && (clock() > 3000))
outtextxy(368, 456, "3");
else if ((clock() < 5000) && (clock() > 4000))
outtextxy(448, 456, "2");
else if ((clock() < 6000) && (clock() > 5000))
outtextxy(528, 456, "1");
else if (clock() > 6000)
break;
FlushBatchDraw();
}
EndBatchDraw();
}
void Move()
{
BeginBatchDraw();
while (!_kbhit())
{//任意键结束
cleardevice();
putimage(0, 0, &bk[1]);
for (size_t i = 0; i < STAR_NUM; i++)
{
star[i].DrawStar();
if (star[i].star_move_stay >= 5)
star[i].MoveStar();
}
for (size_t i = 0; i < METEOR_NUM; i++)
{
meteor[i].DrawMeteor();
if (meteor[i].meteor_move_stay >= 5)
meteor[i].MoveMeteor();
}
FlushBatchDraw();
}
EndBatchDraw();
}
里面还可以加音乐,大家自己操作,最后祝大家新年快乐