DirectX3D游戏制作之---粒子效果的实现
引言:
既不回头,何必不忘;既然无缘,何需誓言。今日种种,似水无痕;明夕何夕,君已陌路。
----赵灵儿《仙剑奇侠传一》
-------------------------------------------分 割 线-------------------------------------------------
今天这个程序主要是在之前的程序改进所得,主要增加了粒子效果,当然还加了一些人物,,让程序看上更加饱满了一些,上一篇已经把基本要讲的内容都写了,今天主要是增加了粒子效果。场景没有换,不过把人物换了,增加了点人物。不过这次的观察方式比较酷炫,这次是骑在一条小龙身上观察的。
可能有人会说无图无真相,所以按照惯例,我先把程序截图给出:
骑在小龙身上是不是很酷炫啊(小龙附带动画效果)
在小龙身上,前进、后退、向左、向右、转换方向、旋转等操作都可以实现 ,这样就可以很好地观察场景了。
首先往高处飞,看到一只仙鹤正在天上盘旋:
不过在它的隔壁还有一只凤凰哦:
好了,看过了那么多的动物,来看一看人吧!(可惜动画效果图片展示不出来)
先来看一看菱纱(韩菱纱---仙四女主角),也是我很喜欢的一个女主角,敢爱敢恨,就是结局让人痛心!
在往低处飞,我们来看一看正在舞剑的陆雪琪吧(诛仙青云志正在热播,不过个人不怎么感冒,看了一点,发现没有书中的那种感觉,不过也确实很难演出书中的感觉),舞剑的姿势还是挺美的。
最后来一个帅气的男主角收尾吧!
---------------------------------------------------------分 割 线----------------------------------------------------------------------
好了,看完之后,你应该发现了,这次虽然与上一次的场景相类似,不过这次多了雪花粒子的效果。相信细心的你肯定已经发现了。好了,这就是今天主要的内容,雪花粒子,还特意加入了风,使得粒子随风飘扬,这样的效果还是挺好的。
在这之前,先要简单说一下什么是粒子吧!自从1983年,粒子系统的概念首次提出以来,粒子系统就开始广泛应用在计算机各种模糊景物的模拟。经常使用的粒子系统模拟的现象有火焰、爆炸、烟、以及流水、火花、落叶等等,也包括今天我们所使用的雪花粒子。
一般情况下,粒子的几何性质都十分简单,可以用一个像素,或者一个小的多边形来表示。需要注意的是,粒子系统的最大缺陷就是,当粒子数量很大的时候,对运行的机器性能的要求会很大,如果性能跟不上,那么就会起到适得其反的效果,特别是在游戏之后,电脑很卡,谁还有心思玩你的游戏啊!
我们可以看一下微软写的一个粒子系统的效果:
有没有觉得很酷炫啊,不过这里面的代码可以说很复杂,毕竟是微软大师写出来的代码,质量很高。所以读起来自然会复杂。希望在以后能写出来像这样的好看的粒子效果(哪怕是看懂之后的模仿!哈哈)。
说完了这些之后,我们来看一看源码吧:(先来看一看粒子类的定义)
//粒子类
class SnowParticleClass
{
public:
#define PARTICLE_NUMBER 3000 //雪花粒子的总个数
#define SNOW_SYSTEM_LENGTH_X 20000 //下雪区域的长度
#define SNOW_SYSTEM_WIDTH_Z 20000 //下雪区域的宽度
#define SNOW_SYSTEM_HEIGHT_Y 15000 //下雪区域的高度typedef enum WindDirection //枚举类型,风的方向{North = 0,South = 1,West = 2,East = 3}Direction;struct POINTVERTEX{float x, y, z; //顶点坐标float u, v; //顶点纹理坐标};
#define D3DFVF_POINTVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)struct SNOWPARTICLE{float x, y, z; //坐标位置float RotationY; //顶点绕自身Y轴旋转的角度float RotationX; //顶点绕自身X轴旋转的角度float FallSpeed; //顶点的下落速度float RotationSpeed; //顶点的旋转速度int TextureIndex; //纹理索引数};struct WIND //风结构体{float WindSpeed; //风速Direction Dir; //方向float RotationY; //风绕Y轴旋转的角度float RotationSpeed; //风的旋转速度(风向的变换速度)WIND(float wSpeed = 50.0f, Direction dir = South, float RoY = 0.0f, float Rspeed = 0.0f):WindSpeed(wSpeed), Dir(dir), RotationY(RoY), RotationSpeed(Rspeed){} //构造函数}
public:SnowParticleClass(LPDIRECT3DDEVICE9 pd3dDevice); //类的构造函数~SnowParticleClass(); //类的析构函数//常规函数HRESULT InitSnowParticle(); //雪花粒子类的初始化函数HRESULT UpdateSnowParticle(float fElapsedTime); //粒子系统更新函数HRESULT RenderSnowParticle(); //粒子系统渲染函数
private:LPDIRECT3DDEVICE9 m_pd3dDevice; //D3D设备对象SNOWPARTICLE m_Sonw[PARTICLE_NUMBER];//雪花粒子数组WIND m_wind; //风的对象LPDIRECT3DVERTEXBUFFER9 m_pVertexBuffer; //保存粒子数据的顶点缓存LPDIRECT3DTEXTURE9 m_pTexture[6]; //雪花粒子纹理
}; 接下来再来看一下
粒子类的实现:
//-----------------------------------雪花粒子类相关函数的实现--------------------------
SnowParticleClass::SnowParticleClass(LPDIRECT3DDEVICE9 pd3dDevice) //构造函数
{m_pd3dDevice = pd3dDevice;m_pVertexBuffer = NULL;for (int i = 0; i < 6; i++){m_pTexture[i] = NULL;}
}
//初始化函数
HRESULT SnowParticleClass::InitSnowParticle()
{//给一个时间种子srand(GetTickCount());//初始化雪花粒子for (int i = 0; i < PARTICLE_NUMBER; i++){m_Sonw[i].x = (float)(rand() % SNOW_SYSTEM_LENGTH_X - SNOW_SYSTEM_LENGTH_X / 2);m_Sonw[i].z = (float)(rand() % SNOW_SYSTEM_WIDTH_Z - SNOW_SYSTEM_WIDTH_Z / 2);m_Sonw[i].y = (float)((rand() % (SNOW_SYSTEM_HEIGHT_Y / 2)) + SNOW_SYSTEM_HEIGHT_Y / 2);m_Sonw[i].FallSpeed = 300.0f + rand() % 500;m_Sonw[i].RotationX = (rand() % 100) / 50.0f * D3DX_PI;m_Sonw[i].RotationY = (rand() % 100) / 50.0f * D3DX_PI;m_Sonw[i].RotationSpeed = 5.0f + rand() % 10 / 10.0f;m_Sonw[i].TextureIndex = rand() % 6;}//创建雪花粒子的顶点缓存if (FAILED(m_pd3dDevice->CreateVertexBuffer(sizeof(POINTVERTEX)* 4, 0, D3DFVF_POINTVERTEX, D3DPOOL_MANAGED, &m_pVertexBuffer, NULL))){return E_FAIL;}POINTVERTEX vertices[] ={{ -20.0f, 0.0f, 0.0f, 0.0f, 1.0f },{ -20.0f, 40.0f, 0.0f, 0.0f, 0.0f },{ 20.0f, 0.0f, 0.0f, 1.0f, 1.0f },{ 20.0f, 40.0f, 0.0f, 1.0f, 0.0f },};//加锁void * pVertices;m_pVertexBuffer->Lock(0, sizeof(vertices), (void **)&pVertices, 0);//访问memcpy(pVertices, vertices, sizeof(vertices));//解锁m_pVertexBuffer->Unlock();//创建6中雪花纹理D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow1.jpg", &m_pTexture[0]);D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow2.jpg", &m_pTexture[1]);D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow3.jpg", &m_pTexture[2]);D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow4.jpg", &m_pTexture[3]);D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow5.jpg", &m_pTexture[4]);D3DXCreateTextureFromFile(m_pd3dDevice, L"GameMedia\\snow6.jpg", &m_pTexture[5]);return S_OK;
}
//读取文件内容函数
HRESULT SnowParticleClass::UpdateSnowParticle(float fElapsedTime)
{static float wind_dx = 0.0f, wind_dz = 0.0f;//定义两个静态变量,用于存放x轴方向上的速度、z轴方向上的速度//更新风的状态m_wind.WindSpeed += rand() % 150;m_wind.RotationSpeed = (float)(2.0f / 50.0f) * D3DX_PI;m_wind.RotationY += fElapsedTime * m_wind.RotationSpeed;wind_dz = sin(m_wind.RotationY) * 1000; //旋转角度的正弦值wind_dx = cos(m_wind.RotationY) * 1000; //旋转角度的余弦值if (wind_dx >= -0.05f && wind_dx <= 0.05f && wind_dz < 0){m_wind.Dir = North; //更新风的方向状态}else if (wind_dx >= -0.05f && wind_dx <= 0.05f && wind_dz >= 0){m_wind.Dir = South;}else if (wind_dz >= -0.05f && wind_dz <= 0.05f && wind_dx < 0){m_wind.Dir = West;}else if (wind_dz >= -0.05f && wind_dz <= 0.05f && wind_dx >= 0){m_wind.Dir = East;}//用一个for循环,更新每个雪花粒子的当前位置和角度 for (int i = 0; i < PARTICLE_NUMBER; i++){m_Sonw[i].y -= m_Sonw[i].FallSpeed * fElapsedTime;if (m_Sonw[i].y <= 0){m_Sonw[i].y = SNOW_SYSTEM_HEIGHT_Y; //雪花粒子落到地面}m_Sonw[i].x += wind_dx * fElapsedTime; //雪花的X轴坐标m_Sonw[i].z += wind_dz * fElapsedTime; //雪花的Z轴坐标//更改自旋角度m_Sonw[i].RotationX += m_Sonw[i].RotationSpeed * fElapsedTime;m_Sonw[i].RotationY += m_Sonw[i].RotationSpeed * fElapsedTime;}return S_OK;
}
//渲染函数
HRESULT SnowParticleClass::RenderSnowParticle()
{//禁用照明效果m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);//设置纹理状态m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);//将纹理颜色混合后的第一个参数的颜色值用于输出m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTOP_SELECTARG1);//纹理颜色混合的第一个参数的值就取纹理的颜色值m_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);//选用过滤状态方式、采用线性纹理过滤m_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);//放大过滤状态采用线性纹理状态//设置Alpha混合系数m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); //打开m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); //源混合系数设为1m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); //目标混合系数设为1//设置剔除模式为不提出任何面m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);//渲染雪花for (int i = 0; i < PARTICLE_NUMBER; i++){//构造并设置当前雪花粒子的世界矩阵static D3DXMATRIX matYaw, matPitch, matTrans, matWorld;D3DXMatrixRotationY(&matYaw, m_Sonw[i].RotationY);D3DXMatrixRotationX(&matPitch, m_Sonw[i].RotationX);D3DXMatrixTranslation(&matTrans, m_Sonw[i].x, m_Sonw[i].y, m_Sonw[i].z);matWorld = matYaw * matPitch * matTrans;m_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); //设置雪花的世界矩阵//渲染当前的雪花粒子//设置雪花的纹理状态m_pd3dDevice->SetTexture(0, m_pTexture[m_Sonw[i].TextureIndex]);//把包含顶点信息的顶点缓冲区与流水相关联m_pd3dDevice->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(POINTVERTEX));m_pd3dDevice->SetFVF(D3DFVF_POINTVERTEX); //设置为灵活顶点格式m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); //绘制顶点}//恢复相关渲染状态:Alpha混合、剔除状态、光照m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); //恢复渲染状态m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); //开启背面消影m_pd3dDevice->SetRenderState(D3DRS_LIGHTING, true); //设置光照状态return S_OK;
}SnowParticleClass::~SnowParticleClass() //析构函数,主要进行状态的释放
{SAFE_RELEASE(m_pVertexBuffer);for (size_t i = 0; i < 6; i++){SAFE_RELEASE(m_pTexture[i]);} 具体就不解释了,大部分都在代码里面写好了注释,估计大家都看的懂。
最后放一张 雪花粒子类的图,作为今天的结束吧!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
