// Copyright (c) Craftwork Games. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System;
using Microsoft.Xna.Framework;
using MonoGame.Extended.Particles.Data;
namespace MonoGame.Extended.Particles.Modifiers;
///
/// A modifier that creates a gravitational vortex effect, pulling particles toward a central point.
///
///
/// The simulates a gravitational attraction between a central point and
/// each particle. The strength of the attraction is based on gravitational principles, where the force
/// is proportional to the masses and inversely proportional to the square of the distance.
///
/// The actual acceleration applied to each particle is clamped to prevent particles from moving
/// too quickly when they get close to the center of the vortex.
///
public unsafe class VortexModifier : Modifier
{
private const float GRAVITY = 100000f;
///
/// Gets or sets the center position of the vortex in 2D space.
///
///
/// Particles will be attracted toward this point.
///
public Vector2 Position;
///
/// Gets or sets the mass of the vortex center.
///
///
/// Higher mass values create stronger attraction forces.
///
public float Mass;
///
/// Gets or sets the maximum speed that the vortex can impart on particles.
///
///
/// This value limits how quickly particles can be accelerated by the vortex,
/// preventing extreme velocities when particles get very close to the center.
///
public float MaxSpeed;
///
/// Updates all particles by applying a gravitational force towards the vortex center.
///
///
public override unsafe void Update(float elapsedSeconds, ParticleIterator iterator)
{
if (!Enabled) { return; }
while (iterator.HasNext)
{
Particle* particle = iterator.Next();
float distx = Position.X - particle->Position[0];
float disty = Position.Y - particle->Position[1];
float distance2 = (distx * distx) + (disty * disty);
float distance = (float)Math.Sqrt(distance2);
float m = (GRAVITY * Mass * particle->Mass) / distance2;
m = Math.Max(Math.Min(m, MaxSpeed), -MaxSpeed) * elapsedSeconds;
distx = (distx / distance) * m;
disty = (disty / distance) * m;
particle->Velocity[0] += distx;
particle->Velocity[1] += disty;
}
}
}