ParticleSystem.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. //-----------------------------------------------------------------------------
  2. // ParticleSystem.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections.Generic;
  9. using Microsoft.Xna.Framework;
  10. using Microsoft.Xna.Framework.Content;
  11. using Microsoft.Xna.Framework.Graphics;
  12. namespace AlienGameSample
  13. {
  14. /// <summary>
  15. /// A relatively simple particle system. We recycle particles instead of creating
  16. /// and destroying them as we need more. "Effects" are created via factory methods
  17. /// on ParticleSystem, rather than a data driven model due to the relatively low
  18. /// number of effects.
  19. /// </summary>
  20. public class ParticleSystem
  21. {
  22. Random random;
  23. Texture2D tank_tire;
  24. Texture2D tank_top;
  25. Texture2D fire;
  26. Texture2D smoke;
  27. SpriteBatch spriteBatch;
  28. List<Particle> particles;
  29. public ParticleSystem(ContentManager content, SpriteBatch spriteBatch)
  30. {
  31. random = new Random();
  32. particles = new List<Particle>();
  33. this.spriteBatch = spriteBatch;
  34. tank_tire = content.Load<Texture2D>("tank_tire");
  35. tank_top = content.Load<Texture2D>("tank_top");
  36. fire = content.Load<Texture2D>("fire");
  37. smoke = content.Load<Texture2D>("smoke");
  38. }
  39. /// <summary>
  40. /// Update all active particles.
  41. /// </summary>
  42. /// <param name="elapsed">The amount of time elapsed since last Update.</param>
  43. public void Update(float elapsed)
  44. {
  45. for (int i = 0; i < particles.Count; ++i)
  46. {
  47. particles[i].Life -= elapsed;
  48. if (particles[i].Life <= 0.0f)
  49. {
  50. continue;
  51. }
  52. particles[i].Position += particles[i].Velocity * elapsed;
  53. particles[i].Rotation += particles[i].RotationRate * elapsed;
  54. particles[i].Alpha += particles[i].AlphaRate * elapsed;
  55. particles[i].Scale += particles[i].ScaleRate * elapsed;
  56. if (particles[i].Alpha <= 0.0f)
  57. particles[i].Alpha = 0.0f;
  58. }
  59. }
  60. /// <summary>
  61. /// Draws the particles.
  62. /// </summary>
  63. public void Draw()
  64. {
  65. for (int i = 0; i < particles.Count; ++i)
  66. {
  67. Particle p = particles[i];
  68. if (p.Life <= 0.0f)
  69. continue;
  70. float alphaF = 255.0f * p.Alpha;
  71. if (alphaF < 0.0f)
  72. alphaF = 0.0f;
  73. if (alphaF > 255.0f)
  74. alphaF = 255.0f;
  75. spriteBatch.Draw(p.Texture, p.Position, null, new Color(p.Color.R, p.Color.G, p.Color.B, (byte)alphaF), p.Rotation, new Vector2(p.Texture.Width / 2, p.Texture.Height / 2), p.Scale, SpriteEffects.None, 0.0f);
  76. }
  77. }
  78. /// <summary>
  79. /// Creats a particle, preferring to reuse a dead one in the particles list
  80. /// before creating a new one.
  81. /// </summary>
  82. /// <returns></returns>
  83. Particle CreateParticle()
  84. {
  85. Particle p = null;
  86. for (int i = 0; i < particles.Count; ++i)
  87. {
  88. if (particles[i].Life <= 0.0f)
  89. {
  90. p = particles[i];
  91. break;
  92. }
  93. }
  94. if (p == null)
  95. {
  96. p = new Particle();
  97. particles.Add(p);
  98. }
  99. p.Color = Color.White;
  100. return p;
  101. }
  102. /// <summary>
  103. /// Creats the effect for when an alien dies.
  104. /// </summary>
  105. /// <param name="position">Where on the screen to create the effect.</param>
  106. public void CreateAlienExplosion(Vector2 position)
  107. {
  108. Particle p = null;
  109. for (int i = 0; i < 8; ++i)
  110. {
  111. p = CreateParticle();
  112. p.Position = position;
  113. p.RotationRate = -6.0f + 12.0f * (float)random.NextDouble();
  114. p.Scale = 0.5f;
  115. p.ScaleRate = 0.25f;// *(float)random.NextDouble();
  116. p.Alpha = 2.0f;
  117. p.AlphaRate = -1.0f;
  118. p.Velocity.X = -32.0f + 64.0f * (float)random.NextDouble();
  119. p.Velocity.Y = -32.0f + 64.0f * (float)random.NextDouble();
  120. p.Texture = smoke;
  121. p.Life = 2.0f;
  122. }
  123. for (int i = 0; i < 3; ++i)
  124. {
  125. p = CreateParticle();
  126. p.Position = position;
  127. p.Position.X += -8.0f + 16.0f * (float)random.NextDouble();
  128. p.Position.Y += -8.0f + 16.0f * (float)random.NextDouble();
  129. p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
  130. p.Scale = 0.25f;
  131. p.ScaleRate = 1.0f;// *(float)random.NextDouble();
  132. p.Alpha = 2.0f;
  133. p.AlphaRate = -1.0f;
  134. p.Velocity = Vector2.Zero;
  135. p.Texture = fire;
  136. p.Life = 2.0f;
  137. }
  138. }
  139. /// <summary>
  140. /// Creats the effect for when the player dies.
  141. /// </summary>
  142. /// <param name="position">Where on the screen to create the effect.</param>
  143. public void CreatePlayerExplosion(Vector2 position)
  144. {
  145. Particle p = null;
  146. for (int i = 0; i < 16; ++i)
  147. {
  148. p = CreateParticle();
  149. p.Position = position;
  150. p.RotationRate = -6.0f + 12.0f * (float)random.NextDouble();
  151. p.Scale = 0.5f;
  152. p.ScaleRate = 0.25f;// *(float)random.NextDouble();
  153. p.Alpha = 2.0f;
  154. p.AlphaRate = -1.0f;
  155. p.Velocity.X = -32.0f + 64.0f * (float)random.NextDouble();
  156. p.Velocity.Y = -32.0f + -48.0f * (float)random.NextDouble();
  157. p.Texture = smoke;
  158. p.Life = 2.0f;
  159. }
  160. p = CreateParticle();
  161. p.Texture = tank_tire;
  162. p.Position = position;
  163. p.Scale = 1.0f;
  164. p.ScaleRate = 0.0f;
  165. p.Alpha = 2.0f;
  166. p.AlphaRate = -1.0f;
  167. p.Life = 2.0f;
  168. p.RotationRate = 0.5f;
  169. p.Rotation = 0.0f;
  170. p.Velocity = new Vector2(40.0f, -75.0f);
  171. p = CreateParticle();
  172. p.Texture = tank_tire;
  173. p.Position = position;
  174. p.Scale = 1.0f;
  175. p.ScaleRate = 0.0f;
  176. p.Alpha = 2.0f;
  177. p.AlphaRate = -1.0f;
  178. p.Life = 2.0f;
  179. p.RotationRate = 0.5f;
  180. p.Rotation = 0.0f;
  181. p.Velocity = new Vector2(-45.0f, -90.0f);
  182. p = CreateParticle();
  183. p.Texture = tank_top;
  184. p.Position = position;
  185. p.Scale = 1.0f;
  186. p.ScaleRate = 0.0f;
  187. p.Alpha = 2.0f;
  188. p.AlphaRate = -1.0f;
  189. p.Life = 2.0f;
  190. p.RotationRate = 2.5f;
  191. p.Rotation = 0.0f;
  192. p.Velocity = new Vector2(0.0f, -60.0f);
  193. for (int i = 0; i < 8; ++i)
  194. {
  195. p = CreateParticle();
  196. p.Position = position;
  197. p.Position.X += -16.0f + 32.0f * (float)random.NextDouble();
  198. p.Position.Y += -16.0f + 32.0f * (float)random.NextDouble();
  199. p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
  200. p.Scale = 0.25f;
  201. p.ScaleRate = 1.0f;// *(float)random.NextDouble();
  202. p.Alpha = 2.0f;
  203. p.AlphaRate = -1.0f;
  204. p.Velocity.X = -4.0f + 8.0f * (float)random.NextDouble();
  205. p.Velocity.Y = -4.0f + -8.0f * (float)random.NextDouble();
  206. p.Texture = fire;
  207. p.Life = 2.0f;
  208. }
  209. }
  210. /// <summary>
  211. /// Creats the mud/dust effect when the player moves.
  212. /// </summary>
  213. /// <param name="position">Where on the screen to create the effect.</param>
  214. public void CreatePlayerDust(Player player)
  215. {
  216. for (int i = 0; i < 2; ++i)
  217. {
  218. Particle p = CreateParticle();
  219. p.Texture = smoke;
  220. p.Color = new Color(125, 108, 43);
  221. p.Position.X = player.Position.X + player.Width * (float)random.NextDouble();
  222. p.Position.Y = player.Position.Y + player.Height - 3.0f * (float)random.NextDouble();
  223. p.Alpha = 1.0f;
  224. p.AlphaRate = -2.0f;
  225. p.Life = 0.5f;
  226. p.Rotation = 0.0f;
  227. p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
  228. p.Scale = 0.25f;
  229. p.ScaleRate = 0.5f;
  230. p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();
  231. p.Velocity.Y = -8 + 4.0f * (float)random.NextDouble();
  232. }
  233. }
  234. /// <summary>
  235. /// Creats the effect for when the player fires a bullet.
  236. /// </summary>
  237. /// <param name="position">Where on the screen to create the effect.</param>
  238. public void CreatePlayerFireSmoke(Player player)
  239. {
  240. for (int i = 0; i < 8; ++i)
  241. {
  242. Particle p = CreateParticle();
  243. p.Texture = smoke;
  244. p.Color = Color.White;
  245. p.Position.X = player.Position.X + player.Width / 2;
  246. p.Position.Y = player.Position.Y;
  247. p.Alpha = 1.0f;
  248. p.AlphaRate = -1.0f;
  249. p.Life = 1.0f;
  250. p.Rotation = 0.0f;
  251. p.RotationRate = -2.0f + 4.0f * (float)random.NextDouble();
  252. p.Scale = 0.25f;
  253. p.ScaleRate = 0.25f;
  254. p.Velocity.X = -4 + 8.0f * (float)random.NextDouble();
  255. p.Velocity.Y = -16.0f + -32.0f * (float)random.NextDouble();
  256. }
  257. }
  258. }
  259. /// <summary>
  260. /// A basic particle. Since this is strictly a data class, I decided to not go
  261. /// the full property route and used public fields instead.
  262. /// </summary>
  263. public class Particle
  264. {
  265. public Vector2 Position;
  266. public Vector2 Velocity;
  267. public Texture2D Texture;
  268. public float RotationRate;
  269. public float Rotation;
  270. public float Life;
  271. public float AlphaRate;
  272. public float Alpha;
  273. public float ScaleRate;
  274. public float Scale;
  275. public Color Color = Color.White;
  276. }
  277. }