Example #1
0
        private List <Interaction> GetInteractions_Static(out double totalForce, MyVector centerWorld, MyVector dirFacingWorld)
        {
            totalForce = 0d;
            List <Interaction> retVal = new List <Interaction>();


            // This is only used for left/right modes (lazy initialization)
            AngularVelocityInfo angularInfo = null;


            // Scan for objects in my path
            foreach (BallBlip blip in FindBlipsInCone(centerWorld, dirFacingWorld))
            {
                // Get a vector from me to the ball
                MyVector lineBetween = blip.Ball.Position - centerWorld;
                double   distance    = lineBetween.GetMagnitude();

                switch (_mode)
                {
                case BeamMode.PushPull:
                    #region Push Pull

                    if (!Utility3D.IsNearZero(distance))
                    {
                        lineBetween.BecomeUnitVector();
                        lineBetween.Multiply(-1);

                        double relativeVelocity = MyVector.Dot(lineBetween, blip.Ball.Velocity - _ship.Ball.Velocity);

                        // Figure out how much force is required to make this relative velocity equal zero
                        double force = relativeVelocity * blip.Ball.Mass;       // Velocity * Mass is impulse force

                        // See if force needs to be limited by the tractor's max force
                        double maxForce = UtilityCore.GetScaledValue(_forceAtZero, _forceAtMax, 0d, _maxDistance, distance);
                        if (Math.Abs(force) > maxForce)
                        {
                            if (force > 0d)
                            {
                                force = maxForce;
                            }
                            else
                            {
                                force = maxForce * -1d;
                            }
                        }

                        // Add to results
                        retVal.Add(new Interaction(blip, lineBetween, force));
                        totalForce += Math.Abs(force);
                    }

                    #endregion
                    break;

                case BeamMode.LeftRight:
                    #region Left Right

                    // Only do something if the lines aren't sitting directly on top of each other (even if they want to repel,
                    // I'd be hesitant to just repel in any random direction)
                    if (!Utility3D.IsNearValue(MyVector.Dot(lineBetween, dirFacingWorld, true), 1d))
                    {
                        // Figure out how fast the ship is spinning where the blip is
                        MyVector dirToCenterLine;
                        MyVector spinVelocity = GetSpinVelocityAtPoint(ref angularInfo, out dirToCenterLine, dirFacingWorld, lineBetween, blip.Ball.Position);

                        // Figure out the relative velocity (between blip and my spin)
                        double relativeVelocity1 = MyVector.Dot(dirToCenterLine, blip.Ball.Velocity - spinVelocity);

                        // Figure out how much force is required to make this relative velocity equal zero
                        double force1 = relativeVelocity1 * blip.Ball.Mass;       // Velocity * Mass is impulse force

                        // See if force needs to be limited by the tractor's max force
                        double maxForce1 = UtilityCore.GetScaledValue(_forceAtZero, _forceAtMax, 0d, _maxDistance, distance);
                        if (Math.Abs(force1) > maxForce1)
                        {
                            if (force1 > 0d)
                            {
                                force1 = maxForce1;
                            }
                            else
                            {
                                force1 = maxForce1 * -1d;
                            }
                        }

                        // Add to results
                        retVal.Add(new Interaction(blip, dirToCenterLine, force1));
                        totalForce += force1;
                    }

                    #endregion
                    break;

                default:
                    throw new ApplicationException("Unknown BeamMode: " + _mode.ToString());
                }
            }

            // Exit Function
            return(retVal);
        }
Example #2
0
        /// <summary>
        /// This method will adjust the force to keep the relative velocity relativaly small
        /// </summary>
        /// <remarks>
        /// This method needs work.  It would help if I exposed velocity and force lines to be drawn for debugging
        /// </remarks>
        private double GetForceForSoft(ref AngularVelocityInfo angularInfo, double maxForce, MyVector forceDirection, double distance, Ball ball, MyVector dirFacingWorld)
        {
            const double MINVELOCITY = 20d;

            double minVelocity = UtilityCore.GetScaledValue(0, MINVELOCITY, 0, _maxDistance, distance);

            MyVector dummy;
            MyVector tractorVelocity = GetSpinVelocityAtPoint(ref angularInfo, out dummy, dirFacingWorld, _offset, _ship.Ball.Position + _offset);

            tractorVelocity = tractorVelocity + _ship.Ball.Velocity;

            double relativeVelocity = MyVector.Dot(forceDirection, ball.Velocity - tractorVelocity);

            double retVal = maxForce;

            if (maxForce > 0)
            {
                #region Pulling In

                // Positive force means the relative velocity will need to be negative (pulling the object in)

                if (Utility3D.IsNearValue(relativeVelocity, minVelocity * -1d))
                {
                    // It's going the right speed.  No force needed
                    return(0);
                }
                else if (relativeVelocity < (minVelocity * -1d))
                {
                    // It's coming in too fast.  Slow it down
                    retVal = Math.Abs(relativeVelocity) - Math.Abs(minVelocity) * ball.Mass;   // Velocity * Mass is impulse force
                }

                #endregion
            }
            else
            {
                #region Pushing Away

                // Negative force means the relative velocity will need to be positive (pushing the object away)


                if (Utility3D.IsNearValue(relativeVelocity, minVelocity))
                {
                    // It's going the right speed.  No force needed
                    return(0);
                }
                else if (relativeVelocity > minVelocity)
                {
                    // It's going away too fast.  Slow it down
                    retVal = Math.Abs(relativeVelocity) - Math.Abs(minVelocity) * ball.Mass;   // Velocity * Mass is impulse force

                    retVal *= -1d;
                }



                //if (relativeVelocity > MINVELOCITY)
                //{
                //    // It's going fast enough, no need to apply any more force
                //    return 0;
                //}


                // Figure out how much force is required to make this relative velocity equal MINVELOCITY
                //retVal = (relativeVelocity - MINVELOCITY) * ball.Mass;   // Velocity * Mass is impulse force

                #endregion
            }

            // Cap the return the max force
            if (Math.Abs(retVal) > Math.Abs(maxForce))
            {
                if (retVal > 0)
                {
                    retVal = Math.Abs(maxForce);
                }
                else
                {
                    retVal = Math.Abs(maxForce) * -1d;
                }
            }

            // Exit Function
            return(retVal);
        }
Example #3
0
        private List <Interaction> GetInteractions_Standard(out double totalForce, MyVector centerWorld, MyVector dirFacingWorld)
        {
            totalForce = 0d;
            List <Interaction> retVal = new List <Interaction>();

            AngularVelocityInfo tractorAngularInfo = null;

            // Scan for objects in my path
            foreach (BallBlip blip in FindBlipsInCone(centerWorld, dirFacingWorld))
            {
                // Get the distance
                MyVector lineBetween = blip.Sphere.Position - centerWorld;
                double   distance    = lineBetween.GetMagnitude();

                // Figure out the force to apply
                double force = UtilityCore.GetScaledValue(_forceAtZero, _forceAtMax, 0d, _maxDistance, distance);
                force *= _percent;

                switch (_mode)
                {
                case BeamMode.PushPull:
                    #region Push Pull

                    if (!Utility3D.IsNearZero(distance))
                    {
                        // Turn lineBetween into a unit vector (it will be multiplied by force later)
                        lineBetween.BecomeUnitVector();

                        if (_isSoft)
                        {
                            force = GetForceForSoft(ref tractorAngularInfo, force, lineBetween, distance, blip.Ball, dirFacingWorld);
                        }

                        // Add this to the return list
                        retVal.Add(new Interaction(blip, lineBetween, force));
                        totalForce += Math.Abs(force);      // percent is negative when in repulse mode
                    }

                    #endregion
                    break;

                case BeamMode.LeftRight:
                    #region Left Right

                    // Only do something if the lines aren't sitting directly on top of each other (even if they want to repel,
                    // I'd be hesitant to just repel in any random direction)
                    if (!Utility3D.IsNearValue(MyVector.Dot(lineBetween, dirFacingWorld, true), 1d))
                    {
                        // Get a line that's orthogonal to lineBetween, and always points toward the dirFacingWorld vector
                        MyVector dirToCenterLine = MyVector.Cross(lineBetween, MyVector.Cross(lineBetween, dirFacingWorld));
                        dirToCenterLine.BecomeUnitVector();

                        // Add to the return list
                        retVal.Add(new Interaction(blip, dirToCenterLine, force));
                        totalForce += Math.Abs(force);      // percent is negative when in repulse mode
                    }

                    #endregion
                    break;

                default:
                    throw new ApplicationException("Unknown BeamMode: " + _mode.ToString());
                }
            }

            // Exit Function
            return(retVal);
        }