|  | 
 
 
 楼主|
发表于 2023-1-30 02:35:59
|
显示全部楼层 
| 本帖最后由 额外减小 于 2023-1-30 21:16 编辑 
 针对改进第一条
 
 想到可以通过减小二级烟花对应重力加速度的值来近似它的有阻力运动。
 例如
 使用
 复制代码        FW* son=launchFATfirework(father,G);
        
#undef G
#define G 0.05
        launchSONfirework(5,son,G);
        
 来使得二级烟花下落较缓
 当然,拟合的不一定像
 
 具体代码
 
 
 复制代码#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;
}
 | 
 |