可以实现各种喷射状的运动状态,按上下左右键分别移动粒子,按y键切换颜色,按7、8、9、0切换不同的纹理,按1、2改变粒子速度、按3、4改变粒子大小
ParticleSys.h
// ParticleSys.h: interface for the CParticleSys class.
//
//
#if !defined(AFX_PARTICLESYS_H__F9DB0BB6_E352_488D_A578_09D57EEE6F42__INCLUDED_)
#define AFX_PARTICLESYS_H__F9DB0BB6_E352_488D_A578_09D57EEE6F42__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define
MAX_PARTICLES 1000 // 定义最大的粒子数
typedef struct
// 创建粒子数据结构
{
bool active; // 是否激活
float life; // 粒子生命
float fade; // 衰减速度
float r; // 红色值
float g; // 绿色值
float b; // 蓝色值
float x; // X 位置
float y; // Y 位置
float z; // Z 位置
float xi; // X 方向移动
float yi; // Y 方向
float zi; // Z 方向
float xg; // X 方向重力加速度
float yg; // Y 方向重力加速度
float zg; // Z 方向重力加速度
}particles;
class CParticleSys
{
public:
CParticleSys();
virtual ~CParticleSys();
public:
void InitParticles();
int DrawParticles();
void ChangeColor();
void ChangeXSpeed(float fOff);
void ChangeYSpeed(float fOff);
void ResetPos();
void ChangeDelay(float fOff);
void ChangeSlow(float fOff);
void ChangeZoom(float fOff);
void SetTexList(GLuint iTexList);
void SetZoom(float fZoom);
void SetXSpeed(float fXSpeed);
void SetYSpeed(float fYSpeed);
void SetSlow(float fSlow);
public:
bool m_rainbow; // 是否为彩虹模式
float m_slowdown; // 减速粒子
float m_xspeed; // X方向的速度
float m_yspeed; // Y方向的速度
float m_zoom; // 沿Z轴缩放
GLuint m_loop; // 循环变量
GLuint m_col; // 当前的颜色
GLuint m_delay; // 彩虹效果延迟
bool m_bXG;
bool m_bYG;
bool m_bXGJ;
bool m_bYGJ;
bool m_bOrg;
private:
particles particle[MAX_PARTICLES]; // 保存1000个粒子的数组
GLuint m_iTexList;
};
#endif // !defined(AFX_PARTICLESYS_H__F9DB0BB6_E352_488D_A578_09D57EEE6F42__INCLUDED_)
Particles.cpp
// ParticleSys.cpp: implementation of the CParticleSys class.
//
//
#include "stdafx.h"
#include "MySDOpenGL.h"
#include "ParticleSys.h"
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
static GLfloat colors[12][3]=
// 彩虹颜色
{
{1.0f,0.5f,0.5f},{1.0f,0.75f,0.5f},{1.0f,1.0f,0.5f},{0.75f,1.0f,0.5f},
{0.5f,1.0f,0.5f},{0.5f,1.0f,0.75f},{0.5f,1.0f,1.0f},{0.5f,0.75f,1.0f},
{0.5f,0.5f,1.0f},{0.75f,0.5f,1.0f},{1.0f,0.5f,1.0f},{1.0f,0.5f,0.75f}
};
CParticleSys::CParticleSys()
{
m_rainbow = true;
m_slowdown = 2.0f; // 减速粒子
m_xspeed = 0; // X方向的速度
m_yspeed = 0; // Y方向的速度
m_zoom = -40.0f; // 沿Z轴缩放
m_loop = 0;
m_col = 0;
m_delay = 0;
m_bOrg = false;
m_bXGJ = false;
m_bYGJ = false;
m_bXG = false;
m_bYG = false;
m_iTexList = 0;
}
CParticleSys::~CParticleSys()
{
}
void CParticleSys::SetXSpeed(float fXSpeed)
{
m_xspeed = fXSpeed;
}
void CParticleSys::SetYSpeed(float fYSpeed)
{
m_yspeed = fYSpeed;
}
void CParticleSys::SetSlow(float fSlow)
{
m_slowdown = fSlow;
}
void CParticleSys::SetZoom(float fZoom)
{
m_zoom = fZoom;
}
void CParticleSys::InitParticles()
{
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
for(m_loop = 0; m_loop < MAX_PARTICLES; m_loop++)
{
particle[m_loop].active = true;
particle[m_loop].life = 1.0f;
particle[m_loop].fade = float(rand() % 100)/1000.0f + 0.003f; // 随机生成衰减速率
particle[m_loop].r = colors[m_loop*(12/MAX_PARTICLES)][0];
particle[m_loop].g = colors[m_loop*(12/MAX_PARTICLES)][1];
particle[m_loop].b = colors[m_loop*(12/MAX_PARTICLES)][2];
particle[m_loop].xi = float((rand() % 50) - 26.0f)*10.0f;
particle[m_loop].yi = float((rand() % 50) - 25.0f)*10.0f;
particle[m_loop].zi = float((rand() % 50) - 25.0f)*10.0f;
particle[m_loop].xg = 0.0f;
particle[m_loop].yg = -0.8f;
particle[m_loop].zg = 0.0f;
particle[m_loop].x = 0.0f;
particle[m_loop].y = 0.0f;
particle[m_loop].z = 0.0f;
}
}
int CParticleSys::DrawParticles()
{
if(m_iTexList == 0)
{
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
else
{
glEnable(GL_TEXTURE_2D);
glCallList(m_iTexList);
glEnable(GL_BLEND);
}
for(m_loop = 0; m_loop < MAX_PARTICLES; m_loop++)
{
if(particle[m_loop].active)
{
float x = particle[m_loop].x;
float y = particle[m_loop].y;
float z = particle[m_loop].z + m_zoom;
glColor4f(particle[m_loop].r, particle[m_loop].g, particle[m_loop].b, particle[m_loop].life);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex3f(x+0.5f,y+0.5f,z);
glTexCoord2d(0,1); glVertex3f(x-0.5f,y+0.5f,z);
glTexCoord2d(1,0); glVertex3f(x+0.5f,y-0.5f,z);
glTexCoord2d(0,0); glVertex3f(x-0.5f,y-0.5f,z);
glEnd();
particle[m_loop].x+=particle[m_loop].xi/(m_slowdown*1000); // 更新X坐标的位置
particle[m_loop].y+=particle[m_loop].yi/(m_slowdown*1000); // 更新Y坐标的位置
particle[m_loop].z+=particle[m_loop].zi/(m_slowdown*1000); // 更新Z坐标的位置
particle[m_loop].xi+=particle[m_loop].xg; // 更新X轴方向速度大小
particle[m_loop].yi+=particle[m_loop].yg; // 更新Y轴方向速度大小
particle[m_loop].zi+=particle[m_loop].zg; // 更新Z轴方向速度大小
particle[m_loop].life-=particle[m_loop].fade; // 减少粒子的生命值
if(particle[m_loop].life < 0.0f)
{
particle[m_loop].life = 1.0f;
particle[m_loop].fade = float(rand() % 100)/1000.0f + 0.003f;
particle[m_loop].x=0.0f; // 新粒子出现在屏幕的中央
particle[m_loop].y=0.0f;
particle[m_loop].z=0.0f;
particle[m_loop].xi=m_xspeed+float((rand()%60)-32.0f); // 随机生成粒子速度
particle[m_loop].yi=m_yspeed+float((rand()%60)-30.0f);
particle[m_loop].zi=float((rand()%60)-30.0f);
particle[m_loop].r=colors[m_col][0]; // 设置粒子颜色
particle[m_loop].g=colors[m_col][1];
particle[m_loop].b=colors[m_col][2];
}
if(m_bYG && particle[m_loop].yg < 1.5f)
particle[m_loop].yg += 0.01;
if(m_bYGJ && particle[m_loop].yg > -1.5f)
particle[m_loop].yg -= 0.01;
if(m_bXG && particle[m_loop].xg < 1.5f)
particle[m_loop].xg += 0.01;
if(m_bXGJ && particle[m_loop].xg > -1.5f)
particle[m_loop].xg -= 0.01;
if(m_bOrg)
{
particle[m_loop].x=0.0f;
particle[m_loop].y=0.0f;
particle[m_loop].z=0.0f;
particle[m_loop].xi=float((rand()%50)-26.0f)*10.0f; // 随机生成速度
particle[m_loop].yi=float((rand()%50)-25.0f)*10.0f;
particle[m_loop].zi=float((rand()%50)-25.0f)*10.0f;
m_bOrg = false;
}
}
}
ChangeColor();
return 1;
}
void CParticleSys::ChangeColor()
{
m_delay ++;
if(m_rainbow && m_delay > 25)
{
if(m_col > 11)
m_col = 0;
m_col ++;
}
}
void CParticleSys::ChangeXSpeed(float fOff)
{
if(fabs(m_xspeed) < 200)
m_xspeed += fOff;
}
void CParticleSys::ChangeYSpeed(float fOff)
{
if(fabs(m_yspeed) < 200)
m_yspeed += fOff;
}
void CParticleSys::ResetPos()
{
m_bOrg = false;
m_bXGJ = false;
m_bYGJ = false;
m_bXG = false;
m_bYG = false;
}
void CParticleSys::ChangeDelay(float fOff)
{
m_delay += fOff;
}
void CParticleSys::ChangeSlow(float fOff)
{
m_slowdown += fOff;
}
void CParticleSys::ChangeZoom(float fOff)
{
m_zoom += fOff;
}
void CParticleSys::SetTexList(GLuint iTexList)
{
m_iTexList = iTexList;
}
应用:
1、粒子和纹理的建立
m_pParticle = new CParticleSys();
m_pParticle->InitParticles();
GenTexList("light02.RGB", 101);
GenTexList("smoke02.RGB", 102);
GenTexList("fire.RGB", 103);
GenTexList("waterexp.RGB", 104);
2、粒子绘制
m_pParticle->DrawParticles();
3、粒子状态改变
void CMySDOpenGLView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
m_pParticle->ResetPos();
switch(nChar)
{
case 39:
m_pParticle->m_bXG = true;
break;
case 37:
m_pParticle->m_bXGJ = true;
break;
case 38:
m_pParticle->m_bYG = true;
break;
case 40:
m_pParticle->m_bYGJ = true;
break;
case 67:
m_pParticle->m_bOrg =true;
break;
case 65:
m_pParticle->ChangeXSpeed(-1.0f);
break;
case 68:
m_pParticle->ChangeXSpeed(1.0f);
break;
case 87:
m_pParticle->ChangeYSpeed(1.0f);
break;
case 88:
m_pParticle->ChangeYSpeed(-1.0f);
break;
case 89:
m_pParticle->m_rainbow = !m_pParticle->m_rainbow;
break;
case '1':
m_pParticle->ChangeSlow(0.01);
break;
case '2':
m_pParticle->ChangeSlow(-0.01);
break;
case '3':
m_pParticle->ChangeZoom(0.1f);
break;
case '4':
m_pParticle->ChangeZoom(-0.1f);
break;
case '6':
m_pParticle->SetTexList(0);
break;
case '7':
m_pParticle->SetTexList(101);
break;
case '8':
m_pParticle->SetTexList(102);
break;
case '9':
m_pParticle->SetTexList(103);
break;
case '0':
m_pParticle->SetTexList(104);
break;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
4、删除粒子
if(m_pParticle != NULL)
{
delete m_pParticle;
m_pParticle = NULL;
}