用粒子系统模拟烟花效果

//定义粒子系统状态
#define PARTICLE_STATE_DEAD                   0
#define PARTICLE_STATE_ALIVE                  1
//定义粒子的类型
#define PARTICLE_TYPE_FLICKER                 0
#define PARTICLE_TYPE_FADE                    1
//定义粒子颜色
#define PARTICLE_COLOR_RED                    0
#define PARTICLE_COLOR_GREEN                  1
#define PARTICLE_COLOR_BLUE                   2
#define PARTICLE_COLOR_WHITE                  3
//定义粒子数
#define MAX_PARTICLES                         512
//颜色调色板索引范围
#define COLOR_RED_START                      32
#define COLOR_RED_END                        47

#define COLOR_GREEN_START                    96
#define COLOR_GREEN_END                      111

#define COLOR_BLUE_START                     144
#define COLOR_BLUE_END                       159

#define COLOR_WHITE_START                    16
#define COLOR_WHITE_END                      31

//风力与重力影响x轴和y轴上速度大小
const float particle_wind = 0.0f;
const float particle_gravity = 0.0f;

typedef struct tagPARTCLE 
{
	int state;   //粒子状态
	int type;    //粒子效果类型
	int x,y;   //位置
	int xv,yv; //粒子速度
	int curr_color; //当前颜色
	int start_color; //开始颜色调色板索引
	int end_color;   //结束颜色调色板索引
	int counter;     //生命周期,帧数
	int max_count;   //最大生命周数
}PARTICLE, *PARTICLE_PTR;

class Particle {
public:
	PARTICLE particles[MAX_PARTICLES];
	Particle() { Init_Reset_Particles(); }

public:
	void Init_Reset_Particles(void);
	void Start_Particle(int type, int color, int count,
						float x, float y, float xv, float yv);
	void Process_Particles(void);
	void Draw_Particles(void);

	//模拟粒子爆炸效果
	void Start_Particle_Explosion(int type, int color, int count,
								 int x, int y, int xv, int yv, int num_particles);

	void Start_Particle_Ring(int type, int color, int count, 
		int x, int y, int xv, int yv, int num_particles);
};


#include "particle.h"

void Particle::Init_Reset_Particles(void)
{
	for (int index=0; index<MAX_PARTICLES; ++index)
	{
		particles[index].state = PARTICLE_STATE_DEAD;
		particles[index].type  = PARTICLE_TYPE_FADE;
		particles[index].x     = 0;
		particles[index].y     = 0;
		particles[index].xv    = 0;
		particles[index].yv    = 0;
		particles[index].curr_color = 0;
		particles[index].start_color= 0;
		particles[index].end_color  = 0;
		particles[index].counter    = 0;
		particles[index].max_count  = 0;
	}
}

void Particle::Start_Particle(int type, int color, int count,
	float x, float y, float xv, float yv)
{
	int pindex = -1; // index of particle

	// first find open particle
	for (int index=0; index < MAX_PARTICLES; index++)
	{
		if (particles[index].state == PARTICLE_STATE_DEAD)
		{
			// set index
			pindex = index; 
			break;
		} // end if   
	}

		// did we find one
		if (pindex==-1)
			return;

		// set general state info
		particles[pindex].state = PARTICLE_STATE_ALIVE;
		particles[pindex].type  = type;
		particles[pindex].x     = x;
		particles[pindex].y     = y;
		particles[pindex].xv    = xv;
		particles[pindex].yv    = yv;
		particles[pindex].counter     = 0;
		particles[pindex].max_count   = count;     

		// set color ranges, always the same
		switch(color)
		{
		case PARTICLE_COLOR_RED:
			{
				particles[pindex].start_color = COLOR_RED_START;
				particles[pindex].end_color   = COLOR_RED_END;
			} break;

		case PARTICLE_COLOR_GREEN:
			{
				particles[pindex].start_color = COLOR_GREEN_START;
				particles[pindex].end_color   = COLOR_GREEN_END;
			} break;

		case PARTICLE_COLOR_BLUE:
			{
				particles[pindex].start_color = COLOR_BLUE_START;
				particles[pindex].end_color   = COLOR_BLUE_END;
			} break;

		case PARTICLE_COLOR_WHITE:
			{
				particles[pindex].start_color = COLOR_WHITE_START;
				particles[pindex].end_color   = COLOR_WHITE_END;
			} break;

			break;

		} // end switch

		// what type of particle is being requested
		if (type == PARTICLE_TYPE_FLICKER)
		{
			// set current color
			particles[pindex].curr_color  = RAND_RANGE(particles[pindex].start_color, particles[pindex].end_color);

		} // end if
		else
		{
			// particle is fade type
			// set current color
			particles[pindex].curr_color  = particles[pindex].start_color;
		} // end if
	
}

void Particle::Process_Particles(void)
{
	for (int index=0; index<MAX_PARTICLES; index++)
	{
		if (particles[index].state == PARTICLE_STATE_ALIVE)
		{
			particles[index].x+=particles[index].xv;
			particles[index].y+=particles[index].yv;

			particles[index].xv+=particle_wind;
			particles[index].yv+=particle_gravity;

			if (particles[index].type==PARTICLE_TYPE_FLICKER)
			{
				particles[index].curr_color = RAND_RANGE(particles[index].start_color,
														 particles[index].end_color);

				if (++particles[index].counter >= particles[index].max_count)
				{
					particles[index].state = PARTICLE_STATE_DEAD;
				}
			}
			else
			{
				if (++particles[index].counter >= particles[index].max_count)
				{
					particles[index].counter = 0;

					if (++particles[index].curr_color>particles[index].end_color)
					{
						particles[index].state = PARTICLE_STATE_DEAD;
					}
				}
			}

			//屏幕边界测试
			if (particles[index].x>SCREEN_WIDTH ||
				particles[index].x<0 ||
				particles[index].y>SCREEN_HEIGHT||
				particles[index].y<0)
			{
				particles[index].state = PARTICLE_STATE_DEAD;
			}
			
		}
	}
}


void Particle::Draw_Particles(void)
{
	DDraw_Lock_Back_Surface();

	for (int index=0; index<MAX_PARTICLES; index++)
	{
		if (particles[index].state==PARTICLE_STATE_ALIVE)
		{
			int x = particles[index].x;
			int y = particles[index].y;

			if (x>=SCREEN_WIDTH || x<0 || y>=SCREEN_HEIGHT || y<0)
				continue;

			Draw_Pixel(x,y,particles[index].curr_color,back_buffer, back_lpitch);
		}
	}

	DDraw_Unlock_Back_Surface();
}

void Particle::Start_Particle_Explosion(int type, int color, int count,
	int x, int y, int xv, int yv, int num_particles)
{
	while(--num_particles >=0)
	{
		int ang=rand()%360;
		float vel = 2+rand()%4;
		Start_Particle(type, color, count,
			x+RAND_RANGE(-50,50), y+RAND_RANGE(-50,50),
			xv+cos_look[ang]*vel, yv+sin_look[ang]*vel);

	}
}


void Particle::Start_Particle_Ring(int type, int color, int count, 
	int x, int y, int xv, int yv, int num_particles)
{
	// this function starts a particle explosion at the given position and velocity
	// note the use of look up tables for sin,cos

	// compute random velocity on outside of loop
	float vel = 200+rand()%4;

	while(--num_particles >=0)
	{
		// compute random trajectory angle
		int ang = rand()%360;

		// start the particle
		Start_Particle(type,color,count,
			x,y, 
			xv+cos_look[ang]*vel, 
			yv+sin_look[ang]*vel);        

	} // end while
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值