LineProfile.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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 System;
  5. using Microsoft.Xna.Framework;
  6. namespace MonoGame.Extended.Particles.Profiles;
  7. /// <summary>
  8. /// A profile that distributes particles uniformly along a line segment with random headings.
  9. /// </summary>
  10. /// <remarks>
  11. /// The <see cref="LineProfile"/> positions particles randomly along a line segment centered at the emitter position and
  12. /// defined by an axis direction and length.
  13. /// </remarks>
  14. public sealed class LineProfile : Profile
  15. {
  16. /// <summary>
  17. /// Gets or sets the direction vector of the line axis.
  18. /// </summary>
  19. public Vector2 Axis { get; set; }
  20. /// <summary>
  21. /// Gets or sets the length of the line segment.
  22. /// </summary>
  23. public float Length { get; set; }
  24. /// <summary>
  25. /// Gets or sets the emission direction vector used when <see cref="Radiate"/> is
  26. /// <see cref="LineRadiation.Directional"/> or as a scale factor when <see cref="Radiate"/> is
  27. /// <see cref="LineRadiation.PerpendicularUp"/> or <see cref="LineRadiation.PerpendicularDown"/>.
  28. /// </summary>
  29. /// <remarks>
  30. /// For <see cref="LineRadiation.Directional"/>, this vector directly specifies the particle heading direction.
  31. /// For <see cref="LineRadiation.PerpendicularUp"/> and <see cref="LineRadiation.PerpendicularDown"/>, this vector's
  32. /// magnitude and sign control the normal emission behavior. Positive values emit in the specified normal direction,
  33. /// while negative values flip to the opposite direction.
  34. /// This property is ignored when <see cref="Radiate"/> is <see cref="LineRadiation.None"/>.
  35. /// </remarks>
  36. public Vector2 Direction { get; set; }= Vector2.UnitY;
  37. /// <summary>
  38. /// Gets or sets the radiation mode that determines how particle headings are calculated.
  39. /// </summary>
  40. public LineRadiation Radiate { get; set; } = LineRadiation.None;
  41. /// <summary>
  42. /// Computes the offset and heading for a new particle.
  43. /// </summary>
  44. /// <param name="offset">A pointer to the Vector2 where the offset from the emitter position will be stored.</param>
  45. /// <param name="heading">A pointer to the Vector2 where the unit direction vector will be stored.</param>
  46. /// <exception cref="InvalidOperationException">
  47. /// Thrown when <see cref="Radiate"/> contains an unsupported value.
  48. /// </exception>
  49. public override unsafe void GetOffsetAndHeading(Vector2* offset, Vector2* heading)
  50. {
  51. float value = FastRandom.Shared.NextSingle(Length * -0.5f, Length * 0.5f);
  52. Vector2 normalizedAxis = Vector2.Normalize(Axis);
  53. offset->X = normalizedAxis.X * value;
  54. offset->Y = normalizedAxis.Y * value;
  55. // Calculate heading based on radiation mode
  56. switch (Radiate)
  57. {
  58. case LineRadiation.None:
  59. FastRandom.Shared.NextUnitVector(heading);
  60. break;
  61. case LineRadiation.Directional:
  62. Vector2 normalizedDirection = Vector2.Normalize(Direction);
  63. heading->X = normalizedDirection.X;
  64. heading->Y = normalizedDirection.Y;
  65. break;
  66. case LineRadiation.PerpendicularUp:
  67. heading->X = normalizedAxis.Y;
  68. heading->Y = -normalizedAxis.X;
  69. break;
  70. case LineRadiation.PerpendicularDown:
  71. heading->X = -normalizedAxis.Y;
  72. heading->Y = normalizedAxis.X;
  73. break;
  74. default:
  75. throw new InvalidOperationException($"Unsupported radiation mode '{Radiate}'");
  76. }
  77. }
  78. }