Exemplo n.º 1
0
        internal override void ActionCommand(Game game)
        {
            if (!IsRunning)
            {
                Entity  parentEntity = EntityCommanding.GetDataBlob <OrbitDB>().Parent;
                Vector2 newVector    = OrbitProcessor.InstantaneousOrbitalVelocityVector(EntityCommanding.GetDataBlob <OrbitDB>(), _db.ActionOnDateTime);
                newVector += _db.DeltaVToExpend_AU;
                var     spdmps      = Distance.AuToMt(newVector.Length());
                Vector3 newVector3d = new Vector3(newVector.X, newVector.Y, 0);
                OrbitDB newOrbit    = OrbitDB.FromVector(parentEntity, EntityCommanding, newVector3d, _db.ActionOnDateTime);

                /*
                 * if (newOrbit.Periapsis > targetSOI)
                 * {
                 *  //TODO: find who's SOI we're currently in and create an orbit for that;
                 * }
                 * if (newOrbit.Apoapsis > targetSOI)
                 * {
                 *  //TODO: change orbit to new parent at SOI change
                 * }
                 */


                EntityCommanding.SetDataBlob(newOrbit);
                newOrbit.SetParent(parentEntity);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Returns an orbit representing the defined parameters.
        /// </summary>
        /// <param name="semiMajorAxis_AU">SemiMajorAxis of orbit in AU.</param>
        /// <param name="eccentricity">Eccentricity of orbit.</param>
        /// <param name="inclination">Inclination of orbit in degrees.</param>
        /// <param name="longitudeOfAscendingNode">Longitude of ascending node in degrees.</param>
        /// <param name="argumentOfPeriapsis">Argument of periapsis in degrees.</param>
        /// <param name="meanAnomaly">Mean Anomaly in degrees.</param>
        /// <param name="epoch">reference time for these orbital elements.</param>
        public static OrbitDB FromAsteroidFormat([NotNull] Entity parent, double parentMass, double myMass, double semiMajorAxis_AU, double eccentricity, double inclination,
                                                 double longitudeOfAscendingNode, double argumentOfPeriapsis, double meanAnomaly, DateTime epoch)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }

            double sma_m = Distance.AuToMt(semiMajorAxis_AU);

            OrbitDB orbit = new OrbitDB(parent)
            {
                SemiMajorAxis       = sma_m,
                Eccentricity        = eccentricity,
                Inclination_Degrees = inclination,
                LongitudeOfAscendingNode_Degrees = longitudeOfAscendingNode,
                ArgumentOfPeriapsis_Degrees      = argumentOfPeriapsis,
                MeanAnomalyAtEpoch_Degrees       = meanAnomaly,
                Epoch = epoch,

                _parentMass = parentMass,
                _myMass     = myMass
            };

            orbit.CalculateExtendedParameters();
            return(orbit);
        }
Exemplo n.º 3
0
        public static void StartNonNewtTranslation(Entity entity)
        {
            var moveDB       = entity.GetDataBlob <TranslateMoveDB>();
            var propulsionDB = entity.GetDataBlob <PropulsionAbilityDB>();
            var positionDB   = entity.GetDataBlob <PositionDB>();
            var maxSpeedMS   = propulsionDB.MaximumSpeed_MS;

            positionDB.SetParent(null);
            Vector3 targetPosMt       = Distance.AuToMt(moveDB.TranslateExitPoint_AU);
            Vector3 currentPositionMt = Distance.AuToMt(positionDB.AbsolutePosition_AU);

            Vector3 postionDelta  = currentPositionMt - targetPosMt;
            double  totalDistance = postionDelta.Length();

            double maxKMeters        = ShipMovementProcessor.CalcMaxFuelDistance_KM(entity);
            double fuelMaxDistanceMt = maxKMeters * 1000;

            if (fuelMaxDistanceMt >= totalDistance)
            {
                var currentVelocityMS = Vector3.Normalise(targetPosMt - currentPositionMt) * maxSpeedMS;
                propulsionDB.CurrentVectorMS       = currentVelocityMS;
                moveDB.CurrentNonNewtonionVectorMS = currentVelocityMS;
                moveDB.LastProcessDateTime         = entity.Manager.ManagerSubpulses.StarSysDateTime;

                CargoStorageDB storedResources = entity.GetDataBlob <CargoStorageDB>();
                foreach (var item in propulsionDB.FuelUsePerKM)
                {
                    var fuel = staticData.GetICargoable(item.Key);
                    StorageSpaceProcessor.RemoveCargo(storedResources, fuel, (long)(item.Value * totalDistance / 1000));
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Moves an entity while it's in a non newtonion translation state.
        /// TODO: doing this in meters will likely cause problems for ships that have a large position value.
        /// (position in meters could consevably go out of max value)
        /// </summary>
        /// <param name="entity">Entity.</param>
        /// <param name="deltaSeconds">Unused</param>
        public void ProcessEntity(Entity entity, int deltaSeconds)
        {
            var      manager           = entity.Manager;
            var      moveDB            = entity.GetDataBlob <TranslateMoveDB>();
            var      propulsionDB      = entity.GetDataBlob <PropulsionAbilityDB>();
            var      currentVelocityMS = moveDB.CurrentNonNewtonionVectorMS;
            DateTime dateTimeFrom      = moveDB.LastProcessDateTime;
            DateTime dateTimeNow       = manager.ManagerSubpulses.StarSysDateTime;
            DateTime dateTimeFuture    = dateTimeNow + TimeSpan.FromSeconds(deltaSeconds);

            double  deltaT            = (dateTimeFuture - dateTimeFrom).TotalSeconds;
            var     positionDB        = entity.GetDataBlob <PositionDB>();
            var     currentPositionAU = positionDB.AbsolutePosition_AU;
            Vector3 currentPositionMt = Distance.AuToMt(positionDB.AbsolutePosition_AU);

            Vector3 targetPosMt;

            targetPosMt = Distance.AuToMt(moveDB.TranslateExitPoint_AU);

            var deltaVecToTargetMt = currentPositionMt - targetPosMt;

            var newPositionMt = currentPositionMt + currentVelocityMS * deltaT;

            //var distanceToTargetAU = deltaVecToTargetAU.Length();  //in au
            var distanceToTargetMt = deltaVecToTargetMt.Length();

            //var deltaVecToTimeAU = currentPositionAU - TimePosAU;
            var positionDelta = currentPositionMt - newPositionMt;

            double distanceToMove = positionDelta.Length();


            if (distanceToTargetMt <= distanceToMove) // moving would overtake target, just go directly to target
            {
                newPositionMt = targetPosMt;
                positionDB.SetParent(moveDB.TargetEntity);
                //positionDB.AbsolutePosition_AU = Distance.MToAU(newPositionMt);//this needs to be set before creating the orbitDB
                positionDB.RelativePosition_AU = moveDB.TranslateRalitiveExit_AU;
                SetOrbitHere(entity, propulsionDB, positionDB, moveDB, dateTimeFuture);
            }
            else
            {
                positionDB.AbsolutePosition_AU = Distance.MToAU(newPositionMt);
            }


            moveDB.LastProcessDateTime = dateTimeFuture;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Returns an orbit representing the defined parameters.
        /// </summary>
        /// <param name="semiMajorAxis_AU">SemiMajorAxis of orbit in AU.</param>
        /// <param name="eccentricity">Eccentricity of orbit.</param>
        /// <param name="inclination">Inclination of orbit in degrees.</param>
        /// <param name="longitudeOfAscendingNode">Longitude of ascending node in degrees.</param>
        /// <param name="longitudeOfPeriapsis">Longitude of periapsis in degrees.</param>
        /// <param name="meanLongitude">Longitude of object at epoch in degrees.</param>
        /// <param name="epoch">reference time for these orbital elements.</param>
        public static OrbitDB FromMajorPlanetFormat([NotNull] Entity parent, double parentMass, double myMass, double semiMajorAxis_AU, double eccentricity, double inclination,
                                                    double longitudeOfAscendingNode, double longitudeOfPeriapsis, double meanLongitude, DateTime epoch)
        {
            if (parent == null)
            {
                throw new ArgumentNullException(nameof(parent));
            }

            // http://en.wikipedia.org/wiki/Longitude_of_the_periapsis
            double argumentOfPeriapsis = longitudeOfPeriapsis - longitudeOfAscendingNode;
            // http://en.wikipedia.org/wiki/Mean_longitude
            double meanAnomaly = meanLongitude - (longitudeOfAscendingNode + argumentOfPeriapsis);
            double sma_m       = Distance.AuToMt(semiMajorAxis_AU);

            return(new OrbitDB(parent, parentMass, myMass, sma_m, eccentricity, inclination, longitudeOfAscendingNode, argumentOfPeriapsis, meanAnomaly, epoch));
        }
Exemplo n.º 6
0
        void SetOrbitHere(Entity entity, PropulsionAbilityDB propulsionDB, PositionDB positionDB, TranslateMoveDB moveDB, DateTime atDateTime)
        {
            propulsionDB.CurrentVectorMS = new Vector3(0, 0, 0);

            double targetSOI = OrbitProcessor.GetSOI(moveDB.TargetEntity);

            Entity targetEntity;

            if (moveDB.TargetEntity.GetDataBlob <PositionDB>().GetDistanceTo(positionDB) > targetSOI)
            {
                targetEntity = moveDB.TargetEntity.GetDataBlob <OrbitDB>().Parent; //TODO: it's concevable we could be in another SOI not the parent (ie we could be in a target's moon's SOI)
            }
            else
            {
                targetEntity = moveDB.TargetEntity;
            }
            OrbitDB targetOrbit         = targetEntity.GetDataBlob <OrbitDB>();
            var     orbitalVector       = OrbitProcessor.GetOrbitalVector(targetOrbit, atDateTime);
            var     insertionVector2d   = OrbitProcessor.GetOrbitalInsertionVector(moveDB.SavedNewtonionVector_AU, targetOrbit, atDateTime);
            Vector3 parentOrbitalVector = new Vector3(orbitalVector.X, orbitalVector.Y, 0);
            Vector3 insertionVector     = new Vector3(insertionVector2d.X, insertionVector2d.Y, 0);

            insertionVector             += moveDB.ExpendDeltaV_AU; //TODO: only use it if we have it.
            propulsionDB.RemainingDV_MS -= (float)Distance.AuToMt(moveDB.ExpendDeltaV_AU).Length();
            OrbitDB newOrbit = OrbitDB.FromVector(targetEntity, entity, insertionVector, atDateTime);

            if (newOrbit.Periapsis > targetSOI)
            {
                //TODO: find who's SOI we're currently in and create an orbit for that;
            }
            if (newOrbit.Apoapsis > targetSOI)
            {
                //TODO: change orbit to new parent at SOI change
            }

            positionDB.SetParent(targetEntity);
            moveDB.IsAtTarget = true;
            entity.RemoveDataBlob <TranslateMoveDB>();
            entity.SetDataBlob(newOrbit);
            newOrbit.SetParent(targetEntity);
        }
Exemplo n.º 7
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;
        }