ParticleEmitter.cs 3.5 KB

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