/// <summary> /// /// </summary> /// <param name="system"></param> /// <param name="emitter"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="minks">Minimum Spring Constant</param> /// <param name="maxks">Maximum Spring Constant</param> /// <param name="minkd">Minimum Dampening Constant</param> /// <param name="maxkd">Maximum Dampening Constant</param> /// <param name="minrest">Minimum Rest Length</param> /// <param name="maxrest">Maximum Rest Length</param> public Meatball(ParticleSystem system, Emitter emitter, double x, double y, double minks, double maxks, double minkd, double maxkd, double minrest, double maxrest, bool anchored) { // create thre particles mParticles[0] = new Particle(); mParticles[0].IsAnchor = anchored; // anchors the first particle if so desired mParticles[1] = new Particle(); mParticles[2] = new Particle(); // update the particles Update(emitter, x, y); // Create the spring between particles 0 and 1 Spring s = new Spring(); s.ThisParticle = mParticles[0]; s.ConnectedParticle = mParticles[1]; s.SpringConstant = ParticleSystem.random.NextDouble(minks, maxks); //1.0, 4.0); s.DampingConstant = ParticleSystem.random.NextDouble(minkd, maxkd); //0.10, 0.30); s.RestLength = ParticleSystem.random.NextDouble(minrest, maxrest); //1.0, 6.0); mParticles[0].Connections.Add(s); mParticles[1].Connections.Add(s); //system.Forces.Add(s); // Create the spring between particles 0 and 2 s = new Spring(); s.ThisParticle = mParticles[0]; s.ConnectedParticle = mParticles[2]; s.SpringConstant = ParticleSystem.random.NextDouble(minks, maxks); //1.0, 4.0); s.DampingConstant = ParticleSystem.random.NextDouble(minkd, maxkd); //0.10, 0.30); s.RestLength = ParticleSystem.random.NextDouble(minrest, maxrest); //1.0, 6.0); mParticles[0].Connections.Add(s); mParticles[2].Connections.Add(s); //system.Forces.Add(s); // Create the spring between particles 1 and 2 s = new Spring(); s.ThisParticle = mParticles[1]; s.ConnectedParticle = mParticles[2]; s.SpringConstant = ParticleSystem.random.NextDouble(minks, maxks); //1.0, 4.0); s.DampingConstant = ParticleSystem.random.NextDouble(minkd, maxkd); //0.10, 0.30); s.RestLength = ParticleSystem.random.NextDouble(minrest, maxrest); //1.0, 6.0); mParticles[1].Connections.Add(s); mParticles[2].Connections.Add(s); //system.Forces.Add(s); // Add the particles to the system system.Particles.Add(mParticles[0]); system.Particles.Add(mParticles[1]); system.Particles.Add(mParticles[2]); }
/// <summary> /// Calculate all the forces acting on a particle at a given time /// </summary> /// <param name="particle"></param> /// <param name="time"></param> /// <returns></returns> private Vector ComputeForces(Particle particle, double time) { // set all the forces for a particle at a time and position double forceX = (particle.Mass * Gravity.X) - (particle.Velocity.X * Drag.X); double forceY = (particle.Mass * Gravity.Y) - (particle.Velocity.Y * Drag.Y); // If there are spring force connections on this particle then for every connection update // the forces acting upon the particle if (particle.Connections.Count > 0) { foreach (Spring s in particle.Connections) { // apply the spring force Vector force = s.ApplyForce(particle); forceX += force.X; forceY += force.Y; } } // for every other force in the global list of forces, apply and update the force. foreach (Force f in Forces) { Vector force = f.ApplyForce(particle); forceX += force.X; forceY += force.Y; } return new Vector(forceX, forceY); // return the force vector. }
/// <summary> /// Update the particle /// </summary> /// <param name="particle"></param> public override void UpdateParticle(Particle particle) { base.UpdateParticle(particle); // Find a new x and corresponding y double x = ParticleSystem.random.NextDouble(X1, X2); particle.Position = new Point(x + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset), LinearEquation(x) + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset)); }
/// <summary> /// Add a particle to the system /// </summary> /// <param name="system"></param> /// <param name="particle"></param> public override void AddParticle(ParticleSystem system, Particle particle) { base.AddParticle(system, particle); // pick a random X between X1 and X2 // then get the corresponding y double x = ParticleSystem.random.NextDouble(X1, X2); particle.Position = new Point(x + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset), LinearEquation(x) + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset)); }
/// <summary> /// Add a particle to the system. /// </summary> /// <param name="system"></param> /// <param name="particle"></param> public override void AddParticle(ParticleSystem system, Particle particle) { base.AddParticle(system, particle); // overwrite the position based on the emitters X and Y position particle.Position = new Point(this.X + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset), this.Y + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset)); }
/// <summary> /// Update the particle /// </summary> /// <param name="particle"></param> public override void UpdateParticle(Particle particle) { base.UpdateParticle(particle); // Update the particles position particle.Position = new Point(this.X + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset), this.Y + ParticleSystem.random.NextDouble(MinPositionOffset, MaxPositionOffset)); }
/// <summary> /// Create a meatball which adds three particles with springs to the system. /// </summary> /// <param name="system"></param> /// <param name="particle"></param> public override void AddParticle(ParticleSystem system, Particle particle) { //base.AddParticle(system, particle); // ignore the base double x = ParticleSystem.random.NextDouble(X1, X2); Meatball meatball = new Meatball(system, this, x, LinearEquation(x), MinSpringConstant, MaxSpringConstant, MinDampeningConstant, MaxDampeningConstant, MinRestLength, MaxRestLength, true); // add each particle to the dictionary and its associated meatball. foreach (Particle p in meatball.Particles) { mMeatballs.Add(p, meatball); } }
/// <summary> /// Update the particle. Ignore the base and use the meatball update. /// </summary> /// <param name="particle"></param> public override void UpdateParticle(Particle particle) { //base.UpdateParticle(particle); double x = ParticleSystem.random.NextDouble(X1, X2); // Get the meatball this particle is a part of. ((Meatball)mMeatballs[particle]).Update(this, x, LinearEquation(x)); }
/// <summary> /// Used by the Particle System to apply a force vector to a particle. /// </summary> /// <param name="particle"></param> /// <returns></returns> public virtual Vector ApplyForce(Particle particle) { return new Vector(); }
/// <summary> /// Updates the particle by reinitializing its parameters. Used when a particle is first created and /// when a particle is resurrected. /// </summary> /// <param name="particle"></param> public virtual void UpdateParticle(Particle particle) { particle.Owner = this; particle.Mass = ParticleSystem.random.NextDouble(MinMass, MaxMass); particle.StartOpacity = this.StartOpacity; particle.EndOpacity = this.EndOpacity; particle.Force = new Vector(0, 0); particle.Velocity = new Vector( ParticleSystem.random.NextDouble(MinHorizontalVelocity, MaxHorizontalVelocity), ParticleSystem.random.NextDouble(MinVerticalVelocity, MaxVerticalVelocity)); particle.LifeSpan = ParticleSystem.random.NextDouble(MinLifeSpan, MaxLifeSpan); particle.BackgroundColors = this.ColorKeyFrames; }
/// <summary> /// Generates the particles for an emitter, called once at creation by the Particle System. /// </summary> /// <param name="system"></param> public virtual void GenerateParticles(ParticleSystem system) { // Init the particles for the emitter for (int i = 0; i < MaxParticles; i++) { Particle mParticle = new Particle(); UpdateParticle(mParticle); this.AddParticle(system, mParticle); system.Particles.Add(mParticle); } }
/// <summary> /// Method which is used to perform additional processing when adding a particle to the system for the /// first time. /// </summary> /// <param name="system"></param> /// <param name="particle"></param> public virtual void AddParticle(ParticleSystem system, Particle particle) { }
/// <summary> /// Apply the spring force to ThisParticle and the ConnectedParticle /// </summary> /// <param name="particle"></param> /// <returns></returns> public override Vector ApplyForce(Particle particle) { // The particle to apply the force to must be one if the two particles which // connects this spring if (ThisParticle.Equals(particle) || ConnectedParticle.Equals(particle)) { // if the particle is ThisParticle the the other particle is the ConnectedParticle and vice-versa Particle con = ConnectedParticle; if (ConnectedParticle.Equals(particle)) con = ThisParticle; // Calculate the change in position (x and y) for the particle and its connection double deltaX = particle.Position.X - con.Position.X; double deltaY = particle.Position.Y - con.Position.Y; // Calculate the change in velocity (x and y) for the particle and its connection double deltaVX = particle.Velocity.X - con.Velocity.X; double deltaVY = particle.Velocity.Y - con.Velocity.Y; // Calculate the x and y forces generate on the particle by the spring double fx1 = -(SpringConstant * (Math.Abs(deltaX) - RestLength) + DampingConstant * ((deltaVX * deltaX) / Math.Abs(deltaX))) * (deltaX / Math.Abs(deltaX)); double fy1 = -(SpringConstant * (Math.Abs(deltaY) - RestLength) + DampingConstant * ((deltaVY * deltaY) / Math.Abs(deltaY))) * (deltaY / Math.Abs(deltaY)); // The negative of that force is applied to the connected particle double fx2 = -fx1; double fy2 = -fy1; // Apply the negative force Vector cForce = con.Force; con.Force = new Vector(cForce.X + fx2, cForce.Y + fy2); // Return the spring force to be applied to this particle return new Vector(fx1, fy1); } else return new Vector(0, 0); }