public GridFin(ISpaceCraft parent, DVector2 offset, int block, bool isLeft) : base(parent, GenerateTexturePath(block, isLeft)) { if (block == 6) { Width = 2.4; Height = 4.0; } else if (block == 5) { Width = 1.3; Height = 2.0; } else { Width = 1.2192; Height = 1.79806518; } DrawingOffset = 0.6; _isLeft = isLeft; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Constants.PiOverTwo; }
private void ComputeCachedProperties() { DVector2 difference = GravitationalParent.Position - Position; double totalDistance = difference.Length() - TotalHeight * 0.5; _cachedAltitude = totalDistance - GravitationalParent.SurfaceRadius; double altitude = GetRelativeAltitude(); if (altitude > GravitationalParent.AtmosphereHeight) { _cachedRelativeVelocity = Velocity - GravitationalParent.Velocity; } else { difference.Normalize(); var surfaceNormal = new DVector2(-difference.Y, difference.X); double altitudeFromCenter = altitude + GravitationalParent.SurfaceRadius; // Distance of circumference at this altitude ( c= 2r * pi ) double pathCirumference = 2 * Math.PI * altitudeFromCenter; double rotationalSpeed = pathCirumference / GravitationalParent.RotationPeriod; _cachedRelativeVelocity = Velocity - (GravitationalParent.Velocity + surfaceNormal * rotationalSpeed); } }
public static List <ISpaceCraft> BuildSpaceCraft(IMassiveBody planet, double surfaceAngle, MissionConfig config, string craftDirectory) { if (string.IsNullOrEmpty(config.VehicleType)) { throw new Exception("Must specify a vehicle type in the MissionConfig.xml!"); } if (string.IsNullOrEmpty(config.ParentPlanet)) { throw new Exception("Must specify a parent planet for the launch vehicle!"); } var planetOffset = new DVector2(Math.Cos(surfaceAngle) * planet.SurfaceRadius, Math.Sin(surfaceAngle) * planet.SurfaceRadius); List <ISpaceCraft> spaceCrafts = GenerateSpaceCraft(planet, config, craftDirectory); if (spaceCrafts.Count == 0) { throw new Exception("No spacecrafts produced!"); } ISpaceCraft primaryCraft = spaceCrafts[0]; DVector2 distanceFromSurface = primaryCraft.Position - planet.Position; // If the ship is spawned on the planet update it's position to the correct surface angle if (distanceFromSurface.Length() * 0.999 < planet.SurfaceRadius) { primaryCraft.SetSurfacePosition(planet.Position + planetOffset, surfaceAngle); } return(spaceCrafts); }
protected virtual void RenderAbove(Graphics graphics, Camera camera) { if (EntryFlame != null) { EntryFlame.Draw(graphics, camera); } // Only show the vectors when it's requested and the craft is not parented if (_showDisplayVectors && Parent == null) { // The length of the vector is based on the width of the camera bounds float lengthFactor = (float)(camera.Bounds.Width * 0.1); PointF start = RenderUtils.WorldToScreen(Position, camera.Bounds); DVector2 relativeVelocity = GetRelativeVelocity(); // Only draw the velocity vector when it can be normalized if (relativeVelocity.Length() > 0) { relativeVelocity.Normalize(); PointF velocityEnd = RenderUtils.WorldToScreen(Position + relativeVelocity * lengthFactor, camera.Bounds); graphics.DrawLine(Pens.White, start, velocityEnd); } DVector2 pitchVector = DVector2.FromAngle(Pitch); pitchVector.Normalize(); PointF pitchEnd = RenderUtils.WorldToScreen(Position + pitchVector * lengthFactor, camera.Bounds); graphics.DrawLine(Pens.Red, start, pitchEnd); } }
// Find the parent body for each massive body private void ResolveMassiveBodyParents() { foreach (IMassiveBody bodyA in _massiveBodies) { double bestMassDistanceRatio = double.MaxValue; foreach (IMassiveBody bodyB in _massiveBodies) { if (bodyA == bodyB) { continue; } double massRatio = Math.Pow(bodyA.Mass / bodyB.Mass, 0.45); DVector2 difference = bodyA.Position - bodyB.Position; double massDistanceRatio = massRatio * difference.Length(); // New parent if (massDistanceRatio < bestMassDistanceRatio) { bodyA.SetGravitationalParent(bodyB); bestMassDistanceRatio = massDistanceRatio; } } } }
public override void Update(double dt) { base.Update(dt); foreach (GridFin gridFin in _gridFins) { gridFin.Update(dt); } foreach (LandingLeg landingLeg in _landingLegs) { landingLeg.Update(dt); } DVector2 velocity = GetRelativeVelocity(); double altitude = GetRelativeAltitude(); DVector2 normalizedVelocity = velocity.Clone(); normalizedVelocity.Normalize(); DVector2 rotation = new DVector2(Math.Cos(Pitch), Math.Sin(Pitch)); // If we are going retro-grade and firing rockets adds soot if (altitude < 70000 && normalizedVelocity.Dot(rotation) < 0 && velocity.Length() > 400) { foreach (IEngine engine in Engines) { if (engine.IsActive && engine.Throttle > 0) { _sootRatio = Math.Min(_sootRatio + 0.015 * dt, 1.0); } } } }
public double GetRelativeHeight(DVector2 position) { DVector2 difference = Position - position; double totalDistance = difference.Length(); return(totalDistance - _proxy.SurfaceRadius); }
/// <summary> /// Gets the relative altitude of the spacecraft from it's parent's surface. /// </summary> public override double GetRelativeAltitude() { DVector2 difference = Position - GravitationalParent.Position; double totalDistance = difference.Length(); return(totalDistance - GravitationalParent.SurfaceRadius); }
public SSGridFin(ISpaceCraft parent, DVector2 offset, bool isLeft) : base(parent, GenerateTexturePath(isLeft)) { _isLeft = isLeft; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Constants.PiOverTwo; }
public LandingLeg(ISpaceCraft parent, DVector2 offset, int block, bool isLeft) : base(parent, GenerateTexturePath(block, isLeft)) { _isLeft = isLeft; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Constants.PiOverTwo; }
public NGLandingLeg(ISpaceCraft parent, DVector2 offset, bool isLeft) : base(parent, GenerateTexturePath(isLeft)) { _parent = parent; _isLeft = isLeft; _offsetLength = -offset.Length(); _offsetRotation = offset.Angle() + Math.PI / 2.0; }
public void AddPoint(DVector2 point, IMassiveBody parentBody, bool isPowered) { DVector2 offset = point - parentBody.Position; _trailAngles.Add(offset.Angle() - parentBody.Pitch); _trailDistances.Add(offset.Length()); _trailPowered.Add(isPowered); }
public DrogueChute(ISpaceCraft parent, DVector2 offset) { _parent = parent; _offsetLength = offset.Length(); _offsetRotation = _offsetRotation = offset.Angle() - Math.PI / 2.0; _texture = new Bitmap("Textures/Spacecrafts/Falcon/Common/drogueChute.png"); }
protected EngineBase(ISpaceCraft parent, DVector2 offset, EngineFlame flame) { _parent = parent; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Math.PI / 2.0; _engineFlame = flame; }
protected EngineBase(ISpaceCraft parent, DVector2 offset, Plume plume) { Parent = parent; Offset = offset; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Math.PI / 2.0; _plume = plume; }
public ReEntryFlame(int maxParticles, double particleRate, DVector2 offset) : base(maxParticles, Color.FromArgb(50, 255, 255, 0)) { _random = new Random(); _particleRate = particleRate; _offsetAngle = offset.Angle(); _offsetLength = offset.Length(); }
public LandingLeg(ISpaceCraft parent, DVector2 offset, bool isLeft) { _parent = parent; _isLeft = isLeft; _offsetLength = offset.Length(); _offsetRotation = _offsetRotation = offset.Angle() - Math.PI / 2.0; _texture = isLeft ? new Bitmap("Textures/landingLegLeft.png") : new Bitmap("Textures/landingLegRight.png"); }
public GridFin(ISpaceCraft parent, DVector2 offset, bool isLeft) { _parent = parent; _isLeft = isLeft; _offsetLength = offset.Length(); _offsetRotation = _offsetRotation = offset.Angle() - Math.PI / 2.0; _texture = isLeft ? new Bitmap("Textures/Spacecrafts/Falcon/Common/gridFinLeft.png") : new Bitmap("Textures/Spacecrafts/Falcon/Common//gridFinRight.png"); }
public void ResolveAtmopsherics(IMassiveBody body) { DVector2 difference = body.Position - Position; double distance = difference.Length(); difference.Normalize(); double altitude = distance - body.SurfaceRadius; // The object is in the atmosphere of body B if (altitude < body.AtmosphereHeight) { var surfaceNormal = new DVector2(-difference.Y, difference.X); double altitudeFromCenter = altitude + body.SurfaceRadius; // Distance of circumference at this altitude ( c= 2r * pi ) double pathCirumference = 2 * Math.PI * altitudeFromCenter; double rotationalSpeed = pathCirumference / body.RotationPeriod; // Simple collision detection if (altitude <= 0) { var normal = new DVector2(-difference.X, -difference.Y); Position = body.Position + normal * (body.SurfaceRadius); Velocity = (body.Velocity + surfaceNormal * rotationalSpeed); Rotation = normal.Angle(); AccelerationN.X = -AccelerationG.X; AccelerationN.Y = -AccelerationG.Y; } double atmosphericDensity = body.GetAtmosphericDensity(altitude); DVector2 relativeVelocity = (body.Velocity + surfaceNormal * rotationalSpeed) - Velocity; double velocityMagnitude = relativeVelocity.LengthSquared(); if (velocityMagnitude > 0) { relativeVelocity.Normalize(); // Drag ( Fd = 0.5pv^2dA ) DVector2 dragForce = relativeVelocity * (0.5 * atmosphericDensity * velocityMagnitude * DragCoefficient * CrossSectionalArea); AccelerationD += dragForce / Mass; } } }
protected StructureBase(DVector2 relativePosition, string texturePath, IMassiveBody parent) { _parent = parent; _initialDistance = relativePosition.Length(); _rotationOffset = relativePosition.Angle(); _initialRotation = parent.Rotation; _texture = new Bitmap(texturePath); }
public Skid(ISpaceCraft parent, DVector2 offset, bool isLeft) { _parent = parent; _isLeft = isLeft; _offsetLength = -offset.Length(); _offsetRotation = offset.Angle() + Math.PI / 2.0; _texture = isLeft ? new Bitmap("Textures/Spacecrafts/NewGlenn/landingLegLeft.png") : new Bitmap("Textures/Spacecrafts/NewGlenn/landingLegRight.png"); }
public Parachute(ISpaceCraft parent, DVector2 offset) { _parent = parent; _offsetLength = offset.Length(); _offsetRotation = offset.Angle(); //Pitch = -Math.PI / 2.0; Pitch = Math.PI / 2.0 + Math.PI / 12.0; _texture = new Bitmap("Textures/Spacecrafts/Falcon/Common/parachutes.png"); }
private void ResolveGravitionalParents() { // Find the parent body for each massive body foreach (IMassiveBody bodyA in _massiveBodies) { double bestMassDistanceRatio = double.MaxValue; foreach (IMassiveBody bodyB in _massiveBodies) { if (bodyA == bodyB) { continue; } double massRatio = Math.Pow(bodyA.Mass / bodyB.Mass, 0.45); DVector2 difference = bodyA.Position - bodyB.Position; double massDistanceRatio = massRatio * difference.Length(); // New parent if (massDistanceRatio < bestMassDistanceRatio) { bodyA.SetGravitationalParent(bodyB); bestMassDistanceRatio = massDistanceRatio; } } } // Find the parent for each space craft foreach (ISpaceCraft spaceCraft in _spaceCrafts) { double bestMassDistanceRatio = double.MaxValue; foreach (IMassiveBody bodyB in _massiveBodies) { double massRatio = Math.Pow(spaceCraft.Mass / bodyB.Mass, 0.45); DVector2 difference = spaceCraft.Position - bodyB.Position; double massDistanceRatio = massRatio * difference.Length(); // New parent if (massDistanceRatio < bestMassDistanceRatio) { spaceCraft.SetGravitationalParent(bodyB); bestMassDistanceRatio = massDistanceRatio; } } } }
// Finds the orbtial delta time step by assuming 200 points along the oribtal cirumference private static double GetOrbitalDt(DVector2 positon, DVector2 velocity, out double terminationRadius) { double orbitalAltitude = positon.Length(); double approximateOrbitDiameter = orbitalAltitude * 2 * Math.PI; // Terminate the trace if it comes within 1/100 of starting point terminationRadius = approximateOrbitDiameter * 0.01; double approximateOrbitPeriod = approximateOrbitDiameter / velocity.Length(); return(approximateOrbitPeriod * 0.005); }
public virtual void UpdateChildren(DVector2 position, DVector2 velocity) { Position = position - new DVector2(StageOffset.X * Math.Sin(Rotation) + StageOffset.Y * Math.Cos(Rotation), -StageOffset.X * Math.Cos(Rotation) + StageOffset.Y * Math.Sin(Rotation)); Velocity.X = velocity.X; Velocity.Y = velocity.Y; MachNumber = velocity.Length() * 0.0029411764; foreach (ISpaceCraft child in Children) { child.UpdateChildren(Position, Velocity); } }
public void Update(TimeStep timeStep, DVector2 enginePosition, DVector2 shipVelocity, DVector2 retrogradeVelocity, double density, double sootRatio) { int particles = (int)((sootRatio * shipVelocity.Length() * 0.001) / timeStep.UpdateLoops); if (density < 0.2 || density > 0.7) { particles = 0; } // Add new particles if nessecary for (int i = 0; i < particles; i++) { if (_availableParticles.Count > 0) { var randomUnitVector = new DVector2(_random.NextDouble(), _random.NextDouble()); DVector2 velocity = shipVelocity.Clone(); int id = _availableParticles.Dequeue(); Particle particle = _particles[id]; particle.IsActive = true; particle.Age = 0; particle.MaxAge = _random.NextDouble() + 1; particle.Position = enginePosition.Clone() + randomUnitVector * 2; particle.Velocity = velocity + retrogradeVelocity * 0.5 + randomUnitVector * 2; } } // Update the particles for (int i = 0; i < _particles.Length; i++) { Particle particle = _particles[i]; if (particle.IsActive) { particle.Position += particle.Velocity * timeStep.Dt; particle.Age += timeStep.Dt; if (particle.Age > particle.MaxAge) { particle.IsActive = false; _availableParticles.Enqueue(i); } } } }
public virtual void UpdateChildren(DVector2 position, DVector2 velocity) { var rotationOffset = new DVector2(Math.Cos(Pitch), Math.Sin(Pitch)); Position = position - new DVector2(StageOffset.X * rotationOffset.Y + StageOffset.Y * rotationOffset.X, -StageOffset.X * rotationOffset.X + StageOffset.Y * rotationOffset.Y); Velocity.X = velocity.X; Velocity.Y = velocity.Y; MachNumber = velocity.Length() * 0.0029411764; foreach (ISpaceCraft child in Children) { child.UpdateChildren(Position, Velocity); } }
public Parachute(ISpaceCraft parent, DVector2 offset, bool isLeft) { _parent = parent; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Math.PI / 2.0; if (isLeft) { _texture = new Bitmap("Textures/Spacecrafts/Falcon/Common/parachuteLeft.png"); } else { _texture = new Bitmap("Textures/Spacecrafts/Falcon/Common/parachuteRight.png"); } }
public Fin(ISpaceCraft parent, DVector2 offset, DVector2 size, double dihedral = 0.0, string texturePath = "Textures/Spacecrafts/ITS/Fin.png") : base(parent, texturePath) { _width = size.X; _height = size.Y; Width = _width; Height = _height; Dihedral = dihedral; DrawingOffset = 0.0; _offsetLength = offset.Length(); _offsetRotation = offset.Angle() - Constants.PiOverTwo; }
/// <summary> /// Traces a massive body orbit by re-centering the world around the parent. /// </summary> public static OrbitTrace TraceMassiveBody(MassiveBodyBase body) { IMassiveBody parent = body.GravitationalParent; DVector2 initialPosition = body.Position - parent.Position; var proxyParent = new MassiveBodyProxy(DVector2.Zero, DVector2.Zero, parent); var proxySatellite = new MassiveBodyProxy(initialPosition, body.Velocity - parent.Velocity, body); double orbitalTerminationRadius; double altitude = body.GetRelativeAltitude(); double orbitalDt = GetOrbitalDt(initialPosition, proxySatellite.Velocity, out orbitalTerminationRadius); var trace = new OrbitTrace(body.Position, altitude); for (int i = 0; i < 300; i++) { proxySatellite.ResetAccelerations(); proxySatellite.ResolveGravitation(proxyParent); proxySatellite.Update(orbitalDt); altitude = proxyParent.GetRelativeHeight(proxySatellite.Position); // Check expensive termination conditions after half of the iterations if (i > 150) { DVector2 offsetVector = proxySatellite.Position - initialPosition; double distanceFromStart = offsetVector.Length(); // Terminate and add the end point if (distanceFromStart < orbitalTerminationRadius) { trace.AddPoint(proxySatellite.Position + parent.Position, altitude); break; } } trace.AddPoint(proxySatellite.Position + parent.Position, altitude); } return(trace); }