// Copyright (c) Craftwork Games. All rights reserved. // Licensed under the MIT license. // See LICENSE file in the project root for full license information. using MonoGame.Extended.Particles.Data; namespace MonoGame.Extended.Particles.Modifiers.Containers; /// /// A modifier that constrains particles within a rectangular boundary. /// /// /// The keeps particles inside a rectangular area, reflecting them off the /// boundaries based on a configurable restitution coefficient. The rectangle is centered at each particle's trigger /// position (where it was emitted), creating local containment areas. /// public sealed class RectangleContainerModifier : Modifier { /// /// Gets or sets the width of the rectangular container. /// public int Width; /// /// Gets or sets the height of the rectangular container, in units. /// public int Height; /// /// Gets or sets the coefficient of restitution (bounciness) for particle /// collisions with the boundary. /// /// /// /// /// A value of 1.0 creates a perfectly elastic collision where particles maintain their energy. /// /// /// Values less than 1.0 create inelastic collisions where particles lose energy with each bounce. /// /// /// Values greater than 1.0 create super-elastic collisions where particles gain energy. /// /// /// /// The default value is 1.0. /// public float RestitutionCoefficient = 1.0f; /// /// Updates all particles by constraining them to the rectangular boundary. /// /// public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator) { if (!Enabled) { return; } while (iterator.HasNext) { Particle* particle = iterator.Next(); float left = particle->TriggeredPos[0] + Width * -0.5f; float right = particle->TriggeredPos[0] + Width * 0.5f; float top = particle->TriggeredPos[1] + Height * -0.5f; float bottom = particle->TriggeredPos[1] + Height * 0.5f; float xPos = particle->Position[0]; float xVel = particle->Velocity[0]; float yPos = particle->Position[1]; float yVel = particle->Velocity[1]; if ((int)particle->Position[0] < left) { xPos = left + (left - xPos); xVel = -xVel * RestitutionCoefficient; } else { if (particle->Position[0] > right) { xPos = right - (xPos - right); xVel = -xVel * RestitutionCoefficient; } } if (particle->Position[1] < top) { yPos = top + (top - yPos); yVel = -yVel * RestitutionCoefficient; } else { if ((int)particle->Position[1] > bottom) { yPos = bottom - (yPos - bottom); yVel = -yVel * RestitutionCoefficient; } } particle->Position[0] = xPos; particle->Position[1] = yPos; particle->Velocity[0] = xVel; particle->Velocity[1] = yVel; } } }