2
0

ParticleEmitter.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // ParticleEmitter.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using Microsoft.Xna.Framework;
  12. #endregion
  13. namespace Particle3DSample
  14. {
  15. /// <summary>
  16. /// Helper for objects that want to leave particles behind them as they
  17. /// move around the world. This emitter implementation solves two related
  18. /// problems:
  19. ///
  20. /// If an object wants to create particles very slowly, less than once per
  21. /// frame, it can be a pain to keep track of which updates ought to create
  22. /// a new particle versus which should not.
  23. ///
  24. /// If an object is moving quickly and is creating many particles per frame,
  25. /// it will look ugly if these particles are all bunched up together. Much
  26. /// better if they can be spread out along a line between where the object
  27. /// is now and where it was on the previous frame. This is particularly
  28. /// important for leaving trails behind fast moving objects such as rockets.
  29. ///
  30. /// This emitter class keeps track of a moving object, remembering its
  31. /// previous position so it can calculate the velocity of the object. It
  32. /// works out the perfect locations for creating particles at any frequency
  33. /// you specify, regardless of whether this is faster or slower than the
  34. /// game update rate.
  35. /// </summary>
  36. public class ParticleEmitter
  37. {
  38. #region Fields
  39. ParticleSystem particleSystem;
  40. float timeBetweenParticles;
  41. Vector3 previousPosition;
  42. float timeLeftOver;
  43. #endregion
  44. /// <summary>
  45. /// Constructs a new particle emitter object.
  46. /// </summary>
  47. public ParticleEmitter (ParticleSystem particleSystem,
  48. float particlesPerSecond,Vector3 initialPosition)
  49. {
  50. this.particleSystem = particleSystem;
  51. timeBetweenParticles = 1.0f / particlesPerSecond;
  52. previousPosition = initialPosition;
  53. }
  54. /// <summary>
  55. /// Updates the emitter, creating the appropriate number of particles
  56. /// in the appropriate positions.
  57. /// </summary>
  58. public void Update (GameTime gameTime, Vector3 newPosition)
  59. {
  60. if (gameTime == null)
  61. throw new ArgumentNullException ("gameTime");
  62. // Work out how much time has passed since the previous update.
  63. float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
  64. if (elapsedTime > 0) {
  65. // Work out how fast we are moving.
  66. Vector3 velocity = (newPosition - previousPosition) / elapsedTime;
  67. // If we had any time left over that we didn't use during the
  68. // previous update, add that to the current elapsed time.
  69. float timeToSpend = timeLeftOver + elapsedTime;
  70. // Counter for looping over the time interval.
  71. float currentTime = -timeLeftOver;
  72. // Create particles as long as we have a big enough time interval.
  73. while (timeToSpend > timeBetweenParticles) {
  74. currentTime += timeBetweenParticles;
  75. timeToSpend -= timeBetweenParticles;
  76. // Work out the optimal position for this particle. This will produce
  77. // evenly spaced particles regardless of the object speed, particle
  78. // creation frequency, or game update rate.
  79. float mu = currentTime / elapsedTime;
  80. Vector3 position = Vector3.Lerp (previousPosition, newPosition, mu);
  81. // Create the particle.
  82. particleSystem.AddParticle (position, velocity);
  83. }
  84. // Store any time we didn't use, so it can be part of the next update.
  85. timeLeftOver = timeToSpend;
  86. }
  87. previousPosition = newPosition;
  88. }
  89. }
  90. }