//定义粒子系统状态 #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 }