C语言 烟花 粒子系统

废话不多说上视频

 

粒子系统

谁说程序员不懂浪漫的?诺这就是!

环境:decC++

如果大家用Vs的话,因为vc有一些在dev里的函数已经弃用了,关闭安全警告就可以了。

如果不会配置dev的easyx库可以到官网借鉴帮助文档。

该系统基于easyx图库的粒子系统,基本思想来自于视频帧,每一次将所有需要展示的内容一次性绘画,最后再一次性删除,该系统并不使用清屏函数 

     基于物理系统:

实现是为每一个烟花颗粒赋予两个方向上的速度和一个加速度。

加速度模拟重力系统,初速度模拟爆炸时的动能,最后执行到指定高度爆炸,爆炸之后到指定步数停止。

#include<stdio.h> 
#include <graphics.h>
#include <math.h>
#include <time.h>

#include <pthread.h>
typedef struct fireworks{
	int x;
	int y;
	int Vx;
	int Vy;
	int a;
	int tops;
	int r;
	int number;
};
typedef struct fireworksmain{
	int x;
	int y;
	int Vx;
	int Vy;
	int a;
	int r;
	int heightmax;//最大爆炸高度 
	int stop; 
	int i;//对应爆炸效果 
	int n;
};
void delete_ex();
void delete_exs(int n);
int height=600;//屏幕高 
fireworks ax[30][1000];//最多同时绘制10*100个烟花颗粒
fireworksmain as[30];//主烟花 
 //30是烟花升空的数量,100是烟花爆炸的最多数量
int N=0;//烟花的最初数量
int Nmax=100; 

void delay(DWORD ms)
{
	static DWORD oldtime = GetTickCount();
    while(GetTickCount() - oldtime < ms)
		Sleep(1);
	oldtime = GetTickCount();
}
void initialization() {//初始化所有烟花 
	 for(int i=0;i<30;i++) {
	 	as[i].a=-1;
	 	as[i].Vx=0;
	 	as[i].Vy=-5;
	 	as[i].y=height-1;
	 	as[i].r=6;
	 	as[i].heightmax=100+rand()%100;
	 	as[i].stop=0;
	 	as[i].i=i;
	 	as[i].n=100;//
	 	for(int i1=0;i1<1000;i1++){
	 		ax[i][i1].r=2;
	 		ax[i][i1].number=0;
	 		//每25个赋予不同方向的初速度
			 if(i1<=250) {//正方向+x +y 
			 if(i1<100){
			 	ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=rand()%20;
				ax[i][i1].Vy=rand()%14;
			 }if(i1>100&&i1<200){
			 	ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=rand()%15;
				ax[i][i1].Vy=rand()%19;
			 }if(i1>=200&&i1<=250){
			 		ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=rand()%17;
				ax[i][i1].Vy=rand()%19;
			 }else{
			 	ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=rand()%17;
				ax[i][i1].Vy=rand()%19;
			 }
			 	
			 }if(i1>250&&i1<=500){//第一 
			 if(i1>250&&i1<=300){
			 	ax[i][i1].a=-1;//加速度
				ax[1][i1].Vx=-rand()%10;
				ax[i][i1].Vy=rand()%15;
			 }if(i1>300&&i1<=400){
			 		ax[i][i1].a=-1;//加速度
				ax[1][i1].Vx=-rand()%16;
				ax[i][i1].Vy=rand()%15;
			 }if(i1>400&&i1<500){
			 	ax[i][i1].a=-1;//加速度
				ax[1][i1].Vx=-rand()%20;
				ax[i][i1].Vy=rand()%15;
			 }
			 }
			 if(i1>500&&i1<=750){//第一 
			 	ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=-rand()%13;
				ax[i][i1].Vy=-rand()%15;
			 }if(i1>750&&i1<1000){//第一 
			 	ax[i][i1].a=-1;//加速度
				ax[i][i1].Vx=rand()%10;
				ax[i][i1].Vy=-rand()%15;
			 }
		 }
	 }
}
void explosion(int i) {//爆炸效果 
    for(int i1=0;i1<=1000;i1++){
    	if(ax[i][i1].number>100){
	    	as[i].stop=0;
	    	return ;
		}
	}
	 for(int i1=0;i1<1000;i1++){
	 	ax[i][i1].x+=ax[i][i1].Vx;
	 	ax[i][i1].y+=ax[i][i1].Vy;	
	 	ax[i][i1].number++;
	    if(ax[i][i1].number>200){
	    	delete_exs(i);
	    	as[i].stop=0;
		}
	 }
}
void thisa(int i){//爆炸 前 
	 for(int i1=0;i1<1000;i1++){
	 	ax[i][i1].x=as[i].x+rand()%50;
	 	ax[i][i1].y=as[i].heightmax+rand()%50;
	 }
}
void setXY(){//根据物理量改变位置 
	 for(int i=0;i<Nmax;i++) {
	 	if(as[i].stop==1){//烟花为激活态需要绘制 
	 		if(as[i].y<=as[i].heightmax){//到达规定高度绘制爆炸效果 
	 		//开始爆炸需要改变 爆炸效果 
	 		explosion(i);
		 }	else{//否则继续升空 
		 	as[i].y+=as[i].Vy;
		 	as[i].x+=as[i].Vx;
		 	ax[i]->Vy+=ax[i]->a;
		 } 
		}

	 }
}
void  explosion_draws(int i1){//批量绘制爆炸效果
      for(int i=0;i<=1000;i++){
    	if(ax[i1][i].number>200){
	    	as[i1].stop=2;
	    	return ;
		}
	}
	  for(int i=0;i<1000;i++){
	  	setfillcolor(BLUE);
	  	fillcircle(ax[i1][i].x,ax[i1][i].y,ax[i1][i].r) ;
	  }
}
void draws(){//开始一次性绘制 
	 for(int i=0;i<Nmax;i++) {
	 	if(as[i].stop==1){//寻找需要绘制的 主烟花 
	 	    if(as[i].y<=as[i].heightmax&& as[i].stop==1 ){//爆炸效果 
	 	    	explosion_draws(i);
			 }else{
			 	fillcircle(as[i].x,as[i].y,as[i].r) ;
			 }
	 		
	 		
		 }
	 }
}
void  delete_exs(int i){
	  for(int i1=0;i1<1000;i1++){
	  	clearcircle(ax[i][i1].x,ax[i][i1].y,ax[i][i1].r+1) ;
	  	
	  }
}
void delete_ex(){//批量删除 
	for(int i=0;i<Nmax;i++) {
	 	if(as[i].stop==1||as[i].stop==2){//寻
	 	    if(as[i].y<=as[i].heightmax){//
	 	    	delete_exs(i);
			 }else{
			 clearcircle(as[i].x,as[i].y,as[i].r+1) ;
			 }
	 		
	 		if(as[i].stop==2) as[i].stop=0;
		 }
	 }
}
int H(int x,int y){//寻找一个空的 
	for(int i=0;i<30;i++) {
		if(as[i].stop==0){
			for(int i1=0;i1<=1000;i1++){
				ax[i][i1].number=0;
		
			}as[i].y=height-1;
			as[i].stop=1;
			as[i].x=x;
			thisa(i);
			return i;
		}
	}return 0;
}
void* pthraed_1_Code(void* arg){
	MOUSEMSG msg;  
	MOUSEMSG m;  
	 while(1){
	 	 m = GetMouseMsg(); // 获取鼠标消息 
	 	  if (m.uMsg == WM_LBUTTONDOWN) { // 判断是否有鼠标消息  
	 	  printf("sss\n");
            H(m.x,m.y);
        }  
	delay(10) ;
	 }
}
void run(){
	delay(1000);
	 initialization();
	 as[1].stop=1;
	 as[1].x=300;
	 thisa(1);
	 BeginBatchDraw();
	while(1){
	 	setXY();
	 	
	 	draws();//绘制
	 	FlushBatchDraw();
		delay(14);
		delete_ex();
		
	 }EndBatchDraw();
	 
	 draws();	 
}
int draw() {//绘制烟花  同时绘制帧 
	
}
int main(void){
	 initialization();
	 as[1].stop=1;
	 as[1].x=300;
	 thisa(1);
	initgraph(1500,1000);
	 initialization();
	 pthread_t p1,p2;
 
    //初始化线程1(无参)
    pthread_create(&p1,NULL,pthraed_1_Code,NULL);
	run();
	getchar();
	pthread_join(p1,NULL);
	return 0;
}

      缺陷:因为写的急,所以在判断是否到最后一步的地方有待改进,循环判断也有待烟花

最后,祝大家新年快乐!

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值