本帖最后由 秋声赋 于 2012-3-8 17:12 编辑
大家好,我是秋声赋,上次给大家介绍了关于XNA的一些3D知识,这次给大家介绍下XNA的粒子特效。(其实所有编程的粒子系统的原理都是这样。)
注意:本帖需要基本的几何知识和基本的图形编程知识。
首先简绍Sprite(精灵)。精灵是一个2D图形,在需要绘制的时候始终在屏幕的最前端。Sprite常被用来绘制一些纹理(只有纹理,与3D物体无关的),例如本例中粒子,子弹,2D游戏中的人物等等。注意:在绘制精灵的时候,我们的坐标系统和GDI一样,以屏幕左上角为原点,X轴向右递增,Y轴向下递增。
建立XNA工程后,系统便帮我们建立了一个SpriteBatch类的对象spriteBatch,我们就是利用这个对象来绘制精灵的。
关于spriteBatch,我们现在只了绘图函数。spriteBatch.Draw()有7个重载函数,具体可以到下面网址了解。http://hi.baidu.com/znacm/blog/item/60be0308d078b0286b60fbaf.html
SpriteBatch.Draw( Texture2D texture,Vector2 vector,
Color color)
是本例中经常用到的形式。Texture2D texture 表示精灵所用的纹理(贴图)Vector2 vector 表示精灵的位置(用二维向量表示)Color color 表示颜色遮罩,如果不透明就用Color.Black
以上是Sprite的简介。下面介绍一下XNA的基本流程。XNA和一般消息驱动的应用程序不同,表面上并没有消息循环,取而代之的是有2个函数的无限循环Update和Draw。
前者负责处理所有逻辑,检查输入,并更新所以应该更新的东西。后者负责整个区域的绘制。这一个循环就完成了一帧,每一秒完成循环的次数就是游戏的FPS。XNA中FPS是一般固定的(Windows下是60帧,WindowsPhone是30帧),也可以根据需要修改,或者取消FPS限制。
如果在固定的FPS下当2个函数都执行完了却还有空余时间,程序便会等待直到此次循环时间结束。
下面就来介绍粒子特效。也许大家对粒子特效没什么感觉,但他确实游戏特效中很重要的一个环节。例如爆炸,下雨,烟雾,子弹(弹幕)等待都是粒子特效。下面是本例中的雪花效果。
截图不怎么样,实际效果会很好看。本例本来是微软的粒子特效演示,我把其中所有的注释都翻译了过来,方便大家理解,并增加了一些我的理解。如果能仔细阅读这个程序,我相信你就能完整的掌握粒子特效的相关知识。粒子效果由以下2个部分构成:粒子和粒子系统。
一、粒子粒子是粒子系统最基本的单元。你可以想象一下一个物体,这个物体中,他的组成成分都是相似的,这 个相似的部分就是粒子,就像一场雪是由很多很多的雪花所组成的一样。由此我们可以想象一个(自然界)粒子应该具有的性质。位置 Vector2 Position大小(规模) float scale
速度 Vector2 Velocity
加速度 Vector2 Acceleration
自转速度 float rotation;
这些都是自然界中粒子所拥有的属性,在程序中我们还需要以下属性
生存周期 float lifetime粒子被创建以后所经历的时间 float timeSinceStart
由此我们就可以得到粒子类的构造函数public void Initialize(Vector2 position, Vector2 velocity, Vector2 acceleration,float lifetime, float scale, float rotationSpeed)
{
//设置所有的值
this.Position = position;
this.Velocity = velocity;
this.Acceleration = acceleration;
this.Lifetime = lifetime;
this.Scale = scale;
this.RotationSpeed = rotationSpeed;
//重置TimeSinceStart,因为当我们要重复利用粒子.
this.TimeSinceStart = 0.0f;
//设置一个旋转的角度(0-2π)
this.Rotation = ParticleHelpers.RandomBetween(0, MathHelper.TwoPi);
}
除了构造函数外,我们还需要另外2个函数来帮助我们使用粒子类判断是否粒子的活动函数 public bool Active()更新粒子状态函数 void Update(float)
以上就是粒子类的构成,详细解释请看代码中的注释。
二、粒子系统上面我们定义了粒子类,他代表了我们系统中的每一个粒子。为了把管理他们,我们就需要一个粒子系统。因为粒子系统有点复杂,代码也非常长,所以就不贴出来了,大家可以参看源代码中的ParticleSystem.cs文件了解。这里我就只介绍粒子系统的原理。首先要明确一点,我们的粒子是重复利用的,不然会造成很大的资源浪费。为了满足这个要求,除了所有粒子的集合外(我们用List *本站禁止HTML标签噢* 来储存),我们还需要一个 队列(Queue *本站禁止HTML标签噢* )来保存可以使用的自由粒子(处于非活动状态)。在新建粒子的函数(AddParticles)中,根据需要新建粒子的数量,先从自由粒子队列中取出粒子,如果不够用再新建粒子对象。这样能节省很多资源。当我们发现一个粒子的生命周期结束(或者其他自定义的条件),我们就把他放入自由粒子队列中以便我们继续利用它。为了方便修改特效,我们利用XML串行化(序列化)处理过得配置文件来保存特效相关的变量的信息,并利用ParticleSystemSettings类来读取其中的数据。这些数据一般是提供一个变化的范围,以便能让粒子系统生成满足要求但却不完全一样的粒子,这样美观度就会大大提高。当需要修改特效时,大多数不要修改源代码,而是直接修改配置文件就能得出新的特效,这对于引擎的易用性来说也很重要。粒子系统是整个粒子系统的核心部分,大部分的算法都在这里完成,如果想理解粒子效果实现的方法,还是请仔细看源代码,我已经做了很详细的注释,如果还有不懂的地方请在帖子里面说明,我会尽量帮你解答。
三、关于粒子特效的设置: 这里主要介绍通过修改配置文件来完成各种特效。首先介绍配置文件的组成:
public class ParticleSystemSettings{
// 设置粒子数目的范围
// 注意:这里是每一次产生效果的时候所产生粒子的数目
// 并不是粒子的总数目!!!
public int MinNumParticles;
public int MaxNumParticles;
// 粒子所用纹理效果的文件名(不要写后缀名)
public string TextureFilename = null;
// 这2个参数将会控制粒子运动的偏移角度.在XML文件中是用角度表示的,在实际运算中我们会转换成弧度
public float MinDirectionAngle = 0;
public float MaxDirectionAngle = 360;
// 这2个参数将会控制粒子创建时的速度大小
public float MinInitialSpeed;
public float MaxInitialSpeed;
// 设置加速度模式
public AccelerationMode AccelerationMode = AccelerationMode.None;
//当用EndVelocity模式的时候,将会利用下面的参数,即末速度.
//改变这个大小将会影响粒子的生存周期.
//如果设置为1,粒子将会一直保持原速度
//如果设置为0,粒子将会在消失前停止.
public float EndVelocity = 1f;
//当使用Scale模式时,将会用下面2个参数决定其加速度的大小
public float MinAccelerationScale = 0;
public float MaxAccelerationScale = 0;
// 当用Vector模式的时候,下面2个变量将会决定加速度的矢量值
public Vector2 MinAccelerationVector = Vector2.Zero;
public Vector2 MaxAccelerationVector = Vector2.Zero;
//这个参数控制有多少粒子(百分比)在创建出来的时候就会赋予初速度
public float EmitterVelocitySensitivity = 0;
// 这2个参数决定粒子的自转(自旋)速度,同样在XML文件里面是角度,计算的时候会转换成弧度
public float MinRotationSpeed = 0;
public float MaxRotationSpeed = 0;
// 这2个参数决定粒子的生存周期
public float MinLifetime;
public float MaxLifetime;
// 这2个参数决定粒子的大小
public float MinSize = 1;
public float MaxSize = 1;
// 控制重力对粒子的影响,这是一个矢量,我们除了在上面的加速度使用矢量外,也可以
// 在这里利用重力描述出一个风的效果,例如雪花往左边飘
public Vector2 Gravity = Vector2.Zero;
// 这个参数决定粒子的Alpha值(透明度).我们所给定的默认值适合大多数粒子效果
public Blend SourceBlend = Blend.One;
public Blend DestinationBlend = Blend.InverseSourceAlpha;
}
下面是关于上面提到的加速度模式的解释None: 粒子系统将不会使用加速度,即粒子将匀速运动Scalar: 标量加速度:系统会把速度(矢量)乘以一个介于最小标量加速度(MinAccelerationScale和最大标量加速度(MaxAccelerationScale)中随机产生的一个值然后再乘以一个随机的方向(由MinDirectionAngle和MaxDirectionAngle中随机).EndVelocity:标准物理学加速度:按公式Vt=V0+at计算速度 不会改变方向Vector:矢量加速度:系统会把速度乘以一个矢量。这个矢量由 MinAccelerationVector.X和MaxAccelerationVector.X 中间产生的随机数 做X坐标。MinAccelerationVector.Y和MaxAccelerationVector.Y 中间产生的随机数 做Y坐标。这个设置会改变方向自此我们的粒子特效系统就完成了。下面就行修改特效的代码了,我在代码中提供了3种特效,分别是:下雪,烟雾,爆炸。大家可以试试看,并研究每一个特效的参数。这是雪花的参数:<?xml version="1.0" encoding="utf-8"?>*本站禁止HTML标签噢*
<Asset Type="ParticlesSettings.ParticleSystemSettings">
*本站禁止HTML标签噢* 5</MinNumParticles>
*本站禁止HTML标签噢* 8</MaxNumParticles>
*本站禁止HTML标签噢* 11</TextureFilename>
*本站禁止HTML标签噢* -90</MinDirectionAngle>
*本站禁止HTML标签噢* 90</MaxDirectionAngle>
*本站禁止HTML标签噢* 10</MinInitialSpeed>
*本站禁止HTML标签噢* 50</MaxInitialSpeed>
*本站禁止HTML标签噢* None</AccelerationMode>
*本站禁止HTML标签噢* -45</MinRotationSpeed>
*本站禁止HTML标签噢* 45</MaxRotationSpeed>
*本站禁止HTML标签噢* 5</MinLifetime>
*本站禁止HTML标签噢* 10</MaxLifetime>
*本站禁止HTML标签噢* 0.1</MinSize>
*本站禁止HTML标签噢* .3</MaxSize>
*本站禁止HTML标签噢* 10 40</Gravity>
</Asset>
</XnaContent>
效果如下:
这次写的帖子可能没有太多的图片和例子,主要因为这是介绍一个特效的框架,他的特效参数并没有什么值得研究的。 但是一个帖子中很难把粒子系统的原理解释得很清楚,但是我提供了一个程序给大家参考,也写了很详细的注释,通过阅读整个程序我想你就能完全把握住粒子系统的原理和实现方法,如果有什么问题可以在下面回帖。系统学习的书籍在这:http://115.com/file/anmamcg7另外打下广告:Ruma游戏引擎招收各种NB人物。
Ruma引擎是基于XNA的游戏引擎,现在正在制作Windows版以后主要制作WindowsPhone版。
现在急需程序员(最好有.Net基础),当然有兴趣的话也可以加入我们!
QQ群:2715634


