// Copyright (c) Craftwork Games. All rights reserved. // Licensed under the MIT license. // See LICENSE file in the project root for full license information. using System; using Microsoft.Xna.Framework; using MonoGame.Extended.Particles.Data; namespace MonoGame.Extended.Particles.Modifiers; /// /// A modifier that changes particle colors based on their velocity. /// /// /// The adjusts particle colors dynamically according to their /// movement speed. Particles can transition smoothly between two defined colors: /// /// A color for stationary or slow-moving particles () /// A color for fast-moving particles () /// /// /// The color values are represented in HSL (Hue, Saturation, Lightness) format as a Vector3. /// public class VelocityColorModifier : Modifier { /// /// Gets or sets the color for particles that are stationary or moving slowly. /// /// /// This color is applied to particles with zero velocity and serves as the starting /// point for color interpolation. /// public HslColor StationaryColor { get; set; } /// /// Gets or sets the color for particles that have reached or exceeded the velocity threshold. /// /// /// This color is applied to fast-moving particles and serves as the end point /// for color interpolation. /// public HslColor VelocityColor { get; set; } /// /// Gets or sets the velocity magnitude at which particles fully transition to the velocity color. /// /// /// This value defines the speed threshold that determines when a particle should /// display the full . Particles moving slower than this /// threshold will display a color interpolated between and /// based on their speed relative to this threshold. /// public float VelocityThreshold { get; set; } /// /// Updates all particles by changing their colors based on their current velocity. /// /// protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount) { if (!Enabled) { return; } float velocityThreshold2 = VelocityThreshold * VelocityThreshold; for (int i = 0; i < particleCount && iterator.HasNext; i++) { Particle* particle = iterator.Next(); float velocitySquared = particle->Velocity[0] * particle->Velocity[0] + particle->Velocity[1] * particle->Velocity[1]; if (velocitySquared >= velocityThreshold2) { particle->Color[0] = VelocityColor.H; particle->Color[1] = VelocityColor.S; particle->Color[2] = VelocityColor.L; } else { HslColor deltaColor = VelocityColor - StationaryColor; float t = MathF.Sqrt(velocitySquared) / VelocityThreshold; float h = deltaColor.H * t + StationaryColor.H; float s = deltaColor.S * t + StationaryColor.S; float l = deltaColor.L * t + StationaryColor.L; particle->Color[0] = h; particle->Color[1] = s; particle->Color[2] = l; } } } }