BoxUniformProfile.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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 Microsoft.Xna.Framework;
  5. namespace MonoGame.Extended.Particles.Profiles;
  6. /// <summary>
  7. /// A profile that distributes particles along the edges of a rectangular boundary with uniform density.
  8. /// </summary>
  9. /// <remarks>
  10. /// <para>
  11. /// The <see cref="BoxUniformProfile"/> positions new particles on the perimeter of a rectangle centered at the
  12. /// emitter's position. Unlike <see cref="BoxProfile"/> which gives equal probability to each side, this profile
  13. /// allocates probability proportional to the length of each side, ensuring a uniform distribution of particles
  14. /// around the entire perimeter.
  15. /// </para>
  16. /// <para>
  17. /// This means longer sides will receive more particles than shorter sides, creating a visually balanced
  18. /// distribution regardless of the rectangle's dimensions.
  19. /// </para>
  20. /// <para>
  21. /// Particles are given random unit vector headings, allowing them to move in any direction regardless of their
  22. /// starting edge.
  23. /// </para>
  24. /// </remarks>
  25. public class BoxUniformProfile : Profile
  26. {
  27. /// <summary>
  28. /// The width of the rectangular perimeter.
  29. /// </summary>
  30. public float Width;
  31. /// <summary>
  32. /// The height of the rectangular perimeter.
  33. /// </summary>
  34. public float Height;
  35. /// <summary>
  36. /// Computes the offset and heading for a new particle.
  37. /// </summary>
  38. /// <param name="offset">A pointer to the Vector2 where the offset from the emitter position will be stored.</param>
  39. /// <param name="heading">A pointer to the Vector2 where the unit direction vector will be stored.</param>
  40. public override unsafe void GetOffsetAndHeading(Vector2* offset, Vector2* heading)
  41. {
  42. int perimeter = (int)(2 * Width + 2 * Height);
  43. int value = FastRandom.Shared.Next(perimeter);
  44. switch (value)
  45. {
  46. // Top
  47. case var _ when value < Width:
  48. offset->X = FastRandom.Shared.NextSingle(Width * -0.5f, Width * 0.5f);
  49. offset->Y = Height * -0.5f;
  50. break;
  51. // Bottom
  52. case var _ when value < 2 * Width:
  53. offset->X = FastRandom.Shared.NextSingle(Width * -0.5f, Width * 0.5f);
  54. offset->Y = Height * 0.5f;
  55. break;
  56. // Left
  57. case var _ when value < 2 * Width + Height:
  58. offset->X = Width * -0.5f;
  59. offset->Y = FastRandom.Shared.NextSingle(Height * -0.5f, Height * 0.5f);
  60. break;
  61. // Right
  62. default:
  63. offset->X = Width * 0.5f;
  64. offset->Y = FastRandom.Shared.NextSingle(Height * -0.5f, Height * 0.5f);
  65. break;
  66. }
  67. FastRandom.Shared.NextUnitVector(heading);
  68. }
  69. }