RectangleContainerModifier.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 MonoGame.Extended.Particles.Data;
  5. namespace MonoGame.Extended.Particles.Modifiers.Containers;
  6. /// <summary>
  7. /// A modifier that constrains particles within a rectangular boundary.
  8. /// </summary>
  9. /// <remarks>
  10. /// The <see cref="RectangleContainerModifier"/> keeps particles inside a rectangular area, reflecting them off the
  11. /// boundaries based on a configurable restitution coefficient. The rectangle is centered at each particle's trigger
  12. /// position (where it was emitted), creating local containment areas.
  13. /// </remarks>
  14. public sealed class RectangleContainerModifier : Modifier
  15. {
  16. /// <summary>
  17. /// Gets or sets the width of the rectangular container.
  18. /// </summary>
  19. public int Width;
  20. /// <summary>
  21. /// Gets or sets the height of the rectangular container, in units.
  22. /// </summary>
  23. public int Height;
  24. /// <summary>
  25. /// Gets or sets the coefficient of restitution (bounciness) for particle
  26. /// collisions with the boundary.
  27. /// </summary>
  28. /// <remarks>
  29. /// <list type="bullet">
  30. /// <item>
  31. /// A value of 1.0 creates a perfectly elastic collision where particles maintain their energy.
  32. /// </item>
  33. /// <item>
  34. /// Values less than 1.0 create inelastic collisions where particles lose energy with each bounce.
  35. /// </item>
  36. /// <item>
  37. /// Values greater than 1.0 create super-elastic collisions where particles gain energy.
  38. /// </item>
  39. /// </list>
  40. ///
  41. /// The default value is 1.0.
  42. /// </remarks>
  43. public float RestitutionCoefficient = 1.0f;
  44. /// <summary>
  45. /// Updates all particles by constraining them to the rectangular boundary.
  46. /// </summary>
  47. /// <inheritdoc/>
  48. protected internal override unsafe void Update(float elapsedSeconds, ParticleIterator iterator, int particleCount)
  49. {
  50. if (!Enabled) { return; }
  51. for (int i = 0; i < particleCount && iterator.HasNext; i++)
  52. {
  53. Particle* particle = iterator.Next();
  54. float left = particle->TriggeredPos[0] + Width * -0.5f;
  55. float right = particle->TriggeredPos[0] + Width * 0.5f;
  56. float top = particle->TriggeredPos[1] + Height * -0.5f;
  57. float bottom = particle->TriggeredPos[1] + Height * 0.5f;
  58. float xPos = particle->Position[0];
  59. float xVel = particle->Velocity[0];
  60. float yPos = particle->Position[1];
  61. float yVel = particle->Velocity[1];
  62. if ((int)particle->Position[0] < left)
  63. {
  64. xPos = left + (left - xPos);
  65. xVel = -xVel * RestitutionCoefficient;
  66. }
  67. else
  68. {
  69. if (particle->Position[0] > right)
  70. {
  71. xPos = right - (xPos - right);
  72. xVel = -xVel * RestitutionCoefficient;
  73. }
  74. }
  75. if (particle->Position[1] < top)
  76. {
  77. yPos = top + (top - yPos);
  78. yVel = -yVel * RestitutionCoefficient;
  79. }
  80. else
  81. {
  82. if ((int)particle->Position[1] > bottom)
  83. {
  84. yPos = bottom - (yPos - bottom);
  85. yVel = -yVel * RestitutionCoefficient;
  86. }
  87. }
  88. particle->Position[0] = xPos;
  89. particle->Position[1] = yPos;
  90. particle->Velocity[0] = xVel;
  91. particle->Velocity[1] = yVel;
  92. }
  93. }
  94. }