summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-06-03 10:15:45 +0800
committerchai <215380520@qq.com>2024-06-03 10:15:45 +0800
commitacea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch)
tree0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers
parent88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff)
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers')
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/AgeModifier.cs26
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/CircleContainerModifier.cs52
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleContainerModifier.cs59
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleLoopContainerModifier.cs42
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/DragModifier.cs23
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ColorInterpolator.cs13
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/HueInterpolator.cs12
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/Interpolator.cs26
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/OpacityInterpolator.cs10
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/RotationInterpolator.cs10
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ScaleInterpolator.cs12
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/VelocityInterpolator12
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/LinearGravityModifier.cs23
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Modifier.cs18
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/OpacityFastFadeModifier.cs14
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/RotationModifier.cs18
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityColorModifier.cs36
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityModifier.cs43
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VortexModifier.cs30
19 files changed, 479 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/AgeModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/AgeModifier.cs
new file mode 100644
index 0000000..fac85f0
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/AgeModifier.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using MonoGame.Extended.Particles.Modifiers.Interpolators;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class AgeModifier : Modifier
+ {
+ [EditorBrowsable(EditorBrowsableState.Always)]
+ public List<Interpolator> Interpolators { get; set; } = new List<Interpolator>();
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var n = Interpolators.Count;
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ for (var i = 0; i < n; i++)
+ {
+ var interpolator = Interpolators[i];
+ interpolator.Update(particle->Age, particle);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/CircleContainerModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/CircleContainerModifier.cs
new file mode 100644
index 0000000..30d2802
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/CircleContainerModifier.cs
@@ -0,0 +1,52 @@
+using System;
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers.Containers
+{
+ public class CircleContainerModifier : Modifier
+ {
+ public float Radius { get; set; }
+ public bool Inside { get; set; } = true;
+ public float RestitutionCoefficient { get; set; } = 1;
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var radiusSq = Radius*Radius;
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var localPos = particle->Position - particle->TriggerPos;
+
+ var distSq = localPos.LengthSquared();
+ var normal = localPos;
+ normal.Normalize();
+
+ if (Inside)
+ {
+ if (distSq < radiusSq) continue;
+
+ SetReflected(distSq, particle, normal);
+ }
+ else
+ {
+ if (distSq > radiusSq) continue;
+
+ SetReflected(distSq, particle, -normal);
+ }
+ }
+ }
+
+ private unsafe void SetReflected(float distSq, Particle* particle, Vector2 normal)
+ {
+ var dist = (float) Math.Sqrt(distSq);
+ var d = dist - Radius; // how far outside the circle is the particle
+
+ var twoRestDot = 2*RestitutionCoefficient*
+ Vector2.Dot(particle->Velocity, normal);
+ particle->Velocity -= twoRestDot*normal;
+
+ // exact computation requires sqrt or goniometrics
+ particle->Position -= normal*d;
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleContainerModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleContainerModifier.cs
new file mode 100644
index 0000000..a56e072
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleContainerModifier.cs
@@ -0,0 +1,59 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers.Containers
+{
+ public sealed class RectangleContainerModifier : Modifier
+ {
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public float RestitutionCoefficient { get; set; } = 1;
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+
+ var left = particle->TriggerPos.X + Width*-0.5f;
+ var right = particle->TriggerPos.X + Width*0.5f;
+ var top = particle->TriggerPos.Y + Height*-0.5f;
+ var bottom = particle->TriggerPos.Y + Height*0.5f;
+
+ var xPos = particle->Position.X;
+ var xVel = particle->Velocity.X;
+ var yPos = particle->Position.Y;
+ var yVel = particle->Velocity.Y;
+
+ if ((int) particle->Position.X < left)
+ {
+ xPos = left + (left - xPos);
+ xVel = -xVel*RestitutionCoefficient;
+ }
+ else
+ {
+ if (particle->Position.X > right)
+ {
+ xPos = right - (xPos - right);
+ xVel = -xVel*RestitutionCoefficient;
+ }
+ }
+
+ if (particle->Position.Y < top)
+ {
+ yPos = top + (top - yPos);
+ yVel = -yVel*RestitutionCoefficient;
+ }
+ else
+ {
+ if ((int) particle->Position.Y > bottom)
+ {
+ yPos = bottom - (yPos - bottom);
+ yVel = -yVel*RestitutionCoefficient;
+ }
+ }
+ particle->Position = new Vector2(xPos, yPos);
+ particle->Velocity = new Vector2(xVel, yVel);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleLoopContainerModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleLoopContainerModifier.cs
new file mode 100644
index 0000000..4da6efa
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Containers/RectangleLoopContainerModifier.cs
@@ -0,0 +1,42 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers.Containers
+{
+ public class RectangleLoopContainerModifier : Modifier
+ {
+ public int Width { get; set; }
+ public int Height { get; set; }
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var left = particle->TriggerPos.X + Width*-0.5f;
+ var right = particle->TriggerPos.X + Width*0.5f;
+ var top = particle->TriggerPos.Y + Height*-0.5f;
+ var bottom = particle->TriggerPos.Y + Height*0.5f;
+
+ var xPos = particle->Position.X;
+ var yPos = particle->Position.Y;
+
+ if ((int) particle->Position.X < left)
+ xPos = particle->Position.X + Width;
+ else
+ {
+ if ((int) particle->Position.X > right)
+ xPos = particle->Position.X - Width;
+ }
+
+ if ((int) particle->Position.Y < top)
+ yPos = particle->Position.Y + Height;
+ else
+ {
+ if ((int) particle->Position.Y > bottom)
+ yPos = particle->Position.Y - Height;
+ }
+ particle->Position = new Vector2(xPos, yPos);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/DragModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/DragModifier.cs
new file mode 100644
index 0000000..f2d6d09
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/DragModifier.cs
@@ -0,0 +1,23 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class DragModifier : Modifier
+ {
+ public float DragCoefficient { get; set; } = 0.47f;
+ public float Density { get; set; } = .5f;
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var drag = -DragCoefficient*Density*particle->Mass*elapsedSeconds;
+
+ particle->Velocity = new Vector2(
+ particle->Velocity.X + particle->Velocity.X*drag,
+ particle->Velocity.Y + particle->Velocity.Y*drag);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ColorInterpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ColorInterpolator.cs
new file mode 100644
index 0000000..f94c689
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ColorInterpolator.cs
@@ -0,0 +1,13 @@
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ /// <summary>
+ /// Defines a modifier which interpolates the color of a particle over the course of its lifetime.
+ /// </summary>
+ public sealed class ColorInterpolator : Interpolator<HslColor>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Color = HslColor.Lerp(StartValue, EndValue, amount);
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/HueInterpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/HueInterpolator.cs
new file mode 100644
index 0000000..8b58a8e
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/HueInterpolator.cs
@@ -0,0 +1,12 @@
+using MonoGame.Extended;
+
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public class HueInterpolator : Interpolator<float>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Color = new HslColor((EndValue - StartValue) * amount + StartValue, particle->Color.S, particle->Color.L);
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/Interpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/Interpolator.cs
new file mode 100644
index 0000000..0ec9866
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/Interpolator.cs
@@ -0,0 +1,26 @@
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public abstract class Interpolator
+ {
+ protected Interpolator()
+ {
+ Name = GetType().Name;
+ }
+
+ public string Name { get; set; }
+ public abstract unsafe void Update(float amount, Particle* particle);
+ }
+
+ public abstract class Interpolator<T> : Interpolator
+ {
+ /// <summary>
+ /// Gets or sets the intial value when the particles are created.
+ /// </summary>
+ public virtual T StartValue { get; set; }
+
+ /// <summary>
+ /// Gets or sets the final value when the particles are retired.
+ /// </summary>
+ public virtual T EndValue { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/OpacityInterpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/OpacityInterpolator.cs
new file mode 100644
index 0000000..0a26fcd
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/OpacityInterpolator.cs
@@ -0,0 +1,10 @@
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public class OpacityInterpolator : Interpolator<float>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Opacity = (EndValue - StartValue) * amount + StartValue;
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/RotationInterpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/RotationInterpolator.cs
new file mode 100644
index 0000000..44a72de
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/RotationInterpolator.cs
@@ -0,0 +1,10 @@
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public class RotationInterpolator : Interpolator<float>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Rotation = (EndValue - StartValue) * amount + StartValue;
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ScaleInterpolator.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ScaleInterpolator.cs
new file mode 100644
index 0000000..aff9244
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/ScaleInterpolator.cs
@@ -0,0 +1,12 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public class ScaleInterpolator : Interpolator<Vector2>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Scale = (EndValue - StartValue) * amount + StartValue;
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/VelocityInterpolator b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/VelocityInterpolator
new file mode 100644
index 0000000..bad04b1
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Interpolators/VelocityInterpolator
@@ -0,0 +1,12 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers.Interpolators
+{
+ public class VelocityInterpolator : Interpolator<Vector2>
+ {
+ public override unsafe void Update(float amount, Particle* particle)
+ {
+ particle->Velocity = (EndValue - StartValue) * amount + StartValue;
+ }
+ }
+}
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/LinearGravityModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/LinearGravityModifier.cs
new file mode 100644
index 0000000..e9ed216
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/LinearGravityModifier.cs
@@ -0,0 +1,23 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class LinearGravityModifier : Modifier
+ {
+ public Vector2 Direction { get; set; }
+ public float Strength { get; set; }
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var vector = Direction*(Strength*elapsedSeconds);
+
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ particle->Velocity = new Vector2(
+ particle->Velocity.X + vector.X*particle->Mass,
+ particle->Velocity.Y + vector.Y*particle->Mass);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Modifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Modifier.cs
new file mode 100644
index 0000000..bd62d25
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/Modifier.cs
@@ -0,0 +1,18 @@
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public abstract class Modifier
+ {
+ protected Modifier()
+ {
+ Name = GetType().Name;
+ }
+
+ public string Name { get; set; }
+ public abstract void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator);
+
+ public override string ToString()
+ {
+ return $"{Name} [{GetType().Name}]";
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/OpacityFastFadeModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/OpacityFastFadeModifier.cs
new file mode 100644
index 0000000..9cc44d8
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/OpacityFastFadeModifier.cs
@@ -0,0 +1,14 @@
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public sealed class OpacityFastFadeModifier : Modifier
+ {
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ particle->Opacity = 1.0f - particle->Age;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/RotationModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/RotationModifier.cs
new file mode 100644
index 0000000..2b17058
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/RotationModifier.cs
@@ -0,0 +1,18 @@
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class RotationModifier : Modifier
+ {
+ public float RotationRate { get; set; }
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var rotationRateDelta = RotationRate*elapsedSeconds;
+
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ particle->Rotation += rotationRateDelta;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityColorModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityColorModifier.cs
new file mode 100644
index 0000000..ae9dc7b
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityColorModifier.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class VelocityColorModifier : Modifier
+ {
+ public HslColor StationaryColor { get; set; }
+ public HslColor VelocityColor { get; set; }
+ public float VelocityThreshold { get; set; }
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var velocityThreshold2 = VelocityThreshold*VelocityThreshold;
+
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var velocity2 = particle->Velocity.X*particle->Velocity.X +
+ particle->Velocity.Y*particle->Velocity.Y;
+ var deltaColor = VelocityColor - StationaryColor;
+
+ if (velocity2 >= velocityThreshold2)
+ VelocityColor.CopyTo(out particle->Color);
+ else
+ {
+ var t = (float) Math.Sqrt(velocity2)/VelocityThreshold;
+
+ particle->Color = new HslColor(
+ deltaColor.H*t + StationaryColor.H,
+ deltaColor.S*t + StationaryColor.S,
+ deltaColor.L*t + StationaryColor.L);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityModifier.cs
new file mode 100644
index 0000000..f089abc
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VelocityModifier.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using MonoGame.Extended.Particles.Modifiers.Interpolators;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public class VelocityModifier : Modifier
+ {
+ public List<Interpolator> Interpolators { get; set; } = new List<Interpolator>();
+
+ public float VelocityThreshold { get; set; }
+
+ public override unsafe void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ var velocityThreshold2 = VelocityThreshold*VelocityThreshold;
+ var n = Interpolators.Count;
+
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var velocity2 = particle->Velocity.LengthSquared();
+
+ if (velocity2 >= velocityThreshold2)
+ {
+ for (var i = 0; i < n; i++)
+ {
+ var interpolator = Interpolators[i];
+ interpolator.Update(1, particle);
+ }
+ }
+ else
+ {
+ var t = (float) Math.Sqrt(velocity2)/VelocityThreshold;
+ for (var i = 0; i < n; i++)
+ {
+ var interpolator = Interpolators[i];
+ interpolator.Update(t, particle);
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VortexModifier.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VortexModifier.cs
new file mode 100644
index 0000000..03a9999
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Particles/Modifiers/VortexModifier.cs
@@ -0,0 +1,30 @@
+using Microsoft.Xna.Framework;
+
+namespace MonoGame.Extended.Particles.Modifiers
+{
+ public unsafe class VortexModifier : Modifier
+ {
+ // Note: not the real-life one
+ private const float _gravConst = 100000f;
+
+ public Vector2 Position { get; set; }
+ public float Mass { get; set; }
+ public float MaxSpeed { get; set; }
+
+ public override void Update(float elapsedSeconds, ParticleBuffer.ParticleIterator iterator)
+ {
+ while (iterator.HasNext)
+ {
+ var particle = iterator.Next();
+ var diff = Position + particle->TriggerPos - particle->Position;
+
+ var distance2 = diff.LengthSquared();
+
+ var speedGain = _gravConst*Mass/distance2*elapsedSeconds;
+ // normalize distances and multiply by speedGain
+ diff.Normalize();
+ particle->Velocity += diff*speedGain;
+ }
+ }
+ }
+} \ No newline at end of file