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

  1. SpriteBatch.Draw( Texture2D texture,
  2. Vector2 vector,
  3. 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个部分构成:粒子和粒子系统。

 



一、粒子

粒子是粒子系统最基本的单元。你可以想象一下一个物体,这个物体中,他的组成成分都是相似的,这 个相似的部分就是粒子,就像一场雪是由很多很多的雪花所组成的一样。
由此我们可以想象一个(自然界)粒子应该具有的性质。



  1. 位置 Vector2 Position
  2. 大小(规模) float scale
  3. 速度 Vector2 Velocity
  4. 加速度 Vector2 Acceleration
  5. 自转速度 float rotation;

 


这些都是自然界中粒子所拥有的属性,在程序中我们还需要以下属性

  1. 生存周期 float lifetime
  2. 粒子被创建以后所经历的时间 float timeSinceStart

 





由此我们就可以得到粒子类的构造函数
 

 

  1. public void Initialize(Vector2 position, Vector2 velocity, Vector2 acceleration,
  2. float lifetime, float scale, float rotationSpeed)
  3. {
  4. //设置所有的值
  5. this.Position = position;
  6. this.Velocity = velocity;
  7. this.Acceleration = acceleration;
  8. this.Lifetime = lifetime;
  9. this.Scale = scale;
  10. this.RotationSpeed = rotationSpeed;
  11. //重置TimeSinceStart,因为当我们要重复利用粒子.
  12. this.TimeSinceStart = 0.0f;
  13. //设置一个旋转的角度(0-2π)
  14. this.Rotation = ParticleHelpers.RandomBetween(0, MathHelper.TwoPi);
  15. }




除了构造函数外,我们还需要另外2个函数来帮助我们使用粒子类

 

  1. 判断是否粒子的活动函数 public bool Active()
  2. 更新粒子状态函数 void Update(float)



以上就是粒子类的构成,详细解释请看代码中的注释。

 



二、粒子系统

上面我们定义了粒子类,他代表了我们系统中的每一个粒子。为了把管理他们,我们就需要一个粒子系统。
因为粒子系统有点复杂,代码也非常长,所以就不贴出来了,大家可以参看源代码中的ParticleSystem.cs文件了解。
这里我就只介绍粒子系统的原理。
首先要明确一点,我们的粒子是重复利用的,不然会造成很大的资源浪费。
为了满足这个要求,除了所有粒子的集合外(我们用List<Particle>来储存),我们还需要一个队列(Queue<Particle>)来保存可以使用的自由粒子(处于非活动状态)。
在新建粒子的函数(AddParticles)中,根据需要新建粒子的数量,先从自由粒子队列中取出粒子,如果不够用再新建粒子对象。这样能节省很多资源。
当我们发现一个粒子的生命周期结束(或者其他自定义的条件),我们就把他放入自由粒子队列中以便我们继续利用它。
为了方便修改特效,我们利用XML串行化(序列化)处理过得配置文件来保存特效相关的变量的信息,并利用ParticleSystemSettings类来读取其中的数据。
这些数据一般是提供一个变化的范围,以便能让粒子系统生成满足要求但却不完全一样的粒子,这样美观度就会大大提高。
当需要修改特效时,大多数不要修改源代码,而是直接修改配置文件就能得出新的特效,这对于引擎的易用性来说也很重要。
粒子系统是整个粒子系统的核心部分,大部分的算法都在这里完成,如果想理解粒子效果实现的方法,还是请仔细看源代码,我已经做了很详细的注释,如果还有不懂的地方请在帖子里面说明,我会尽量帮你解答。

 



三、关于粒子特效的设置: 这里主要介绍通过修改配置文件来完成各种特效。
首先介绍配置文件的组成:

  1. public class ParticleSystemSettings
  2. {
  3. // 设置粒子数目的范围
  4. // 注意:这里是每一次产生效果的时候所产生粒子的数目
  5. // 并不是粒子的总数目!!!
  6. public int MinNumParticles;
  7. public int MaxNumParticles;
  8. // 粒子所用纹理效果的文件名(不要写后缀名)
  9. public string TextureFilename = null;
  10. // 这2个参数将会控制粒子运动的偏移角度.在XML文件中是用角度表示的,在实际运算中我们会转换成弧度
  11. public float MinDirectionAngle = 0;
  12. public float MaxDirectionAngle = 360;
  13. // 这2个参数将会控制粒子创建时的速度大小
  14. public float MinInitialSpeed;
  15. public float MaxInitialSpeed;
  16. // 设置加速度模式
  17. public AccelerationMode AccelerationMode = AccelerationMode.None;
  18. //当用EndVelocity模式的时候,将会利用下面的参数,即末速度.
  19. //改变这个大小将会影响粒子的生存周期.
  20. //如果设置为1,粒子将会一直保持原速度
  21. //如果设置为0,粒子将会在消失前停止.
  22. public float EndVelocity = 1f;
  23. //当使用Scale模式时,将会用下面2个参数决定其加速度的大小
  24. public float MinAccelerationScale = 0;
  25. public float MaxAccelerationScale = 0;
  26. // 当用Vector模式的时候,下面2个变量将会决定加速度的矢量值
  27. public Vector2 MinAccelerationVector = Vector2.Zero;
  28. public Vector2 MaxAccelerationVector = Vector2.Zero;
  29. //这个参数控制有多少粒子(百分比)在创建出来的时候就会赋予初速度
  30. public float EmitterVelocitySensitivity = 0;
  31. // 这2个参数决定粒子的自转(自旋)速度,同样在XML文件里面是角度,计算的时候会转换成弧度
  32. public float MinRotationSpeed = 0;
  33. public float MaxRotationSpeed = 0;
  34. // 这2个参数决定粒子的生存周期
  35. public float MinLifetime;
  36. public float MaxLifetime;
  37. // 这2个参数决定粒子的大小
  38. public float MinSize = 1;
  39. public float MaxSize = 1;
  40. // 控制重力对粒子的影响,这是一个矢量,我们除了在上面的加速度使用矢量外,也可以
  41. // 在这里利用重力描述出一个风的效果,例如雪花往左边飘
  42. public Vector2 Gravity = Vector2.Zero;
  43. // 这个参数决定粒子的Alpha值(透明度).我们所给定的默认值适合大多数粒子效果
  44. public Blend SourceBlend = Blend.One;
  45. public Blend DestinationBlend = Blend.InverseSourceAlpha;
  46. }

 

下面是关于上面提到的加速度模式的解释
None: 粒子系统将不会使用加速度,即粒子将匀速运动
 
Scalar: 标量加速度:系统会把速度(矢量)乘以一个介于最小标量加速度(MinAccelerationScale和最大标量加速度(MaxAccelerationScale)中随机产生的一个值然后再乘以一个随机的方向(由MinDirectionAngle和MaxDirectionAngle中随机).
 
EndVelocity:标准物理学加速度:按公式Vt=V0+at计算速度 不会改变方向
 
Vector:矢量加速度:系统会把速度乘以一个矢量。这个矢量由 MinAccelerationVector.X和MaxAccelerationVector.X 中间产生的随机数 做X坐标。MinAccelerationVector.Y和MaxAccelerationVector.Y 中间产生的随机数 做Y坐标。这个设置会改变方向

 



 

自此我们的粒子特效系统就完成了。下面就行修改特效的代码了,我在代码中提供了3种特效,分别是:下雪,烟雾,爆炸。大家可以试试看,并研究每一个特效的参数。
 
这是雪花的参数:

 

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <XnaContent>
  3. <Asset Type="ParticlesSettings.ParticleSystemSettings">
  4. <MinNumParticles>5</MinNumParticles>
  5. <MaxNumParticles>8</MaxNumParticles>
  6. <TextureFilename>11</TextureFilename>
  7. <MinDirectionAngle>-90</MinDirectionAngle>
  8. <MaxDirectionAngle>90</MaxDirectionAngle>
  9. <MinInitialSpeed>10</MinInitialSpeed>
  10. <MaxInitialSpeed>50</MaxInitialSpeed>
  11. <AccelerationMode>None</AccelerationMode>
  12. <MinRotationSpeed>-45</MinRotationSpeed>
  13. <MaxRotationSpeed>45</MaxRotationSpeed>
  14. <MinLifetime>5</MinLifetime>
  15. <MaxLifetime>10</MaxLifetime>
  16. <MinSize>0.1</MinSize>
  17. <MaxSize>.3</MaxSize>
  18. <Gravity>10 40</Gravity>
  19. </Asset>
  20. </XnaContent>
复制代码
效果如下:
 

posted @ 2012-07-19 19:46  Mzhangyl  阅读(1000)  评论(0编辑  收藏  举报