VelocityColorModifier.cs 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. The Vector3 components represent HSL values
  29. /// (Hue, Saturation, Lightness).
  30. /// </remarks>
  31. public Vector3 StationaryColor;
  32. /// <summary>
  33. /// Gets or sets the color for particles that have reached or exceeded the velocity threshold.
  34. /// </summary>
  35. /// <remarks>
  36. /// This color is applied to fast-moving particles and serves as the end point
  37. /// for color interpolation. The Vector3 components represent HSL values
  38. /// (Hue, Saturation, Lightness).
  39. /// </remarks>
  40. public Vector3 VelocityColor;
  41. /// <summary>
  42. /// Gets or sets the velocity magnitude at which particles fully transition to the velocity color.
  43. /// </summary>
  44. /// <remarks>
  45. /// This value defines the speed threshold that determines when a particle should
  46. /// display the full <see cref="VelocityColor"/>. Particles moving slower than this
  47. /// threshold will display a color interpolated between <see cref="StationaryColor"/> and
  48. /// <see cref="VelocityColor"/> based on their speed relative to this threshold.
  49. /// </remarks>
  50. public float VelocityThreshold;
  51. /// <summary>
  52. /// Updates all particles by changing their colors based on their current velocity.
  53. /// </summary>
  54. /// <inheritdoc/>
  55. protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
  56. {
  57. if (!Enabled) { return; }
  58. float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
  59. for (int i = 0; i < particleCount && iterator.HasNext; i++)
  60. {
  61. Particle* particle = iterator.Next();
  62. float velocitySquared = particle->Velocity[0] * particle->Velocity[0] +
  63. particle->Velocity[1] * particle->Velocity[1];
  64. if (velocitySquared >= velocityThreshold2)
  65. {
  66. particle->Color[0] = VelocityColor.X;
  67. particle->Color[1] = VelocityColor.Y;
  68. particle->Color[2] = VelocityColor.Z;
  69. }
  70. else
  71. {
  72. Vector3 deltaColor = VelocityColor - StationaryColor;
  73. float t = MathF.Sqrt(velocitySquared) / VelocityThreshold;
  74. float h = deltaColor.X * t + StationaryColor.X;
  75. float s = deltaColor.Y * t + StationaryColor.Y;
  76. float l = deltaColor.Z * t + StationaryColor.Z;
  77. particle->Color[0] = h;
  78. particle->Color[1] = s;
  79. particle->Color[2] = l;
  80. }
  81. }
  82. }
  83. }