遊戲中最常見『爆炸』特效.最常見做法是使用『粒子系統』模擬『爆炸』.你大約需要:
- 黑底白圓位圖『bmp』如上圖
- 爆炸特效音頻『wav』
- 『粒子系統』
- 『廣告牌』
其實所有『爆炸』特效都是圓心紋理位圖.只是它使用『廣告牌』技術讓其正對著你即『相機』. 渲染為紅色並讓其隨時間『下墜』『變暗』『縮小』直至消亡.之前模擬『飄雪』特效時使用三級系統.這次我將粒子結構大大簡化.其代碼我都在模擬『爆炸』特效中實現.W
粒子結構體
typedef struct PARTICLE_TYP {
VECTOR3D pos;// 位置
VECTOR3D pos_prev;// 之前位置
VECTOR3D velocity;// 速度與方向
VECTOR3D acceleration;// 加速度
float energy;// 生命週期(秒)
float size;// 尺寸
float size_delta;//增量
float weight;// 重量
float wdight_delta;// 重量增量
float color[4];// 顏色
float color_delta[4];// 顏色增量
}PARTICLE,*PARTICLE_PTR;
爆炸特效結構體
typedef struct EXPLOSION_TPY {
int state;// 狀態
PARTICLE_PTR array;// 數組
int count;// 粒子數量/爆炸量
VECTOR3D origin;// 原點
VECTOR3D velocity;// 速度與方向
VECTOR3D variation;// 速度變量
VECTOR3D acceleration;// 加速度
float energy;// 生命週期(秒)
float size;// 尺寸 5.0f
float size_variation ;// 尺寸變量 2.0f
float spread;// 爆炸傳播範圍
float color[4];// 顏色
VECTOR2D texture_coord[4];// 紋理座標
}EXPLOSION,*EXPLOSION_PTR;
生成『爆炸』特效函式
count:爆炸量大約1-10即可.
pos:位置
spread: 爆炸傳播範圍 0.1即可
void Build_Explosion(EXPLOSION_PTR explosion,int count,VECTOR3D_PTR pos,float spread){
explosion->state = MODEL3D_STATE_ACTIVE;
explosion->count = count; // 粒子數量
explosion->array = (PARTICLE_PTR)malloc(sizeof(PARTICLE)*count);// 分配空間
explosion->spread = spread;// 傳播
explosion->size = 5.0f;// 尺寸
explosion->size_variation = 2.0f;// 尺寸變量
explosion->energy = 1.5f + FRAND_RANGE1() / 2.0f;// 生命週期(秒)
Init_VECTOR3D(&explosion->origin, pos->x, pos->y, pos->z);// 源點
Init_VECTOR3D(&explosion->velocity, 0.0f, 2.0f, 0.0f);// 速度
Init_VECTOR3D(&explosion->variation, 4.0f, 4.0f, 4.0f);// 變量
Init_VECTOR3D(&explosion->acceleration, 0.0f, -5.0f, 0.0f);// 加速度
PARTICLE_PTR particle;// 粒子
for (int i = 0; i < count; ++i){
particle = &explosion->array[i];// 粒子
Buid_Explosion(explosion, particle);//生成粒子『爆炸』特效
}
Set_Pos_DirectSound(&explosion_sound3D, pos->x, pos->y, pos->z);// 設置音源位置
Play_DirectSound(&explosion_sound3D, false);//播放音頻數據
}
生成爆炸粒子函式
void Buid_Explosion(EXPLOSION_PTR explosion, PARTICLE_PTR particle){
// 在發射區隨機位置生成粒子
particle->pos.x = explosion->origin.x + FRAND_RANGE1() * explosion->spread;// 傳播
particle->pos.y = explosion->origin.y + FRAND_RANGE1() * explosion->spread;
particle->pos.z = explosion->origin.z + FRAND_RANGE1() * explosion->spread;
//給粒子隨機速度
particle->velocity.x += FRAND_RANGE1() * explosion->velocity.x;
particle->velocity.y += FRAND_RANGE1() * explosion->velocity.y;
particle->velocity.z += FRAND_RANGE1() * explosion->velocity.z;
// 加速度
particle->acceleration = explosion->acceleration;
// 生命週期
particle->energy = 1.5f + FRAND_RANGE1() / 2.0f;
// 顏色
particle->color[0] = 1.0f;
particle->color[1] = 0.5f + FRAND_RANGE1() * 0.5f;
particle->color[2] = 0.0f;
particle->color[3] = 1.0f;
// 顏色增量
particle->color_delta[0] = 0.0f;
particle->color_delta[1] = -(particle->color[1] / 2.0f) / particle->energy;
particle->color_delta[2] = 0.0f;
particle->color_delta[3] = -1.0f / particle->energy;
// 設置粒子的大小
particle->size = explosion->size + FRAND_RANGE1() * explosion->size_variation;
particle->size_delta = -particle->size / particle->energy;
}
釋放『爆炸』特效函式
void Free_Explosion(EXPLOSION_PTR explosion){
if (explosion->array != NULL)
free(explosion->array);
explosion->state = MODEL3D_STATE_NULL;
memset(explosion, 0, sizeof(EXPLOSION));// 清空
}
更新『爆炸』特效函式
deltaTime:時間間隔
void Update_Explosion(EXPLOSION_PTR explosion, float deltaTime){
PARTICLE_PTR particle;// 粒子
for (int i = 0; i < explosion->count; ){
particle = &explosion->array[i];// 粒子
// 基於時間和速度更新粒子的位置
particle->pos = particle->pos + particle->velocity * deltaTime;
particle->velocity = particle->velocity + particle->acceleration * deltaTime;
particle->energy = particle->energy – deltaTime;
particle->size += particle->size_delta * deltaTime;
particle->color[3] += particle->color_delta[3] * deltaTime;
particle->color[1] += particle->color_delta[1] * deltaTime;
// 將最後一個粒子移動到當前位置,並減少計數.
if (particle->energy <= 0.0)
explosion->array[i] = explosion->array[–explosion->count];
else
++i;
}
if (explosion->count == 0)
Free_Explosion(explosion); // 釋放
}
渲染『爆炸』特效紋理函式
void Render_Explosion2(EXPLOSION_PTR explosion, BILLBOARD_PTR billboard){
float viewMatrix[16];
VECTOR3D right, up, pos;
GLfloat size;
right = billboard->right;
up = billboard->up;
// 壓入當前屬性
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, explosion_texture.ID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBegin(GL_QUADS);
for (int i = 0; i < explosion->count; ++i){
PARTICLE_PTR particle = &explosion->array[i];// 粒子
size = particle->size / 2;
pos = particle->pos;
glColor4fv(particle->color);
glTexCoord2f(0.0, 0.0); glVertex3fv((pos + (right + up) * -size).M);
glTexCoord2f(1.0, 0.0); glVertex3fv((pos + (right – up) * size).M);
glTexCoord2f(1.0, 1.0); glVertex3fv((pos + (right + up) * size).M);
glTexCoord2f(0.0, 1.0); glVertex3fv((pos + (up – right) * size).M);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glPopAttrib();// 彈出當前屬性
}
你必須登入才能發表留言。