public GravMouse(LargeMapViewer2D picturebox, SimpleMap map, MyVector boundryLower, MyVector boundryUpper) { const double RADIUS = 400; _picturebox = picturebox; _map = map; _boundryLower = boundryLower; _boundryUpper = boundryUpper; _cursorBlip = new BallBlip(new Ball(new MyVector(), new DoubleVector(1, 0, 0, 0, 1, 0), RADIUS, UtilityCore.GetMassForRadius(RADIUS, 1d), 1, 0, 0, _boundryLower, _boundryUpper), CollisionStyle.Stationary, RadarBlipQual.BallUserDefined05, TokenGenerator.NextToken()); _picturebox.MouseDown += new MouseEventHandler(picturebox_MouseDown); _picturebox.MouseUp += new MouseEventHandler(picturebox_MouseUp); _picturebox.MouseMove += new MouseEventHandler(picturebox_MouseMove); _picturebox.MouseLeave += new EventHandler(picturebox_MouseLeave); }
protected void GetCollisionNormalAndPointsOfContact_SphereSphere(out MyVector normal, out double normalMagnitude, out MyVector pointOfContact1, out MyVector pointOfContact2, BallBlip ball1, BallBlip ball2) { // Vector that is perpendicular to the tangent of the collision, and it points in the direction of object 1. Real // easy when dealing with spheres :) normal = ball2.Ball.Position - ball1.Ball.Position; // Remember this length normalMagnitude = normal.GetMagnitude(); // This needs to be returned as a unit vector normal.Divide(normalMagnitude); // Start them off as unit vectors pointOfContact1 = normal.Clone(); pointOfContact2 = normal.Clone(); // Finish (use the ratio of their radii) pointOfContact1.Multiply((ball1.Ball.Radius / (ball1.Ball.Radius + ball2.Ball.Radius)) * normalMagnitude); pointOfContact2.Multiply((ball2.Ball.Radius / (ball1.Ball.Radius + ball2.Ball.Radius)) * normalMagnitude * -1); // I want this one pointing the other direction // Now that I have the points of contact relative to the centers of position, I need to make them // relative to the centers of mass if (ball1.TorqueBall != null) { pointOfContact1.Subtract(ball1.TorqueBall.CenterOfMass); } if (ball2.TorqueBall != null) { pointOfContact2.Subtract(ball2.TorqueBall.CenterOfMass); } }
protected void Collide_TorqueBallTorqueBall_2IsStationary(BallBlip ball1, BallBlip ball2) { // See if they're sitting directly on top of each other if (Utility3D.IsNearValue(ball1.Sphere.Position.X, ball2.Sphere.Position.X) && Utility3D.IsNearValue(ball1.Sphere.Position.Y, ball2.Sphere.Position.Y) && Utility3D.IsNearValue(ball1.Sphere.Position.Z, ball2.Sphere.Position.Z)) { // They're sitting directly on top of each other. Move them slightly away from each other ball2.Sphere.Position.X += .001; ball2.Sphere.Position.Y += .001; } // Get the collision normal and points of contact relative to the center of mass (assume they are spheres) MyVector normal, pointOfContact1, pointOfContact2; double normalMagnitude; GetCollisionNormalAndPointsOfContact_SphereSphere(out normal, out normalMagnitude, out pointOfContact1, out pointOfContact2, ball1, ball2); // ------------------------------ Calculate the impulse // ------------------------------ impulse = ( -(1+elasticity)(Va - Vb) dot Normal ) / ( Normal dot ((1/Ma) + (1/Mb))Normal + [a lot of rotation calculation]) #region Numerator // Figure out the velocities at the point of contact, which is linear + (angular x pointofcontact) MyVector velocity1 = MyVector.Cross(ball1.TorqueBall.AngularVelocity, pointOfContact1); velocity1.Add(ball1.Ball.Velocity); MyVector velocity2 = MyVector.Cross(ball2.TorqueBall.AngularVelocity, pointOfContact2); velocity2.Add(ball2.Ball.Velocity); MyVector contactVelocity = velocity1 - velocity2; double numerator = MyVector.Dot(contactVelocity, normal); // get the relative velocity dot normal numerator *= -1d * (1d + ((ball1.Ball.Elasticity + ball2.Ball.Elasticity) / 2d)); #endregion if (numerator > 0d) { // Technically, there's no collision return; } #region Denominator double sumOf1OverMass = (1d / ball1.Ball.Mass); // pretend ball2 has infinite mass, so 1 over infinity is zero // (inverse inertia tensor * (pointofcontact x normal)) x pointofcontact MyVector i1 = MyVector.Cross(pointOfContact1, normal); i1 = MyMatrix3.Multiply(ball1.TorqueBall.InertialTensorBodyInverse, i1); i1 = MyVector.Cross(i1, pointOfContact1); //TODO: may need to skip i2 if stationary (not rotatable) // (inverse inertia tensor * (pointofcontact x normal)) x pointofcontact MyVector i2 = MyVector.Cross(pointOfContact2, normal); i2 = MyMatrix3.Multiply(ball2.TorqueBall.InertialTensorBodyInverse, i2); i2 = MyVector.Cross(i2, pointOfContact2); double denominator = sumOf1OverMass + MyVector.Dot(i1, normal) + MyVector.Dot(i2, normal); #endregion double impulse = numerator / denominator; // ------------------------------ Calculate Linear Velocity // ------------------------------ velocity = Va + ( impulse / Ma )Normal // ------------------------------ velocity = Vb - ( impulse / Mb )Normal ball1.Ball.Velocity.Add(normal * (impulse / ball1.Ball.Mass)); //ball2.Ball.Velocity.Subtract(normal * (impulse / ball2.Ball.Mass)); // ------------------------------ Calculate Angular Velocity (collision) // For spheres with mass in the center, there will be no spin as a result of the collision (because the collision // normal points directly to the center). But if the center of mass is elsewhere, there will be a spin. MyVector deltaAngularMomentum = normal * impulse; deltaAngularMomentum = MyVector.Cross(pointOfContact1, deltaAngularMomentum); ball1.TorqueBall.AngularMomentum.Add(deltaAngularMomentum); if (ball2.CollisionStyle == CollisionStyle.StationaryRotatable) { deltaAngularMomentum = normal * (impulse * -1d); deltaAngularMomentum = MyVector.Cross(pointOfContact2, deltaAngularMomentum); ball2.TorqueBall.AngularMomentum.Add(deltaAngularMomentum); } #region Friction // The direction of friction must always be tangent to the collision normal, and in reverse of the sliding velocity. // It might be easier to think of a block sitting on a ramp. The normal of the collision with the ramp points toward // the block. The tangent of that is the surface of the ramp. If friction pointed anywhere but along the surface of // the ramp, the block would go airborne. // Figure out the direction of friction MyVector tangentDirection = contactVelocity - (normal * MyVector.Dot(normal, contactVelocity)); tangentDirection.BecomeUnitVector(); MyVector frictionDirection = tangentDirection * -1.0d; // See how much of the contact velocity is along the tangent double tangentSpeed = MyVector.Dot(tangentDirection, contactVelocity); // Figure out how much of an impulse it would take to exactly stop the objects double impulseToStop = GetImpulseForceMagnitudeFromDeltaVelocity(tangentSpeed, pointOfContact1, pointOfContact2, frictionDirection, sumOf1OverMass, ball1.TorqueBall.InertialTensorBodyInverse, ball2.TorqueBall.InertialTensorBodyInverse); // Take the average of the two object's static friction, and multiply by size of the normal double maxStaticFrictionForce = normalMagnitude * ((ball1.Ball.StaticFriction + ball2.Ball.StaticFriction) * .5d); MyVector frictionImpulse; // Figure out which friction coeficient to use if (maxStaticFrictionForce < impulseToStop) { // Use kinetic friction (slipping). Kinetic friction is always less than static. double kineticFrictionForce = normalMagnitude * ((ball1.Ball.KineticFriction + ball2.Ball.KineticFriction) * .5d); frictionImpulse = frictionDirection * kineticFrictionForce; } else { // Use static friction (not slipping). I don't want to multiply by maxStaticFrictionForce, because // that is too large. I want to use the value that will perfectly stop the objects frictionImpulse = frictionDirection * impulseToStop; } // ------------------------------ Apply Linear Velocity ball1.Ball.Velocity.Add(frictionImpulse * (1d / ball1.Ball.Mass)); //ball2.Ball.Velocity.Subtract(frictionImpulse * (1d / ball2.Ball.Mass)); // ------------------------------ Apply Angular Momentum ball1.TorqueBall.AngularMomentum.Add(MyVector.Cross(pointOfContact1, frictionImpulse)); if (ball2.CollisionStyle == CollisionStyle.StationaryRotatable) { ball2.TorqueBall.AngularMomentum.Subtract(MyVector.Cross(pointOfContact2, frictionImpulse)); } #endregion }
protected void Collide_BallBall_2IsStationary(BallBlip ball1, BallBlip ball2) { // See if they're sitting directly on top of each other if (Utility3D.IsNearValue(ball1.Sphere.Position.X, ball2.Sphere.Position.X) && Utility3D.IsNearValue(ball1.Sphere.Position.Y, ball2.Sphere.Position.Y) && Utility3D.IsNearValue(ball1.Sphere.Position.Z, ball2.Sphere.Position.Z)) { // They're sitting directly on top of each other. Move them slightly away from each other ball2.Sphere.Position.X += .001; ball2.Sphere.Position.Y += .001; } // Vector that is perpendicular to the tangent of the collision, and it points in the direction of object 1. Real // easy when dealing with spheres :) MyVector normal = ball2.Ball.Position - ball1.Ball.Position; // ------------------------------ Calculate the impulse // ------------------------------ impulse = ( -(1+elasticity)(Va - Vb) dot Normal ) / ( Normal dot ((1/Ma) + (1/Mb))Normal) // Numerator MyVector temp = ball1.Ball.Velocity - ball2.Ball.Velocity; temp.Multiply(-1d * (1d + ((ball1.Ball.Elasticity + ball2.Ball.Elasticity) / 2d))); double numerator = MyVector.Dot(temp, normal); if (numerator > 0d) { // Technically, there's no collision return; } // Divisor temp = normal.Clone(); //temp.Multiply((1d / ball1.Ball.Mass) + (1d / ball2.Ball.Mass)); temp.Multiply(1d / ball1.Ball.Mass); // pretend ball2 has infinite mass, so 1 over infinity is zero double divisor = MyVector.Dot(normal, temp); // Impulse double impulse = numerator / divisor; // ------------------------------ Calculate the first object's new velocity // ------------------------------ velocity = Va + ( impulse / Ma )Normal ball1.Ball.Velocity.Add(normal * (impulse / ball1.Ball.Mass)); // ------------------------------ Calculate the second object's new velocity // ------------------------------ velocity = Vb - ( impulse / Mb )Normal //ball2.Ball.Velocity.Subtract(normal * (impulse / ball2.Ball.Mass)); // ball2 is stationary }
protected void PullItemsApartSpring_BallSphere(BallBlip ball, RadarBlip blip) { }
protected void PullItemsApartSpring_BallBall(BallBlip ball1, BallBlip ball2) { double sumRadii = ball1.Sphere.Radius + ball2.Sphere.Radius; // Get the vector from 2 to 1 MyVector move1From2 = ball1.Sphere.Position - ball2.Sphere.Position; double totalDistance = move1From2.GetMagnitude(); // distance from centers if (totalDistance > sumRadii) { return; } // Make this a unit vector move1From2.Divide(totalDistance); // Normally, it's f=kx, but I want x to always be from zero to one. So I'm really just finding the percent of // total velocity. double percent = 1d - (totalDistance / sumRadii); //TODO: Don't pull them both away at the same velocity, use the ratio of the masses move1From2.Multiply(_pullApartSpringVelocity * percent); //TODO: Instead of just adding directly to velocity, set it (but leave some of it there? dot product?) if (ball1.CollisionStyle == CollisionStyle.Standard) { ball1.Ball.Velocity.Add(move1From2); } if (ball2.CollisionStyle == CollisionStyle.Standard) { move1From2.Multiply(-1d); ball2.Ball.Velocity.Add(move1From2); } }
/// <summary> /// This ties this gun to a ship (null is an allowed value) /// </summary> public void SetShip(BallBlip ship) { _ship = ship; }
private void btnAddRigidBody_Click(object sender, EventArgs e) { const int MINPOINTMASSES = 3; const int MAXPOINTMASSES = 8; const double MINPOINTMASSRADIUS = MINRADIUSMASS / MINPOINTMASSES; const double MAXPOINTMASSRADIUS = MAXRADIUSMASS / MAXPOINTMASSES; // Make the chassis RigidBody ball = new RigidBody(Utility3D.GetRandomVector(_boundryLower, _boundryUpper), new DoubleVector(0, -1, 0, -1, 0, 0), .1d, GetElasticity(), 1, 1, _boundryLower, _boundryUpper); int numPointMasses = _rand.Next(MINPOINTMASSES, MAXPOINTMASSES + 1); //double maxOffset = MAXRADIUSMASS - ((MINPOINTMASSRADIUS + MAXPOINTMASSRADIUS) / 2d); // this could result in bodies slightly larger than the other two types, but it should be close double maxOffset = MAXRADIUSMASS - MAXPOINTMASSRADIUS; double ballRadius = ball.Radius; double curRadius; // Add point masses for (int massCntr = 1; massCntr <= numPointMasses; massCntr++) { MyVector pointMassPos = Utility3D.GetRandomVectorSpherical(maxOffset); pointMassPos.Z = 0; // I do this here for the radius calculation below double pointMassMass = MINPOINTMASSRADIUS + (_rand.NextDouble() * (MAXPOINTMASSRADIUS - MINPOINTMASSRADIUS)); // Add a point mass ball.AddPointMass(pointMassPos.X, pointMassPos.Y, 0, pointMassMass); // See if this pushes out the ball's overall radius curRadius = pointMassPos.GetMagnitude() + pointMassMass; // I assume that the pointmass's mass is the same as its radius if (curRadius > ballRadius) { ballRadius = curRadius; } } // Store the new radius ball.Radius = ballRadius * 1.1d; // make it slightly bigger // Set the velocity ball.Velocity.Add(Utility3D.GetRandomVector(MAXVELOCITY)); ball.Velocity.Z = 0; BallBlip blip = new BallBlip(ball, CollisionStyle.Standard, RadarBlipQual.BallUserDefined02, TokenGenerator.NextToken()); _map.Add(blip); }
public static RadarBlip CloneBlip(RadarBlip blip, SimpleMap map) { BallBlip retVal = new BallBlip((Ball)blip.Sphere.Clone(), blip.CollisionStyle, blip.Qual, TokenGenerator.NextToken()); retVal.Ball.Velocity.StoreNewValues(((Ball)blip.Sphere).Velocity); if (blip.Sphere is TorqueBall) { ((TorqueBall)retVal.Sphere).AngularMomentum.StoreNewValues(((TorqueBall)blip.Sphere).AngularMomentum); } return retVal; }
private void TimerBalls() { #region Collide BallBlip collided1 = new BallBlip(_ball1.CloneBall(), CollisionStyle.Standard, RadarBlipQual.BallUserDefined00, 1); collided1.Ball.Velocity.StoreNewValues(_ball1.Velocity); BallBlip collided2 = new BallBlip(_ball2.CloneBall(), CollisionStyle.Standard, RadarBlipQual.BallUserDefined00, 2); collided2.Ball.Velocity.StoreNewValues(_ball2.Velocity); collided1.PrepareForNewCycle(); collided2.PrepareForNewCycle(); _collider.Collide(collided1, collided2); collided1.TimerTestPosition(1); collided2.TimerTestPosition(1); collided1.TimerFinish(); collided2.TimerFinish(); #endregion pictureBox1.PrepareForNewDraw(); #region Draw Balls // Ball1 pictureBox1.FillCircle(UtilityGDI.AlphaBlend(Color.Orange, Color.Silver, .25), _ball1.Position, _ball1.Radius); pictureBox1.DrawCircle(Color.DimGray, 1, _ball1.Position, _ball1.Radius); pictureBox1.DrawLine(Color.Yellow, 8, _ball1.Position, GetVelocityEnd(_ball1)); pictureBox1.DrawLine(Color.Black, 4, _ball1.Position, GetVelocityEnd(_ball1.Position, collided1.Ball)); if (_ball1 is TorqueBall) { pictureBox1.DrawLine(Color.White, 8, GetVelocityEnd(_ball1), GetAngularVelocityEnd((TorqueBall)_ball1)); pictureBox1.DrawLine(Color.Brown, 4, GetVelocityEnd(_ball1.Position, collided1.Ball), GetAngularVelocityEnd(_ball1.Position, collided1.TorqueBall)); } // Ball2 pictureBox1.FillCircle(UtilityGDI.AlphaBlend(Color.DodgerBlue, Color.Silver, .5), _ball2.Position, _ball2.Radius); pictureBox1.DrawCircle(Color.DimGray, 1, _ball2.Position, _ball2.Radius); pictureBox1.DrawLine(UtilityGDI.AlphaBlend(Color.White, Color.Navy, .8), 8, _ball2.Position, GetVelocityEnd(_ball2)); pictureBox1.DrawLine(Color.Black, 4, _ball2.Position, GetVelocityEnd(_ball2.Position, collided2.Ball)); if (_ball2 is TorqueBall) { pictureBox1.DrawLine(Color.White, 8, GetVelocityEnd(_ball2), GetAngularVelocityEnd((TorqueBall)_ball2)); pictureBox1.DrawLine(Color.Brown, 4, GetVelocityEnd(_ball2.Position, collided2.Ball), GetAngularVelocityEnd(_ball2.Position, collided2.TorqueBall)); } #endregion pictureBox1.FinishedDrawing(); }
private void CommitObject() { Ball newObject; #region Get the base object to add if (_drawingBall != null) { newObject = _drawingBall; _drawingBall = null; } else { newObject = BuildObject(); } #endregion RadarBlipQual blipQual; #region Figure out the blipqual //TODO: Define these as constants somewhere switch (_mode) { case AddingMode.AddBall: blipQual = RadarBlipQual.BallUserDefined00; break; case AddingMode.AddSolidBall: blipQual = RadarBlipQual.BallUserDefined01; break; case AddingMode.AddRigidBody: blipQual = RadarBlipQual.BallUserDefined02; break; default: throw new ApplicationException("Unknown AddingMode: " + _mode.ToString()); } #endregion // Create a blip to contain this object BallBlip blip = new BallBlip(newObject, _newBallProps.CollisionStyle, blipQual, TokenGenerator.NextToken()); // If this is a torqueball, then it will get the angular velocity. I have to wait until now, because // the size could change during a draw (you don't see it spin during the drag anyway, because I // don't call it's timer, so there is no reason to set angular velocity before now.) StoreAngularVelocity(blip.Ball); // Add it to the map _map.Add(blip); if (_newBallProps.Temporary) { _tempObjects.Add(blip.Token); } }
private void PropsChangedSprtNew() { MyVector position = null; // Kill Existing if (_ship != null) { position = _ship.Ball.Position.Clone(); _map.Remove(_ship.Token); _ship = null; } else { position = Utility3D.GetRandomVector(_boundryLower, _boundryUpper); } _tractorBeams.Clear(); _cannon = null; _machineGuns.Clear(); #region New Ship //TODO: Listen to global props double elasticity = .75d; double kineticFriction = .75d; double staticFriction = 1d; // Build New Ball newBall; RadarBlipQual blipQual; // logic came from BallAdder.CommitObject switch (_type) { case ShipTypeQual.None: return; case ShipTypeQual.Ball: #region Ball newBall = new Ball(position, new DoubleVector(0, 1, 0, 1, 0, 0), _shipSize, UtilityCore.GetMassForRadius(_shipSize, 1d), elasticity, kineticFriction, staticFriction, _boundryLower, _boundryUpper); blipQual = RadarBlipQual.BallUserDefined00; _thrustForce = GetThrustForce(newBall.Mass); _torqueballLeftRightThrusterForce = _thrustForce; #endregion break; case ShipTypeQual.SolidBall: #region Solid Ball newBall = new SolidBall(position, new DoubleVector(0, 1, 0, 1, 0, 0), _shipSize, UtilityCore.GetMassForRadius(_shipSize, 1d), elasticity, kineticFriction, staticFriction, _boundryLower, _boundryUpper); blipQual = RadarBlipQual.BallUserDefined01; _thrustForce = GetThrustForce(newBall.Mass); _torqueballLeftRightThrusterForce = GetLeftRightThrusterMagnitude(((SolidBall)newBall).InertialTensorBody); #endregion break; default: throw new ApplicationException("Unknown ShipTypeQual: " + _type.ToString()); } newBall.RotateAroundAxis(new MyVector(0, 0, 1), Math.PI); // Finish Building _ship = new BallBlip(newBall, CollisionStyle.Standard, blipQual, _blipToken); _map.Add(_ship); #endregion if (this.CreateNewTractorBeams != null) { this.CreateNewTractorBeams(this, new EventArgs()); } #region Guns _cannon = new ProjectileWeapon(300, 150, UtilityCore.GetMassForRadius(150, 1d), 25, true, _ignoreOtherProjectiles, RadarBlipQual.Projectile, false, _map, _boundryLower, _boundryUpper); _cannon.AddBarrel(_ship.Ball.OriginalDirectionFacing.Standard.Clone()); _cannon.AddFiringMode(20); _cannon.SetProjectileExplosion(450, 2, 10000); _cannon.SeProjectileFuse(500); _cannon.SetShip(_ship); for (int cntr = 0; cntr < 2; cntr++) { ProjectileWeapon weapon = new ProjectileWeapon(30, 20, UtilityCore.GetMassForRadius(20, 1d), 100, true, _ignoreOtherProjectiles, RadarBlipQual.Projectile, false, _map, _boundryLower, _boundryUpper); weapon.AddBarrel(new MyVector(), new MyQuaternion()); weapon.AddFiringMode(2); weapon.SetProjectileExplosion(40, 2, 300); weapon.SeProjectileFuse(500); weapon.SetShip(_ship); _machineGuns.Add(weapon); } #endregion }
public Interaction(BallBlip blip, MyVector forceDirection, double force) { this.Blip = blip; this.ForceDirection = forceDirection; this.Force = force; }
public TractorBeamCone(SimpleMap map, BallBlip ship, MyVector offset, DoubleVector dirFacing, BeamMode mode, bool isSoft, double sweepAngle, double maxDistance, double forceAtZero, double forceAtMax, double maxForcePerTick) { _map = map; _ship = ship; _offset = offset; _dirFacing = dirFacing; _mode = mode; _isSoft = isSoft; _sweepAngle = sweepAngle; _maxDistance = maxDistance; _forceAtZero = forceAtZero; _forceAtMax = forceAtMax; _maxForcePerTick = maxForcePerTick; }
private void AddMultiBall(double radius, double mass) { // Physical Ball MyVector pos = Utility3D.GetRandomVector(BOUNDRY); DoubleVector dirFacing = new DoubleVector(1, 0, 0, 0, 1, 0); Ball ball = new Ball(pos, dirFacing, radius, mass, ELASTICITY, KINETICFRICTION, STATICFRICTION, _boundryLower, _boundryUpper); BallBlip blip = new BallBlip(ball, CollisionStyle.Standard, RadarBlipQual.BallUserDefined00, TokenGenerator.NextToken()); _map.Add(blip); // WPF Rendering Geometry3D geometry = UtilityWPF.GetSphere(5, radius); Material material = new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(255, Convert.ToByte(_rand.Next(256)), Convert.ToByte(_rand.Next(256)), Convert.ToByte(_rand.Next(256))))); GeometryModel3D geometryModel = new GeometryModel3D(geometry, material); geometryModel.Transform = new Transform3DGroup(); //TODO: Tie this transform directly to the ball's velocity (the shpere class should take the transform group) Transform3DGroup group = geometryModel.Transform as Transform3DGroup; group.Children.Clear(); group.Children.Add(new TranslateTransform3D(pos.X, pos.Y, pos.Z)); _geometries.Add(geometryModel); _modelGroup.Children.Add(geometryModel); }
private void btnAddSolidBall_Click(object sender, EventArgs e) { double radius = _rand.Next(Convert.ToInt32(MINRADIUSMASS), Convert.ToInt32(MAXRADIUSMASS)); double mass = GetMass(radius); double elasticity = GetElasticity(); SolidBall ball = new SolidBall(Utility3D.GetRandomVector(_boundryLower, _boundryUpper), new DoubleVector(0, 1, 0, 1, 0, 0), radius, mass, elasticity, 1, 1, _boundryLower, _boundryUpper); ball.Velocity.Add(Utility3D.GetRandomVector(MAXVELOCITY)); ball.Velocity.Z = 0; BallBlip blip = new BallBlip(ball, CollisionStyle.Standard, RadarBlipQual.BallUserDefined01, TokenGenerator.NextToken()); _map.Add(blip); }
private void CollideSprtBallTorqueBall(BallBlip ballBlip1, BallBlip ballBlip2) { // Make a temp torqueball to use in place of ball1 BallBlip tempTorqueball = new BallBlip(new SolidBall(ballBlip1.Ball.Position, ballBlip1.Ball.OriginalDirectionFacing, ballBlip1.Ball.Radius, ballBlip1.Ball.Mass, ballBlip1.Ball.Elasticity, ballBlip1.Ball.KineticFriction, ballBlip1.Ball.StaticFriction, ballBlip1.Ball.BoundryLower, ballBlip1.Ball.BoundryUpper), ballBlip1.CollisionStyle, ballBlip1.Qual, ballBlip1.Token); tempTorqueball.Ball.Velocity.StoreNewValues(ballBlip1.Ball.Velocity); #region Treat them like solid balls if (ballBlip1.CollisionStyle == CollisionStyle.Standard) { if (ballBlip2.CollisionStyle == CollisionStyle.Standard) { // Two standard balls Collide_TorqueBallTorqueBall(tempTorqueball, ballBlip2); } else { // One is standard, two is stationary Collide_TorqueBallTorqueBall_2IsStationary(tempTorqueball, ballBlip2); } } else if (ballBlip2.CollisionStyle == CollisionStyle.Standard) { // One is stationary, two is standard Collide_TorqueBallTorqueBall_2IsStationary(ballBlip2, tempTorqueball); } // No need for an else. There is nothing to do (both are stationary) #endregion // Apply the changes that were made to the temp torqueball onto the ball1 ballBlip1.Ball.Velocity.StoreNewValues(tempTorqueball.Ball.Velocity); }
private void chkIncludeShip_CheckedChanged(object sender, EventArgs e) { const double THRUSTERANGLE = 75; if (chkIncludeShip.Checked) { if (_ship == null) { #region Create Ship // Set up the ship double radius = MINRADIUSMASS + (_rand.NextDouble() * (MAXRADIUSMASS - MINRADIUSMASS)); SolidBall ship = new SolidBall(Utility3D.GetRandomVector(_boundryLower, _boundryUpper), new DoubleVector(0, 1, 0, 1, 0, 0), radius, GetMass(radius), GetElasticity(), 1, 1, _boundryLower, _boundryUpper); // Set up the thrusters MyVector thrusterSeed = new MyVector(0, ship.Radius, 0); MyVector zAxis = new MyVector(0, 0, 1); // Bottom Thrusters _shipThrusterOffset_BottomRight = thrusterSeed.Clone(); _shipThrusterOffset_BottomRight.RotateAroundAxis(zAxis, Utility3D.GetDegreesToRadians(THRUSTERANGLE * -1)); _shipThrusterOffset_BottomLeft = thrusterSeed.Clone(); _shipThrusterOffset_BottomLeft.RotateAroundAxis(zAxis, Utility3D.GetDegreesToRadians(THRUSTERANGLE)); // Top Thrusters thrusterSeed = new MyVector(0, ship.Radius * -1, 0); _shipThrusterOffset_TopRight = thrusterSeed.Clone(); _shipThrusterOffset_TopRight.RotateAroundAxis(zAxis, Utility3D.GetDegreesToRadians(THRUSTERANGLE)); _shipThrusterOffset_TopLeft = thrusterSeed.Clone(); _shipThrusterOffset_TopLeft.RotateAroundAxis(zAxis, Utility3D.GetDegreesToRadians(THRUSTERANGLE * -1)); // Add to the map _ship = new BallBlip(ship, CollisionStyle.Standard, RadarBlipQual.BallUserDefined03, TokenGenerator.NextToken()); _map.Add(_ship); #endregion } } else { if (_ship != null) { _map.Remove(_ship.Token); _ship = null; } } }
/// <summary> /// This function pulls the items directly apart based on the ratio of their radii * mass /// </summary> protected void PullItemsApartInstant_BallBall(BallBlip ball1, BallBlip ball2) { // Get the vector from 2 to 1 MyVector move1From2 = ball1.Ball.Position - ball2.Ball.Position; double totalDistance = move1From2.GetMagnitude() * _pullApartInstantPercent; // distance from centers (exagerated by the percent passed in) double actualDistance = (ball1.Ball.Radius + ball2.Ball.Radius) - totalDistance; // distance from edges // Make this a unit vector move1From2.Divide(totalDistance); double ratio1 = (ball1.Ball.Radius * ball1.Ball.Mass) / ((ball1.Ball.Radius * ball1.Ball.Mass) + (ball2.Ball.Radius * ball2.Ball.Mass)); // Set their positions if (ball1.CollisionStyle == CollisionStyle.Standard) { ball1.Ball.Position.Add(move1From2 * (actualDistance * ratio1)); } if (ball2.CollisionStyle == CollisionStyle.Standard) { ball2.Ball.Position.Add(move1From2 * (actualDistance * (1d - ratio1) * -1d)); } }