ParticleManager.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. //---------------------------------------------------------------------------------
  2. // Written by Michael Hoffman
  3. // Find the full tutorial at: http://gamedev.tutsplus.com/series/vector-shooter-xna/
  4. //----------------------------------------------------------------------------------
  5. using System;
  6. using AtomicEngine;
  7. namespace AtomicBlaster
  8. {
  9. public class ParticleManager<T>
  10. {
  11. // This delegate will be called for each particle.
  12. private Action<Particle> updateParticle;
  13. private CircularParticleArray particleList;
  14. /// <summary>
  15. /// Allows creation of particles.
  16. /// </summary>
  17. /// <param name="capacity">The maximum number of particles. An array of this size will be pre-allocated.</param>
  18. /// <param name="updateParticle">A delegate that lets you specify custom behaviour for your particles. Called once per particle, per frame.</param>
  19. public ParticleManager(int capacity, Action<Particle> updateParticle)
  20. {
  21. this.updateParticle = updateParticle;
  22. particleList = new CircularParticleArray(capacity);
  23. // Populate the list with empty particle objects, for reuse.
  24. for (int i = 0; i < capacity; i++)
  25. particleList[i] = new Particle();
  26. }
  27. /// <summary>
  28. /// Update particle state, to be called every frame.
  29. /// </summary>
  30. public void Update()
  31. {
  32. int removalCount = 0;
  33. for (int i = 0; i < particleList.Count; i++)
  34. {
  35. var particle = particleList[i];
  36. updateParticle(particle);
  37. particle.PercentLife -= 1f / particle.Duration;
  38. // sift deleted particles to the end of the list
  39. Swap(particleList, i - removalCount, i);
  40. // if the alpha < 0, delete this particle
  41. if (particle.PercentLife < 0)
  42. removalCount++;
  43. }
  44. particleList.Count -= removalCount;
  45. }
  46. private static void Swap(CircularParticleArray list, int index1, int index2)
  47. {
  48. var temp = list[index1];
  49. list[index1] = list[index2];
  50. list[index2] = temp;
  51. }
  52. /// <summary>
  53. /// Draw the particles.
  54. /// </summary>
  55. public void Draw(/*SpriteBatch spriteBatch*/)
  56. {
  57. for (int i = 0; i < particleList.Count; i++)
  58. {
  59. var particle = particleList[i];
  60. Vector2 origin = new Vector2(particle.Texture.Width / 2, particle.Texture.Height / 2);
  61. //spriteBatch.Draw(particle.Texture, particle.Position, null, particle.Tint, particle.Orientation, origin, particle.Scale, 0, 0);
  62. }
  63. }
  64. public void CreateParticle(Texture2D texture, Vector2 position, Color tint, float duration, float scale, T state, float theta = 0)
  65. {
  66. CreateParticle(texture, position, tint, duration, new Vector2(scale, scale), state, theta);
  67. }
  68. public void CreateParticle(Texture2D texture, Vector2 position, Color tint, float duration, Vector2 scale, T state, float theta = 0)
  69. {
  70. Particle particle;
  71. if (particleList.Count == particleList.Capacity)
  72. {
  73. // if the list is full, overwrite the oldest particle, and rotate the circular list
  74. particle = particleList[0];
  75. particleList.Start++;
  76. }
  77. else
  78. {
  79. particle = particleList[particleList.Count];
  80. particleList.Count++;
  81. }
  82. // Create the particle
  83. particle.Texture = texture;
  84. particle.Position = position;
  85. particle.Tint = tint;
  86. particle.Duration = duration;
  87. particle.PercentLife = 1f;
  88. particle.Scale = scale;
  89. particle.Orientation = theta;
  90. particle.State = state;
  91. }
  92. /// <summary>
  93. /// Destroys all particles
  94. /// </summary>
  95. public void Clear()
  96. {
  97. particleList.Count = 0;
  98. }
  99. public int ParticleCount
  100. {
  101. get { return particleList.Count; }
  102. }
  103. public class Particle
  104. {
  105. public Texture2D Texture;
  106. public Vector2 Position;
  107. public float Orientation;
  108. public Vector2 Scale = Vector2.One;
  109. public Color Tint;
  110. public float Duration;
  111. public float PercentLife = 1f;
  112. public T State;
  113. }
  114. // Represents a circular array with an arbitrary starting point. It's useful for efficiently overwriting
  115. // the oldest particles when the array gets full. Simply overwrite particleList[0] and advance Start.
  116. private class CircularParticleArray
  117. {
  118. private int start;
  119. public int Start
  120. {
  121. get { return start; }
  122. set { start = value % list.Length; }
  123. }
  124. public int Count { get; set; }
  125. public int Capacity { get { return list.Length; } }
  126. private Particle[] list;
  127. public CircularParticleArray() { } // for serialization
  128. public CircularParticleArray(int capacity)
  129. {
  130. list = new Particle[capacity];
  131. }
  132. public Particle this[int i]
  133. {
  134. get { return list[(start + i) % list.Length]; }
  135. set { list[(start + i) % list.Length] = value; }
  136. }
  137. }
  138. }
  139. }