引言:
既不回头,何必不忘;既然无缘,何需誓言。今日种种,似水无痕;明夕何夕,君已陌路。
----赵灵儿《仙剑奇侠传一》
-------------------------------------------分 割 线-------------------------------------------------
今天这个程序主要是在之前的程序改进所得,主要增加了粒子效果,当然还加了一些人物,,让程序看上更加饱满了一些,上一篇已经把基本要讲的内容都写了,今天主要是增加了粒子效果。场景没有换,不过把人物换了,增加了点人物。不过这次的观察方式比较酷炫,这次是骑在一条小龙身上观察的。
可能有人会说无图无真相,所以按照惯例,我先把程序截图给出:
骑在小龙身上是不是很酷炫啊(小龙附带动画效果)
在小龙身上,前进、后退、向左、向右、转换方向、旋转等操作都可以实现 ,这样就可以很好地观察场景了。
首先往高处飞,看到一只仙鹤正在天上盘旋:
不过在它的隔壁还有一只凤凰哦:
好了,看过了那么多的动物,来看一看人吧!(可惜动画效果图片展示不出来)
先来看一看菱纱(韩菱纱---仙四女主角),也是我很喜欢的一个女主角,敢爱敢恨,就是结局让人痛心!
在往低处飞,我们来看一看正在舞剑的陆雪琪吧(诛仙青云志正在热播,不过个人不怎么感冒,看了一点,发现没有书中的那种感觉,不过也确实很难演出书中的感觉),舞剑的姿势还是挺美的。
最后来一个帅气的男主角收尾吧!
---------------------------------------------------------分 割 线----------------------------------------------------------------------
好了,看完之后,你应该发现了,这次虽然与上一次的场景相类似,不过这次多了雪花粒子的效果。相信细心的你肯定已经发现了。好了,这就是今天主要的内容,雪花粒子,还特意加入了风,使得粒子随风飘扬,这样的效果还是挺好的。
在这之前,先要简单说一下什么是粒子吧!自从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); //源混合系数设为1 m_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]); } 具体就不解释了,大部分都在代码里面写好了注释,估计大家都看的懂。 最后放一张 雪花粒子类的图,作为今天的结束吧!
