Use modifier frequency field (#1025)

This commit is contained in:
Christopher Whitley
2025-09-09 00:10:14 -04:00
committed by GitHub
parent d9cd99d4b9
commit 2906248f2f
13 changed files with 71 additions and 32 deletions
@@ -32,17 +32,17 @@ public class AgeModifier : Modifier
/// Updates all particles by applying each interpolator in the collection to each particle.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
for (int i = 0; i < Interpolators.Count; i++)
for (int j = 0; j < Interpolators.Count; j++)
{
Interpolators[i].Update(particle->Age, particle);
Interpolators[j].Update(particle->Age, particle);
}
}
}
@@ -64,13 +64,13 @@ public class CircleContainerModifier : Modifier
/// Updates all particles by constraining them to the circular boundary.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
float radiusSq = Radius * Radius;
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -51,11 +51,11 @@ public sealed class RectangleContainerModifier : Modifier
/// Updates all particles by constraining them to the rectangular boundary.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -30,11 +30,11 @@ public class RectangleLoopContainerModifier : Modifier
/// Updates all particles by wrapping them around to the opposite side when they cross the rectangular boundary.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -49,11 +49,11 @@ public class DragModifier : Modifier
/// Updates all particles by applying drag forces based on their velocity.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -41,13 +41,13 @@ public class LinearGravityModifier : Modifier
/// Updates all particles by applying a linear gravitational force.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
Vector2 vector = Direction * (Strength * elapsedSeconds);
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -2,6 +2,8 @@
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System;
namespace MonoGame.Extended.Particles.Modifiers;
/// <summary>
@@ -17,6 +19,10 @@ public abstract class Modifier
{
private const float DEFAULT_MODIFIER_FREQUENCY = 60.0f;
private float _frequency;
private float _cycleTime;
private int _particlesUpdatedThisCycle;
/// <summary>
/// Gets or sets the display name of this modifier.
/// </summary>
@@ -40,7 +46,18 @@ public abstract class Modifier
/// cost of performance. Lower values reduce CPU usage but may make particle changes appear
/// less fluid.
/// </remarks>
public float Frequency;
public float Frequency
{
get => _frequency;
set
{
if (value <= 0.0f)
throw new ArgumentOutOfRangeException(nameof(value), "Frequency must be greater than zero.");
_frequency = value;
_cycleTime = 1f / _frequency;
}
}
/// <summary>
/// Indicates whether this modifier is enabled.
@@ -65,10 +82,32 @@ public abstract class Modifier
Enabled = true;
}
internal void InternalUpdate(float elapsedSeconds, ParticleIterator iterator)
{
if (!Enabled || iterator.Total == 0)
return;
var particlesRemaining = iterator.Total - _particlesUpdatedThisCycle;
var particlesToUpdate = Math.Min(particlesRemaining, (int)Math.Ceiling((elapsedSeconds / _cycleTime) * iterator.Total));
if (particlesToUpdate > 0)
{
// Create a new iterator starting from the offset position
var offsetIterator = iterator.Reset(_particlesUpdatedThisCycle);
Update(_cycleTime, offsetIterator, particlesToUpdate);
_particlesUpdatedThisCycle += particlesToUpdate;
}
if (_particlesUpdatedThisCycle >= iterator.Total)
_particlesUpdatedThisCycle = 0;
}
/// <summary>
/// Updates the properties of particles according to this modifier's specific behavior.
/// </summary>
/// <param name="elapsedSeconds">The elapsed time, in seconds, since the last update.</param>
/// <param name="iterator">The iterator used to iterate the particles ot update.</param>
public abstract void Update(float elapsedSeconds, ParticleIterator iterator);
protected internal abstract void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount);
}
@@ -59,7 +59,7 @@ public abstract class ModifierExecutionStrategy
{
for (int i = 0; i < modifiers.Count; i++)
{
modifiers[i].Update(elapsedSeconds, iterator.Reset());
modifiers[i].InternalUpdate(elapsedSeconds, iterator);
}
}
@@ -80,7 +80,7 @@ public abstract class ModifierExecutionStrategy
{
internal override unsafe void ExecuteModifiers(List<Modifier> modifiers, float elapsedSeconds, ParticleIterator iterator)
{
TPL.ForEach(modifiers, modifier => modifier.Update(elapsedSeconds, iterator.Reset()));
TPL.ForEach(modifiers, modifier => modifier.InternalUpdate(elapsedSeconds, iterator));
}
public override string ToString()
@@ -32,11 +32,11 @@ public sealed class OpacityFastFadeModifier : Modifier
/// Updates all particles by setting their opacity based on their age.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -32,13 +32,13 @@ public class RotationModifier : Modifier
/// Updates all particles by applying rotation based on the elapsed time.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
float rotationRateDelta = RotationRate * elapsedSeconds;
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -58,13 +58,13 @@ public class VelocityColorModifier : Modifier
/// Updates all particles by changing their colors based on their current velocity.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -38,13 +38,13 @@ public class VelocityModifier : Modifier
/// Updates all particles by applying interpolators with an amount based on each particle's velocity.
/// </summary>
/// <inheritdoc />
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
float velocityThreshold2 = VelocityThreshold * VelocityThreshold;
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();
@@ -53,9 +53,9 @@ public class VelocityModifier : Modifier
if (velocitySquared >= velocityThreshold2)
{
for (int i = 0; i < Interpolators.Count; i++)
for (int j = 0; j < Interpolators.Count; j++)
{
Interpolator interpolator = Interpolators[i];
Interpolator interpolator = Interpolators[j];
interpolator.Update(1, particle);
}
}
@@ -63,9 +63,9 @@ public class VelocityModifier : Modifier
{
float t = (float)Math.Sqrt(velocitySquared) / VelocityThreshold;
for (int i = 0; i < Interpolators.Count; i++)
for (int j = 0; j < Interpolators.Count; j++)
{
Interpolator interpolator = Interpolators[i];
Interpolator interpolator = Interpolators[j];
interpolator.Update(t, particle);
}
}
@@ -52,11 +52,11 @@ public unsafe class VortexModifier : Modifier
/// Updates all particles by applying a gravitational force towards the vortex center.
/// </summary>
/// <inheritdoc/>
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
{
if (!Enabled) { return; }
while (iterator.HasNext)
for (int i = 0; i < particleCount && iterator.HasNext; i++)
{
Particle* particle = iterator.Next();