コード例 #1
0
        private void CalculateExtendedParameters()
        {
            if (IsStationary)
            {
                return;
            }
            // Calculate extended parameters.
            // http://en.wikipedia.org/wiki/Standard_gravitational_parameter#Two_bodies_orbiting_each_other
            GravitationalParameter   = GameConstants.Science.GravitationalConstant * (_parentMass + _myMass) / (1000 * 1000 * 1000); // Normalize GravitationalParameter from m^3/s^2 to km^3/s^2
            GravitationalParameterAU = GameConstants.Science.GravitationalConstant * (_parentMass + _myMass) / 3.347928976e33;       // (149597870700 * 149597870700 * 149597870700);
            // http://en.wikipedia.org/wiki/Orbital_period#Two_bodies_orbiting_each_other
            double orbitalPeriod = 2 * Math.PI * Math.Sqrt(Math.Pow(Distance.AuToKm(SemiMajorAxis), 3) / (GravitationalParameter));

            if (orbitalPeriod * 10000000 > long.MaxValue)
            {
                OrbitalPeriod = TimeSpan.MaxValue;
            }
            else
            {
                OrbitalPeriod = TimeSpan.FromSeconds(orbitalPeriod);
            }

            // http://en.wikipedia.org/wiki/Mean_motion
            MeanMotion = Math.Sqrt(GravitationalParameter / Math.Pow(Distance.AuToKm(SemiMajorAxis), 3)); // Calculated in radians.
            MeanMotion = Angle.ToDegrees(MeanMotion);                                                     // Stored in degrees.

            Apoapsis  = (1 + Eccentricity) * SemiMajorAxis;
            Periapsis = (1 - Eccentricity) * SemiMajorAxis;
        }
コード例 #2
0
        private void CalculateExtendedParameters()
        {
            if (IsStationary)
            {
                return;
            }
            // Calculate extended parameters.
            // http://en.wikipedia.org/wiki/Standard_gravitational_parameter#Two_bodies_orbiting_each_other
            GravitationalParameter_Km3S2 = GMath.GravitationalParameter_Km3s2(_parentMass + _myMass);  // Normalize GravitationalParameter from m^3/s^2 to km^3/s^2
            GravitationalParameterAU     = GMath.GrabitiationalParameter_Au3s2(_parentMass + _myMass); // (149597870700 * 149597870700 * 149597870700);
            GravitationalParameter_m3S2  = GMath.StandardGravitationalParameter(_parentMass + _myMass);

            double orbitalPeriod = 2 * Math.PI * Math.Sqrt(Math.Pow(Distance.AuToKm(SemiMajorAxis_AU), 3) / (GravitationalParameter_Km3S2));

            if (orbitalPeriod * 10000000 > long.MaxValue)
            {
                OrbitalPeriod = TimeSpan.MaxValue;
            }
            else
            {
                OrbitalPeriod = TimeSpan.FromSeconds(orbitalPeriod);
            }

            // http://en.wikipedia.org/wiki/Mean_motion
            MeanMotion_DegreesSec = Math.Sqrt(GravitationalParameter_Km3S2 / Math.Pow(Distance.AuToKm(SemiMajorAxis_AU), 3)); // Calculated in radians.
            MeanMotion_DegreesSec = Angle.ToDegrees(MeanMotion_DegreesSec);                                                   // Stored in degrees.

            Apoapsis_AU  = (1 + Eccentricity) * SemiMajorAxis_AU;
            Periapsis_AU = (1 - Eccentricity) * SemiMajorAxis_AU;

            SOI_m = OrbitMath.GetSOI(SemiMajorAxis, _myMass, _parentMass);
        }
コード例 #3
0
        internal static void FirstRun(Entity entity)
        {
            CargoTransferDB datablob = entity.GetDataBlob <CargoTransferDB>();

            double?dv;

            if (entity.HasDataBlob <OrbitDB>() && datablob.CargoToEntity.HasDataBlob <OrbitDB>())
            {
                dv = CalcDVDifferenceKmPerSecond(entity.GetDataBlob <OrbitDB>(), datablob.CargoToEntity.GetDataBlob <OrbitDB>());
            }
            else
            {
                OrbitDB orbitDB;
                if (entity.HasDataBlob <ColonyInfoDB>())
                {
                    orbitDB = entity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <OrbitDB>();
                }
                else//if (datablob.CargoToEntity.HasDataBlob<ColonyInfoDB>())
                {
                    orbitDB = datablob.CargoToEntity.GetDataBlob <ColonyInfoDB>().PlanetEntity.GetDataBlob <OrbitDB>();
                }
                dv = Distance.AuToKm(OrbitMath.MeanOrbitalVelocityInAU(orbitDB));
            }
            if (dv != null)
            {
                datablob.TransferRateInKG = CalcTransferRate((double)dv, datablob.CargoFromDB, datablob.CargoToDB);
            }
        }
コード例 #4
0
        /// <summary>
        /// Calculates the DVD ifference.
        /// </summary>
        /// <returns>The delaV Difference in Km/s, null if not in imediate orbit</returns>
        public static double?CalcDVDifferenceKmPerSecond(OrbitDB orbitDBFrom, OrbitDB orbitDBTo)
        {
            Entity toEntity = orbitDBTo.OwningEntity;
            double?dv       = null;

            if (orbitDBFrom.Parent == toEntity) //Cargo going up the gravity well
            {
                dv = OrbitMath.MeanOrbitalVelocityInAU(orbitDBFrom);
            }
            else if (orbitDBFrom.Children.Contains(toEntity)) //Cargo going down the gravity well
            {
                dv = OrbitMath.MeanOrbitalVelocityInAU(orbitDBTo);
            }
            else if (orbitDBFrom.Parent == toEntity.GetDataBlob <OrbitDB>().Parent) //cargo going between objects orbiting the same body
            {
                dv = Math.Abs(OrbitMath.MeanOrbitalVelocityInAU(orbitDBFrom) - OrbitMath.MeanOrbitalVelocityInAU(orbitDBTo));
            }

            if (dv == null)
            {
                return(dv);
            }
            else
            {
                return(Distance.AuToKm((double)dv));
            }
        }
コード例 #5
0
        /// <summary>
        /// Calculates the cartesian coordinates (relative to it's parent) of an orbit for a given angle.
        /// </summary>
        /// <param name="orbit">OrbitDB to calculate position from.</param>
        /// <param name="trueAnomaly">Angle in Radians.</param>
        public static Vector4 GetPosition(OrbitDB orbit, double trueAnomaly)
        {
            if (orbit.IsStationary)
            {
                return(new Vector4(0, 0, 0, 0));
            }

            // http://en.wikipedia.org/wiki/True_anomaly#Radius_from_true_anomaly
            double radius = Distance.AuToKm(orbit.SemiMajorAxis) * (1 - orbit.Eccentricity * orbit.Eccentricity) / (1 + orbit.Eccentricity * Math.Cos(trueAnomaly));

            // Adjust TrueAnomaly by the Argument of Periapsis (converted to radians)
            trueAnomaly += Angle.ToRadians(orbit.ArgumentOfPeriapsis);
            double inclination = Angle.ToRadians(orbit.Inclination);

            // Convert KM to AU
            radius = Distance.KmToAU(radius);

            //https://downloads.rene-schwarz.com/download/M001-Keplerian_Orbit_Elements_to_Cartesian_State_Vectors.pdf
            double lofAN = Angle.ToRadians(orbit.LongitudeOfAscendingNode);
            double aofP  = Angle.ToRadians(orbit.ArgumentOfPeriapsis);
            double tA    = trueAnomaly;
            double incl  = inclination;

            double x = Math.Cos(lofAN) * Math.Cos(aofP + tA) - Math.Sin(lofAN) * Math.Sin(aofP + tA) * Math.Cos(incl);
            double y = Math.Sin(lofAN) * Math.Cos(aofP + tA) + Math.Cos(lofAN) * Math.Sin(aofP + tA) * Math.Cos(incl);
            double z = Math.Sin(incl) * Math.Sin(aofP + tA);

            return(new Vector4(x, y, z, 0) * radius);
        }
コード例 #6
0
ファイル: GameMath.cs プロジェクト: UberWaffe/Pulsar4x
        /// <summary>
        /// This intercept only works if time to intercept is less than the orbital period.
        /// </summary>
        /// <returns>The ntercept.</returns>
        /// <param name="mover">Mover.</param>
        /// <param name="targetOrbit">Target orbit.</param>
        /// <param name="atDateTime">At date time.</param>
        public static (Vector3, TimeSpan) FTLIntercept(Entity mover, OrbitDB targetOrbit, DateTime atDateTime)
        {
            //OrbitDB targetOrbit = target.GetDataBlob<OrbitDB>();
            //PositionDB targetPosition = target.GetDataBlob<PositionDB>();
            //PositionDB moverPosition = mover.GetDataBlob<PositionDB>();

            OrbitDB moverOrbit   = mover.GetDataBlob <OrbitDB>();
            Vector3 moverPosInKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(moverOrbit, atDateTime));

            PropulsionAbilityDB moverPropulsion = mover.GetDataBlob <PropulsionAbilityDB>();

            Vector3 targetPosInKM = Distance.AuToKm((OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, atDateTime)));

            int speed = 25000;//moverPropulsion.MaximumSpeed * 100; //299792458;

            (Vector3, TimeSpan)intercept = (new Vector3(), TimeSpan.Zero);



            TimeSpan eti      = new TimeSpan();
            TimeSpan eti_prev = new TimeSpan();
            DateTime edi      = atDateTime;
            DateTime edi_prev = atDateTime;

            Vector3 predictedPosKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, edi_prev));
            double  distance       = (predictedPosKM - moverPosInKM).Length();

            eti = TimeSpan.FromSeconds((distance * 1000) / speed);

            int steps = 0;

            if (eti < targetOrbit.OrbitalPeriod)
            {
                double timeDifference     = double.MaxValue;
                double distanceDifference = timeDifference * speed;
                while (distanceDifference >= 1000)
                {
                    eti_prev = eti;
                    edi_prev = edi;

                    predictedPosKM = Distance.AuToKm(OrbitProcessor.GetAbsolutePosition_AU(targetOrbit, edi_prev));

                    distance = (predictedPosKM - moverPosInKM).Length();
                    eti      = TimeSpan.FromSeconds((distance * 1000) / speed);
                    edi      = atDateTime + eti;

                    timeDifference     = Math.Abs(eti.TotalSeconds - eti_prev.TotalSeconds);
                    distanceDifference = timeDifference * speed;
                    steps++;
                }
            }

            return(intercept);
        }
コード例 #7
0
        /// <summary>
        /// Creates on Orbit at current location from a given velocity
        /// </summary>
        /// <returns>The Orbit Does not attach the OrbitDB to the entity!</returns>
        /// <param name="parent">Parent.</param>
        /// <param name="entity">Entity.</param>
        /// <param name="velocityAU">Velocity.</param>
        public static OrbitDB FromVector(Entity parent, Entity entity, Vector3 velocityAU, DateTime atDateTime)
        {
            var parentMass = parent.GetDataBlob <MassVolumeDB>().Mass;
            var myMass     = entity.GetDataBlob <MassVolumeDB>().Mass;

            var epoch1 = parent.Manager.ManagerSubpulses.StarSysDateTime;                                      //getting epoch from here is incorrect as the local datetime doesn't change till after the subpulse.

            var parentPos = OrbitProcessor.GetAbsolutePosition_AU(parent.GetDataBlob <OrbitDB>(), atDateTime); //need to use the parent position at the epoch
            var posdb     = entity.GetDataBlob <PositionDB>();

            posdb.SetParent(parent);
            var ralitivePos = posdb.RelativePosition_AU;//entity.GetDataBlob<PositionDB>().AbsolutePosition_AU - parentPos;

            if (ralitivePos.Length() > OrbitProcessor.GetSOI(parent))
            {
                throw new Exception("Entity not in target SOI");
            }

            var sgp = GameConstants.Science.GravitationalConstant * (myMass + parentMass) / 3.347928976e33;
            var ke  = OrbitMath.KeplerFromPositionAndVelocity(sgp, ralitivePos, velocityAU, atDateTime);

            var epoch = atDateTime;// - TimeSpan.FromSeconds(ke.Epoch); //ke.Epoch is seconds from periapsis.

            OrbitDB orbit = new OrbitDB(parent, parentMass, myMass,
                                        Math.Abs(ke.SemiMajorAxis),
                                        ke.Eccentricity,
                                        Angle.ToDegrees(ke.Inclination),
                                        Angle.ToDegrees(ke.LoAN),
                                        Angle.ToDegrees(ke.AoP),
                                        Angle.ToDegrees(ke.MeanAnomalyAtEpoch),
                                        epoch);

            var pos = OrbitProcessor.GetPosition_AU(orbit, atDateTime);
            var d   = Distance.AuToKm(pos - ralitivePos).Length();

            if (d > 1)
            {
                var e = new Event(atDateTime, "Positional difference of " + d + "Km when creating orbit from velocity");
                e.Entity     = entity;
                e.SystemGuid = entity.Manager.ManagerGuid;
                e.EventType  = EventType.Opps;
                //e.Faction =  entity.FactionOwner;
                StaticRefLib.EventLog.AddEvent(e);

                //other info:
                var keta  = Angle.ToDegrees(ke.TrueAnomalyAtEpoch);
                var obta  = Angle.ToDegrees(OrbitProcessor.GetTrueAnomaly(orbit, atDateTime));
                var tadif = Angle.ToDegrees(Angle.DifferenceBetweenRadians(keta, obta));
                var pos1  = OrbitProcessor.GetPosition_AU(orbit, atDateTime);
                var pos2  = OrbitProcessor.GetPosition_AU(orbit, ke.TrueAnomalyAtEpoch);
                var d2    = Distance.AuToKm(pos1 - pos2).Length();
            }
            return(orbit);
        }
コード例 #8
0
        internal override void ActionCommand(Game game)
        {
            if (!IsRunning)
            {
                (Vector3 pos, DateTime eti)targetIntercept = InterceptCalcs.GetInterceptPosition(_entityCommanding, _targetEntity.GetDataBlob <OrbitDB>(), TransitStartDateTime, TargetOffsetPosition_AU);
                OrbitDB orbitDB    = _entityCommanding.GetDataBlob <OrbitDB>();
                Vector3 currentPos = OrbitProcessor.GetAbsolutePosition_AU(orbitDB, TransitStartDateTime);
                var     ralPos     = OrbitProcessor.GetPosition_AU(orbitDB, TransitStartDateTime);
                var     masses     = _entityCommanding.GetDataBlob <MassVolumeDB>().Mass + orbitDB.Parent.GetDataBlob <MassVolumeDB>().Mass;
                var     sgp        = GameConstants.Science.GravitationalConstant * masses / 3.347928976e33;

                //Vector4 currentVec = OrbitProcessor.PreciseOrbitalVector(sgp, ralPos, orbitDB.SemiMajorAxis);
                Vector2 currentVec = OrbitProcessor.GetOrbitalVector(orbitDB, TransitStartDateTime);
                _db = new TranslateMoveDB(targetIntercept.pos);
                _db.TranslateRalitiveExit_AU = TargetOffsetPosition_AU;
                _db.EntryDateTime            = TransitStartDateTime;
                _db.PredictedExitTime        = targetIntercept.eti;
                _db.TranslateEntryPoint_AU   = currentPos;
                _db.SavedNewtonionVector_AU  = currentVec;

                _db.ExpendDeltaV_AU = ExpendDeltaV;
                if (_targetEntity.HasDataBlob <SensorInfoDB>())
                {
                    _db.TargetEntity = _targetEntity.GetDataBlob <SensorInfoDB>().DetectedEntity;
                }
                else
                {
                    _db.TargetEntity = _targetEntity;
                }
                if (EntityCommanding.HasDataBlob <OrbitDB>())
                {
                    EntityCommanding.RemoveDataBlob <OrbitDB>();
                }
                EntityCommanding.SetDataBlob(_db);
                TranslateMoveProcessor.StartNonNewtTranslation(EntityCommanding);
                IsRunning = true;


                var distance   = (currentPos - targetIntercept.Item1).Length();
                var distancekm = Distance.AuToKm(distance);

                var time = targetIntercept.Item2 - TransitStartDateTime;

                double spd = _entityCommanding.GetDataBlob <PropulsionAbilityDB>().MaximumSpeed_MS;
                spd = Distance.MToAU(spd);
                var distb   = spd * time.TotalSeconds;
                var distbKM = Distance.AuToKm(distb);

                var dif = distancekm - distbKM;
                //Assert.AreEqual(distancekm, distbKM);
            }
        }
コード例 #9
0
        /// <summary>
        /// Creates orbit here using the current distance between the two entites as aphelion(furthest distance) and a given semiMajorAxis
        /// *NOTE BUG* this only returns a correct orbit DB if the position is y=0 and is +x (ie the position is in the reference direction)
        /// </summary>
        /// <returns>An OrbitDB. Does Not set DB to Entity.</returns>
        /// <param name="shipEntity">Ship entity.</param>
        /// <param name="parentEntity">The Entity to orbit</param>
        /// <param name="semiMajorAxsis">Largest Radius</param>
        public static OrbitDB CreateOrbitHereWithSemiMajAxis(Entity shipEntity, Entity parentEntity, double semiMajAxsisKM, DateTime time)
        {
            PositionDB parentPosition    = parentEntity.GetDataBlob <PositionDB>();
            PositionDB myPosition        = shipEntity.GetDataBlob <PositionDB>();
            double     parentMass        = parentEntity.GetDataBlob <MassVolumeDB>().Mass;
            double     myMass            = shipEntity.GetDataBlob <MassVolumeDB>().Mass;
            double     aphelionAU        = PositionDB.GetDistanceBetween(parentPosition, myPosition);
            double     semiMajAxisAU     = semiMajAxsisKM / GameConstants.Units.KmPerAu;
            double     linierEcentricity = aphelionAU - semiMajAxisAU;
            double     semiMinorAxsis    = Math.Sqrt(Math.Pow(semiMajAxisAU, 2) - Math.Pow(linierEcentricity, 2));
            double     ecentricity       = linierEcentricity / semiMajAxisAU;
            Vector3    ralitivePos       = myPosition.RelativePosition_AU;

            double  angle    = Math.Atan2(ralitivePos.Y, ralitivePos.X);
            var     theta    = Angle.ToDegrees(angle);
            OrbitDB newOrbit = OrbitDB.FromAsteroidFormat(parentEntity, parentMass, myMass, semiMajAxisAU, ecentricity, 0, 0, angle, angle, time);
            var     pos      = OrbitProcessor.GetPosition_AU(newOrbit, time);
            var     pos2     = Distance.AuToKm(pos);

            return(newOrbit);
        }
コード例 #10
0
 /// <summary>
 /// Calculates volume in Km^3 from a radius in Au.
 /// </summary>
 /// <param name="radius">Radius in AU</param>
 /// <returns>Volume_km3 in Km^3</returns>
 public static double CalculateVolume_Km3(double radius_au)
 {
     return((4.0 / 3.0) * Math.PI * Math.Pow(Distance.AuToKm(radius_au), 3));
 }
コード例 #11
0
        public static Entity CreateShip(Entity classEntity, EntityManager systemEntityManager, Entity ownerFaction, Entity parent, StarSystem starsys, string shipName = null)
        {
            Vector3 position           = parent.GetDataBlob <PositionDB>().AbsolutePosition_AU;
            var     distanceFromParent = parent.GetDataBlob <MassVolumeDB>().Radius * 2;

            position.X += distanceFromParent;
            Entity ship = CreateShip(classEntity, systemEntityManager, ownerFaction, position, starsys, shipName);

            ship.GetDataBlob <PositionDB>().SetParent(parent);
            var orbitDB = ShipMovementProcessor.CreateOrbitHereWithSemiMajAxis(ship, parent, Distance.AuToKm(distanceFromParent), systemEntityManager.ManagerSubpulses.StarSysDateTime);

            ship.SetDataBlob(orbitDB);

            return(ship);
        }
コード例 #12
0
        /// <summary>
        /// This was designed so that fast moving objects will get interpolated a lot more than slow moving objects
        /// so fast moving objects shouldn't loose positional acuracy when close to a planet,
        /// and slow moving objects won't have processor time wasted on them by calulcating too often.
        /// However this seems to be unstable and looses energy, unsure why. currently set it to just itterate/interpolate every second.
        /// so currently will be using more time to get through this than neccisary.
        /// </summary>
        /// <param name="entity">Entity.</param>
        /// <param name="deltaSeconds">Delta seconds.</param>
        public static void NewtonMove(Entity entity, int deltaSeconds)
        {
            NewtonMoveDB newtonMoveDB  = entity.GetDataBlob <NewtonMoveDB>();
            PositionDB   positionDB    = entity.GetDataBlob <PositionDB>();
            double       Mass_Kg       = entity.GetDataBlob <MassVolumeDB>().Mass;
            double       ParentMass_kg = newtonMoveDB.ParentMass;

            var      manager        = entity.Manager;
            DateTime dateTimeFrom   = newtonMoveDB.LastProcessDateTime;
            DateTime dateTimeNow    = manager.ManagerSubpulses.StarSysDateTime;
            DateTime dateTimeFuture = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds);
            double   deltaT         = (dateTimeFuture - dateTimeFrom).TotalSeconds;

            double secondsToItterate = deltaT;

            while (secondsToItterate > 0)
            {
                double speed_kms = newtonMoveDB.CurrentVector_kms.Length();


                //double timeStep = Math.Max(secondsToItterate / speed_kms, 1);
                //timeStep = Math.Min(timeStep, secondsToItterate);
                double timeStep           = 1;//because the above seems unstable and looses energy.
                double distanceToParent_m = Distance.AuToMt(positionDB.GetDistanceTo(newtonMoveDB.SOIParent.GetDataBlob <PositionDB>()));

                distanceToParent_m = Math.Max(distanceToParent_m, 0.1); //don't let the distance be 0 (once collision is in this will likely never happen anyway)

                double  gravForce       = GameConstants.Science.GravitationalConstant * (Mass_Kg * ParentMass_kg / Math.Pow(distanceToParent_m, 2));
                Vector3 gravForceVector = gravForce * -Vector3.Normalise(positionDB.RelativePosition_AU);
                double  distance        = Distance.AuToKm(positionDB.RelativePosition_AU).Length();
                Vector3 totalForce      = gravForceVector + newtonMoveDB.ThrustVector;

                Vector3 acceleration_mps = totalForce / Mass_Kg;
                Vector3 newVelocity      = (acceleration_mps * timeStep * 0.001) + newtonMoveDB.CurrentVector_kms;

                newtonMoveDB.CurrentVector_kms = newVelocity;
                Vector3 deltaPos = (newtonMoveDB.CurrentVector_kms + newVelocity) / 2 * timeStep;
                //Vector4 deltaPos = newtonMoveDB.CurrentVector_kms * timeStep;

                positionDB.RelativePosition_AU += Distance.KmToAU(deltaPos);

                double sOIRadius_AU = OrbitProcessor.GetSOI(newtonMoveDB.SOIParent);

                if (positionDB.RelativePosition_AU.Length() >= sOIRadius_AU)
                {
                    Entity  newParent;
                    Vector3 parentRalitiveVector;
                    //if our parent is a regular kepler object (normaly this is the case)
                    if (newtonMoveDB.SOIParent.HasDataBlob <OrbitDB>())
                    {
                        var orbitDB = newtonMoveDB.SOIParent.GetDataBlob <OrbitDB>();
                        newParent = orbitDB.Parent;
                        var parentVelocity = OrbitProcessor.InstantaneousOrbitalVelocityVector(orbitDB, entity.Manager.ManagerSubpulses.StarSysDateTime);
                        parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms) + parentVelocity;
                        var pvlen = Distance.AuToKm(parentVelocity.Length());
                        var vlen  = newtonMoveDB.CurrentVector_kms.Length();
                        var rvlen = Distance.AuToKm(parentRalitiveVector.Length());
                    }
                    else //if (newtonMoveDB.SOIParent.HasDataBlob<NewtonMoveDB>())
                    {   //this will pretty much never happen.
                        newParent = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().SOIParent;
                        var parentVelocity = newtonMoveDB.SOIParent.GetDataBlob <NewtonMoveDB>().CurrentVector_kms;
                        parentRalitiveVector = Distance.KmToAU(newtonMoveDB.CurrentVector_kms + parentVelocity);
                    }
                    double  newParentMass          = newParent.GetDataBlob <MassVolumeDB>().Mass;
                    double  sgp                    = GameConstants.Science.GravitationalConstant * (newParentMass + Mass_Kg) / 3.347928976e33;
                    Vector3 posRalitiveToNewParent = positionDB.AbsolutePosition_AU - newParent.GetDataBlob <PositionDB>().AbsolutePosition_AU;

                    var dateTime = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds - secondsToItterate);
                    var kE       = OrbitMath.KeplerFromPositionAndVelocity(sgp, posRalitiveToNewParent, parentRalitiveVector, dateTime);

                    if (kE.Eccentricity < 1) //if we're going to end up in a regular orbit around our new parent
                    {
                        /*
                         * var newOrbit = OrbitDB.FromKeplerElements(
                         *  newParent,
                         *  newParentMass,
                         *  Mass_Kg,
                         *  kE,
                         *  dateTime);
                         */
                        var newOrbit = OrbitDB.FromVector(newParent, entity, parentRalitiveVector, dateTime);
                        entity.RemoveDataBlob <NewtonMoveDB>();
                        entity.SetDataBlob(newOrbit);
                        positionDB.SetParent(newParent);
                        var currentPos = Distance.AuToKm(positionDB.RelativePosition_AU);
                        var newPos     = OrbitProcessor.GetPosition_AU(newOrbit, dateTime);
                        var newPosKM   = Distance.AuToKm(newPos);
                        positionDB.RelativePosition_AU = newPos;
                        break;
                    }
                    else //else we're in a hyperbolic trajectory around our new parent, so just coninue the newtonion move.
                    {
                        positionDB.SetParent(newParent);
                        newtonMoveDB.ParentMass = newParentMass;
                        newtonMoveDB.SOIParent  = newParent;
                    }
                }
                secondsToItterate -= timeStep;
            }
            newtonMoveDB.LastProcessDateTime = dateTimeFuture;
        }
コード例 #13
0
ファイル: MoveOrder.cs プロジェクト: johny5w/Pulsar4x
        // sets the speed of the ship to the maximum speed allowed in the direction of the target.
        // Returns true if the destination has been reached or the target no longer exists.
        public override bool processOrder()
        {
            double speedMultiplier = 1.0; //was this just for debugging? if so we should remove it, if not, then maybe move it to game settings?

            double     minimumDistance = 1000.0;
            PositionDB currentPosition = Owner.GetDataBlob <PositionDB>();
            PositionDB targetPosition = null;
            double     AUSpeed, kmSpeed;

            kmSpeed = Owner.GetDataBlob <PropulsionDB>().MaximumSpeed *speedMultiplier;
            AUSpeed = Distance.KmToAU(kmSpeed);

            currentPosition.SetParent(null);

            if (PositionTarget != null)
            {
                // just head straight towards the target position
                targetPosition = PositionTarget;

                // Assume that 1000 is extremely close,
                if (Distance.AuToKm(distanceBetweenPositions(currentPosition, targetPosition)) <= minimumDistance)
                {
                    setPositionToTarget(Owner, targetPosition);
                    Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = new Vector4(0, 0, 0, 0);
                    return(true);
                }
                else
                {
                    Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed);
                    return(false);
                }
            }
            else if (Target == null || Target == Entity.InvalidEntity) // Target no longer exists
            {
                return(true);
            }
            else
            {
                targetPosition = Target.GetDataBlob <PositionDB>();

                // Assume that 1000 is extremely close,
                if (Distance.AuToKm(distanceBetweenPositions(currentPosition, targetPosition)) <= minimumDistance)
                {
                    setPositionToTarget(Owner, targetPosition);

                    currentPosition.SetParent(Target);

                    return(true);
                }



                if (Target.HasDataBlob <OrbitDB>())
                {
                    if (Target.GetDataBlob <OrbitDB>().IsStationary)
                    {
                        // just head straight towards the target position
                        targetPosition = Target.GetDataBlob <PositionDB>();
                        Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed);
                    }
                    else
                    {
                        // TODO: Figure out an intercept based on OrbitProcessor.GetPosition
                        // for now, just head straight towards the target position

                        targetPosition = Target.GetDataBlob <PositionDB>();
                        Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed);
                        return(false);
                    }
                }

                else if (Target.HasDataBlob <PropulsionDB>())
                {
                    if (Target.GetDataBlob <PropulsionDB>().MaximumSpeed >= Owner.GetDataBlob <PropulsionDB>().MaximumSpeed)
                    // Target is faster than our ship, and cannot intercept
                    {
                        // Just head in a straight line
                        targetPosition = Target.GetDataBlob <PositionDB>();
                        Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed);
                    }
                    else
                    {
                        // Calculate an intercept
                        targetPosition = Target.GetDataBlob <PositionDB>();
                        Vector4 targetPos  = new Vector4(targetPosition.X, targetPosition.Y, targetPosition.Z, 0);
                        Vector4 currentPos = new Vector4(currentPosition.X, currentPosition.Y, currentPosition.Z, 0);
                        targetPos      = Find_collision_point(targetPos, Target.GetDataBlob <PropulsionDB>().CurrentSpeed, currentPos, AUSpeed);
                        targetPosition = new PositionDB(targetPos, targetPosition.SystemGuid);
                        Owner.GetDataBlob <PropulsionDB>().CurrentSpeed = getSpeed(currentPosition, targetPosition, kmSpeed);
                    }
                }
            }


            return(false);
        }