Page 1 of 1

'GravitationalField' - How do I get the field to ignore?

Posted: Fri Jun 01, 2012 9:52 am
by Spankenstein
I have an entity associated with a GravitationalField class. This means that I have a kinematic or dynamic model that denotes the origin of the field.

The entity is there so it can be interacted with via a GUI. The position of the GravitationalField is always at the centroid of the associated entity.

Code: Select all

        public GravitationalFieldPrimitive(Game1 game, GravitationalFieldPrimitiveSettings settings)
            : base(game, settings = settings == null ? new GravitationalFieldPrimitiveSettings() : settings)
        {
            // Higher multiplier = Higher gravity (stronger attractive force)
            // Maximum value for 'MaxAcceleration' should be 50 
            // Object shaking occurs after the max value unless the 'space.TimeStepSettings.TimeStepDuration' value is decreased
            gravField = new GravitationalField(
                new InfiniteForceFieldShape(), 
                settings.Position, 
                settings.GravitationalFieldStrength, 
                50
                );
            
            // Force entities in range to wake up
            gravField.ForceWakeUp = true;

            game.Space.Add(gravField);
        }
How can I get the GravitationalField class to ignore the dynamic entity associated with it in the GravitationalFieldPrimitive class?

This is not normally a problem if the associated entity is kinematic but it needs to be ignored when the associated entity is dynamic.

Re: 'GravitationalField' - How do I get the field to ignore?

Posted: Fri Jun 01, 2012 3:02 pm
by Norbo
A custom shape could be used. Here's the code from the infinite shape:

Code: Select all

    /// <summary>
    /// Defines the area in which a force field works using an entity's shape.
    /// </summary>
    public class InfiniteForceFieldShape : ForceFieldShape
    {
        /// <summary>
        /// Determines the possibly involved entities.
        /// </summary>
        /// <returns>Possibly involved entities.</returns>
        public override IList<Entity> GetPossiblyAffectedEntities()
        {
            return (ForceField as ISpaceObject).Space.Entities;
        }

        /// <summary>
        /// Determines if the entity is affected by the force field.
        /// </summary>
        /// <param name="testEntity">Entity to test.</param>
        /// <returns>Whether the entity is affected.</returns>
        public override bool IsEntityAffected(Entity testEntity)
        {
            return true;
        }
    }
GetPossiblyAffectedEntities runs first to gather candidates. Since it's called from a single threaded context, keeping this fast can be important. The following IsEntityEffected allows fine grained checks to run on each candidate from a multithreaded context. So, you could override the IsEntityAffected method and check the testEntity against the followed entity.

Re: 'GravitationalField' - How do I get the field to ignore?

Posted: Fri Jun 01, 2012 3:26 pm
by Spankenstein
Thanks Norbo.

So something like this wouldn't be too bad an implementation I hope:

Code: Select all

        public override bool IsEntityAffected(Entity testEntity)
        {
            var o = testEntity.CollisionInformation.Tag as GravitationalFieldPrimitive;

            return o == null ? true : false;
        }
Also, the new version (1.2.0) is great! :)

Re: 'GravitationalField' - How do I get the field to ignore?

Posted: Fri Jun 01, 2012 3:30 pm
by Norbo
That would work; the cost of that method will likely be completely overwhelmed by everything else going on. If testing shows you need every nanosecond, changing it to a single direct entity equality test would probably be marginally faster (by avoiding a cast), but it almost certainly won't matter.
Also, the new version (1.2.0) is great!
Glad to hear it :)

Re: 'GravitationalField' - How do I get the field to ignore?

Posted: Fri Jun 01, 2012 4:08 pm
by Spankenstein
changing it to a single direct entity equality test would probably be marginally faster
Good point:

Code: Select all

    public class InfiniteForceFieldShapeCustom : ForceFieldShape
    {
        public Entity owner;

        public InfiniteForceFieldShapeCustom(Entity owner)
        {
            this.owner = owner;
        }

        /// <summary>
        /// Determines the possibly involved entities.
        /// </summary>
        /// <returns>Possibly involved entities.</returns>
        public override IList<Entity> GetPossiblyAffectedEntities()
        {
            return (ForceField as ISpaceObject).Space.Entities;
        }

        /// <summary>
        /// Determines if the entity is affected by the force field.
        /// </summary>
        /// <param name="testEntity">Entity to test.</param>
        /// <returns>Whether the entity is affected.</returns>
        public override bool IsEntityAffected(Entity testEntity)
        {
            //var o = testEntity.CollisionInformation.Tag as GravitationalFieldPrimitive;
            //return o == null ? true : false;

            return testEntity != owner;
        }
    }