117 lines
3.5 KiB
C#
117 lines
3.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using FarseerPhysics.Dynamics;
|
|
using Microsoft.Xna.Framework;
|
|
|
|
namespace FarseerPhysics.Controllers
|
|
{
|
|
public enum GravityType
|
|
{
|
|
Linear,
|
|
DistanceSquared
|
|
}
|
|
|
|
public class GravityController : Controller
|
|
{
|
|
public List<Body> Bodies = new List<Body>();
|
|
public List<Vector2> Points = new List<Vector2>();
|
|
|
|
public GravityController(float strength)
|
|
: base(ControllerType.GravityController)
|
|
{
|
|
Strength = strength;
|
|
MaxRadius = float.MaxValue;
|
|
}
|
|
|
|
public GravityController(float strength, float maxRadius, float minRadius)
|
|
: base(ControllerType.GravityController)
|
|
{
|
|
MinRadius = minRadius;
|
|
MaxRadius = maxRadius;
|
|
Strength = strength;
|
|
}
|
|
|
|
public float MinRadius { get; set; }
|
|
public float MaxRadius { get; set; }
|
|
public float Strength { get; set; }
|
|
public GravityType GravityType { get; set; }
|
|
|
|
public override void Update(float dt)
|
|
{
|
|
Vector2 f = Vector2.Zero;
|
|
|
|
foreach (Body body1 in World.BodyList)
|
|
{
|
|
if (!IsActiveOn(body1))
|
|
continue;
|
|
|
|
foreach (Body body2 in Bodies)
|
|
{
|
|
if (body1 == body2 || (body1.IsStatic && body2.IsStatic) || !body2.Enabled)
|
|
continue;
|
|
|
|
Vector2 d = body2.WorldCenter - body1.WorldCenter;
|
|
float r2 = d.LengthSquared();
|
|
|
|
if (r2 < Settings.Epsilon)
|
|
continue;
|
|
|
|
float r = d.Length();
|
|
|
|
if (r >= MaxRadius || r <= MinRadius)
|
|
continue;
|
|
|
|
switch (GravityType)
|
|
{
|
|
case GravityType.DistanceSquared:
|
|
f = Strength / r2 / (float)Math.Sqrt(r2) * body1.Mass * body2.Mass * d;
|
|
break;
|
|
case GravityType.Linear:
|
|
f = Strength / r2 * body1.Mass * body2.Mass * d;
|
|
break;
|
|
}
|
|
|
|
body1.ApplyForce(ref f);
|
|
Vector2.Negate(ref f, out f);
|
|
body2.ApplyForce(ref f);
|
|
}
|
|
|
|
foreach (Vector2 point in Points)
|
|
{
|
|
Vector2 d = point - body1.Position;
|
|
float r2 = d.LengthSquared();
|
|
|
|
if (r2 < Settings.Epsilon)
|
|
continue;
|
|
|
|
float r = d.Length();
|
|
|
|
if (r >= MaxRadius || r <= MinRadius)
|
|
continue;
|
|
|
|
switch (GravityType)
|
|
{
|
|
case GravityType.DistanceSquared:
|
|
f = Strength / r2 / (float)Math.Sqrt(r2) * body1.Mass * d;
|
|
break;
|
|
case GravityType.Linear:
|
|
f = Strength / r2 * body1.Mass * d;
|
|
break;
|
|
}
|
|
|
|
body1.ApplyForce(ref f);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddBody(Body body)
|
|
{
|
|
Bodies.Add(body);
|
|
}
|
|
|
|
public void AddPoint(Vector2 point)
|
|
{
|
|
Points.Add(point);
|
|
}
|
|
}
|
|
} |