VelocityColorModifier.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright (c) Craftwork Games. All rights reserved.
  2. // Licensed under the MIT license.
  3. // See LICENSE file in the project root for full license information.
  4. using System;
  5. using Microsoft.Xna.Framework;
  6. using MonoGame.Extended.Particles.Data;
  7. namespace MonoGame.Extended.Particles.Modifiers;
  8. /// <summary>
  9. /// A modifier that changes particle colors based on their velocity.
  10. /// </summary>
  11. /// <remarks>
  12. /// The <see cref="VelocityColorModifier"/> adjusts particle colors dynamically according to their
  13. /// movement speed. Particles can transition smoothly between two defined colors:
  14. /// <list type="bullet">
  15. /// <item>A color for stationary or slow-moving particles (<see cref="StationaryColor"/>)</item>
  16. /// <item>A color for fast-moving particles (<see cref="VelocityColor"/>)</item>
  17. /// </list>
  18. ///
  19. /// The color values are represented in HSL (Hue, Saturation, Lightness) format as a Vector3.
  20. /// </remarks>
  21. public class VelocityColorModifier : Modifier
  22. {
  23. /// <summary>
  24. /// Gets or sets the color for particles that are stationary or moving slowly.
  25. /// </summary>
  26. /// <remarks>
  27. /// This color is applied to particles with zero velocity and serves as the starting
  28. /// point for color interpolation.
  29. /// </remarks>
  30. public HslColor StationaryColor { get; set; }
  31. /// <summary>
  32. /// Gets or sets the color for particles that have reached or exceeded the velocity threshold.
  33. /// </summary>
  34. /// <remarks>
  35. /// This color is applied to fast-moving particles and serves as the end point
  36. /// for color interpolation.
  37. /// </remarks>
  38. public HslColor VelocityColor { get; set; }
  39. /// <summary>
  40. /// Gets or sets the velocity magnitude at which particles fully transition to the velocity color.
  41. /// </summary>
  42. /// <remarks>
  43. /// This value defines the speed threshold that determines when a particle should
  44. /// display the full <see cref="VelocityColor"/>. Particles moving slower than this
  45. /// threshold will display a color interpolated between <see cref="StationaryColor"/> and
  46. /// <see cref="VelocityColor"/> based on their speed relative to this threshold.
  47. /// </remarks>
  48. public float VelocityThreshold { get; set; }
  49. /// <summary>
  50. /// Updates all particles by changing their colors based on their current velocity.
  51. /// </summary>
  52. /// <inheritdoc/>
  53. protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
  54. {
  55. if (!Enabled) { return; }
  56. float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
  57. for (int i = 0; i < particleCount && iterator.HasNext; i++)
  58. {
  59. Particle* particle = iterator.Next();
  60. float velocitySquared = particle->Velocity[0] * particle->Velocity[0] +
  61. particle->Velocity[1] * particle->Velocity[1];
  62. if (velocitySquared >= velocityThreshold2)
  63. {
  64. particle->Color[0] = VelocityColor.H;
  65. particle->Color[1] = VelocityColor.S;
  66. particle->Color[2] = VelocityColor.L;
  67. }
  68. else
  69. {
  70. HslColor deltaColor = VelocityColor - StationaryColor;
  71. float t = MathF.Sqrt(velocitySquared) / VelocityThreshold;
  72. float h = deltaColor.H * t + StationaryColor.H;
  73. float s = deltaColor.S * t + StationaryColor.S;
  74. float l = deltaColor.L * t + StationaryColor.L;
  75. particle->Color[0] = h;
  76. particle->Color[1] = s;
  77. particle->Color[2] = l;
  78. }
  79. }
  80. }
  81. }