#define _XOPEN_SOURCE
#define _GNU_SOURCE
#define _BSD_SOURCE
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <windows.h>
#define G 9.8 // 重力加速度 /*可变*/
#define sleeptm 42 // 保持 24 帧每秒 (加上运行时间) /*可变:每秒的帧数*/
typedef struct _FPOINT
{
double x;
double y;
} FPOINT;
typedef struct Firework
{
FPOINT startp; //出发点 (正常坐标系,x=Pos_x,y=-Pos_y)
double startv; //初速度
double angle; //发射角 , RAD
int color; //烟花颜色(1-15)
int petal; //花瓣个数
} FW;
void Pos(int x,int y);
void color(int type);
void getcoord(FPOINT *endp,FPOINT startp,double startv,double angle,double g,int mstime);
int _round(double origin);
double mod(double a,double m,int *i);
FW * launchFATfirework(FW FATHER,double g);
void launchSONfirework(int argc,FW * SONarray,double g);
void Pos(int x,int y)
/*
设置光标位置
运行框左上方:(0,0)
从定位光标开始打印
若换行,变为从行首打印
*/
{
COORD pos;
pos.X=x;
pos.Y=y;
HANDLE hOutPut;
hOutPut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutPut,pos);
}
void color(int type)
/*设置颜色*/
{
if((type>=0)||(type<=15))
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),type);
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);
}
}
int _round(double origin)
/*四舍五入函数
用于烟花位置打印
(精确度为1)*/
{
double minus_origin=-origin;
if(origin>=0)
{
if(origin-(int)origin>=0.5)
{
return ((int)origin)+1;
}
else
{
return (int)origin;
}
}
else
{
if(minus_origin-(int)minus_origin>=0.5)
{
return (int)origin-1;
}
else
{
return (int)origin;
}
}
}
double mod(double a,double m,int *i)
//广义上取余数函数
//因为求余符号 % 只能用于整数
{
*i=0;
if(m<=0)
{
return -1;
}
if(a>=0)
{
while((*i)*m<=a)
{
(*i)++;
}
return a-(*i-1)*m;
}
else
{
while((*i)*m+a<0)
{
(*i)++;
}
return a+(*i)*m;
}
}
void getcoord(FPOINT *endp,FPOINT startp,double startv,double angle,double g,int mstime)
// 获取烟花坐标(严格依据运动学定理)
{
endp->x=startp.x+startv*cos(angle)*mstime/1000;
endp->y=startp.y+startv*sin(angle)*mstime/1000-g*mstime*mstime/2000000;
}
FW * launchFATfirework(FW FATHER,double g) // 发射一级烟花
{
int mstime=0,explosion,i,count;
if(mod(FATHER.angle,2*M_PI,&i)<M_PI)
{
explosion=(int)(1000*(FATHER.startv*sin(FATHER.angle)/g)); // 当烟花飞行至最高点时爆炸
}
else
{
explosion=3000; /*可变:一级烟花向下发射时的爆炸时间*/
}
FPOINT now;
while(mstime<=explosion)
{
getcoord(&now,FATHER.startp,FATHER.startv,FATHER.angle,g,mstime);
Pos(_round(now.x),-_round(now.y));
color(FATHER.color);
printf("*");
Sleep(sleeptm);
mstime+=sleeptm;
system("cls");
}
FW *SONarray=(FW *)malloc(sizeof(FW)*FATHER.petal);
FW *ptr=SONarray;
for(count=0;count<FATHER.petal;count++,ptr++)
{
ptr->startp.x=now.x;
ptr->startp.y=now.y;
ptr->startv=15; /*可变:二级烟花的初速度*/
ptr->angle=0.5+2*M_PI/FATHER.petal*count; // 设置为均匀放射(相邻两初速度方向夹角相等)
ptr->color=FATHER.color;
ptr->petal=0; // 每瓣二级烟花附带的三级烟花数量 (一般设为 0 )
}
return SONarray;
}
void launchSONfirework(int argc,FW * SONarray,double g)
{
int mstime=0,i,count;
FPOINT p[argc];
FW *ptr=SONarray;
while(mstime<1000)//explosion /*可变:二级烟花爆炸时间*/
{
for(count=0;count<argc;count++)
{
getcoord(&p[count],SONarray[count].startp,SONarray[count].startv,SONarray[count].angle,g,mstime);
Pos(_round(p[count].x),-_round(p[count].y));
color(SONarray[count].color);
printf("*");
}
Sleep(sleeptm);
mstime+=sleeptm;
system("cls");
}
}
int main()
{
int c;
FPOINT p={100,-50}; /*可变:一级烟花起始点坐标(正常坐标系,x轴向右,y轴向上)*/
FW father=
{
p,
25, /*可变:初速度*/
1.8, /*可变:发射角(RAD)*/
4, /*可变:颜色*/
5 /*可变:附带二级烟花数目*/
}; /*结构体变量内容可修改*/
FW* son=launchFATfirework(father,G);
#undef G
#define G 0.05
launchSONfirework(5,son,G);
free(son);
return 0;
}