using System; using System.Collections.Generic; using System.Linq; using Duality; using Duality.Components.Physics; namespace Gravity { /// /// This component will gravitate other objects based on it's configuration. /// [RequiredComponent(typeof(RigidBody))] public class Gravitator: Component, ICmpUpdatable { // Range is not an auto-property because I felt it needed a default value. // feel free to change it into an auto-property if you'd like. private float range = 1000f; /// /// The maximum range at which this object will gravitate other objects. /// public float Range { get { return this.range; } set { this.range = value; } } private float multiplier = 1f; /// /// The amount with which the gravitational force is multiplied with. /// public float ForceMultiplier { get { return this.multiplier; } set { this.multiplier = value; } } // An enum containing the types of gravitation that can be caused by this // object. public enum GravityType { Attract, Repel } /// /// The type of gravitation that will be caused by this object. /// public GravityType GravitationType { get; set; } // We can perform actions every game update here. void ICmpUpdatable.OnUpdate() { // Gravitate any objects within range of this object. this.GravitateAll(); } /// /// This function attracts all RigidBodies that are in a list of RigidBodies /// towards this GameObject. This code is heavily based on a /// Unity3D Wiki page. /// public void GravitateAll() { // Enumerate over every RigidBody in the scene. foreach (RigidBody rigidBody in this.GameObj.ParentScene.FindComponents()) { // If the RigidBody, well, exists, and if it's not this object's RigidBody... if (rigidBody != null && rigidBody != this.GameObj.GetComponent()) { // The difference in distance between this object and the other object, as // a Vector2. Vector2 distanceOffset = (this.GameObj.Transform.Pos - rigidBody.GameObj.Transform.Pos).Xy; // The force that will be applied to the other object. It depends on the // distanceOffset, it's squared magnitude and the mass of the other // RigidBody. // The force is multiplied by the ForceMultiplier, which is by default // set to 1. Vector2 appliedForce = (distanceOffset / distanceOffset.LengthSquared * rigidBody.Mass) * ForceMultiplier; // If the other distance between both objects is within the Range... if (distanceOffset.Length <= Range) { // Here we do a switch on the GravityType selected... switch (GravitationType) { // If the GravityType is to Attract... case GravityType.Attract: // Then just apply the force as it is... rigidBody.ApplyWorldForce(appliedForce); break; // If the GravityType is to Repel... case GravityType.Repel: // Then apply the force as negative. rigidBody.ApplyWorldForce(-appliedForce); break; } } } } } } }