ParticleState.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //---------------------------------------------------------------------------------
  2. // Ported to the Atomic Game Engine
  3. // Originally written for XNA by Michael Hoffman
  4. // Find the full tutorial at: http://gamedev.tutsplus.com/series/vector-shooter-xna/
  5. //----------------------------------------------------------------------------------
  6. using System;
  7. using AtomicEngine;
  8. namespace AtomicBlaster
  9. {
  10. public enum ParticleType { None, Enemy, Bullet, IgnoreGravity }
  11. public struct ParticleState
  12. {
  13. public Vector2 Velocity;
  14. public ParticleType Type;
  15. public float LengthMultiplier;
  16. private static Random rand = new Random();
  17. public ParticleState(Vector2 velocity, ParticleType type, float lengthMultiplier = 1f)
  18. {
  19. Velocity = velocity;
  20. Type = type;
  21. LengthMultiplier = lengthMultiplier;
  22. }
  23. public static ParticleState GetRandom(float minVel, float maxVel)
  24. {
  25. var state = new ParticleState();
  26. state.Velocity = rand.NextVector2(minVel, maxVel);
  27. state.Type = ParticleType.None;
  28. state.LengthMultiplier = 1;
  29. return state;
  30. }
  31. public static void UpdateParticle(ParticleManager<ParticleState>.Particle particle)
  32. {
  33. var vel = particle.State.Velocity;
  34. float speed = vel.Length;
  35. // using Vector2.Add() should be slightly faster than doing "x.Position += vel;" because the Vector2s
  36. // are passed by reference and don't need to be copied. Since we may have to update a very large
  37. // number of particles, this method is a good candidate for optimizations.
  38. Vector2.Add(ref particle.Position, ref vel, out particle.Position);
  39. // fade the particle if its PercentLife or speed is low.
  40. float alpha = Math.Min(1, Math.Min(particle.PercentLife * 2, speed * 1f));
  41. alpha *= alpha;
  42. particle.Tint.A = alpha;
  43. // the length of bullet particles will be less dependent on their speed than other particles
  44. if (particle.State.Type == ParticleType.Bullet)
  45. particle.Scale.X = particle.State.LengthMultiplier * Math.Min(Math.Min(1f, 0.1f * speed + 0.1f), alpha);
  46. else
  47. particle.Scale.X = particle.State.LengthMultiplier * Math.Min(Math.Min(1f, 0.2f * speed + 0.1f), alpha);
  48. particle.Orientation = vel.ToAngle();
  49. var pos = particle.Position;
  50. int width = (int)GameRoot.ScreenSize.X;
  51. int height = (int)GameRoot.ScreenSize.Y;
  52. // collide with the edges of the screen
  53. if (pos.X < 0)
  54. vel.X = Math.Abs(vel.X);
  55. else if (pos.X > width)
  56. vel.X = -Math.Abs(vel.X);
  57. if (pos.Y < 0)
  58. vel.Y = Math.Abs(vel.Y);
  59. else if (pos.Y > height)
  60. vel.Y = -Math.Abs(vel.Y);
  61. if (particle.State.Type != ParticleType.IgnoreGravity)
  62. {
  63. foreach (var blackHole in EntityManager.BlackHoles)
  64. {
  65. var dPos = blackHole.Position - pos;
  66. float distance = dPos.Length;
  67. var n = dPos / distance;
  68. vel += 10000 * n / (distance * distance + 10000);
  69. // add tangential acceleration for nearby particles
  70. if (distance < 400)
  71. vel += 45 * new Vector2(n.Y, -n.X) / (distance + 100);
  72. }
  73. }
  74. if (Math.Abs(vel.X) + Math.Abs(vel.Y) < 0.00000000001f) // denormalized floats cause significant performance issues
  75. vel = Vector2.Zero;
  76. else if (particle.State.Type == ParticleType.Enemy)
  77. vel *= 0.94f;
  78. else
  79. vel *= 0.96f + Math.Abs(pos.X) % 0.04f; // rand.Next() isn't thread-safe, so use the position for pseudo-randomness
  80. particle.State.Velocity = vel;
  81. }
  82. }
  83. }