Source: spring.js

/**
* Creates a Spring object. Consists of a spring with a block attached to the end.
* @constructor Spring
* @param {p5.Vector} position The origin of the Spring.
* @param {number} k Spring coefficient.
* @param  {number} m Mass of the block attached to the spring.
* @param  {number} lengthOfSpring Length of the Spring in px.
* @param  {number} oscAmp Amplitude of the oscillation.
* @param  {number} mu Coefficient of friction.

* @property {number} boxSize Length of the sides of the box attached to spring.
* @property {number} lengthOfSpring The current length of the spring in pixels.
* @property {number} noOfCoils The number of coils. Decorative. Odd numbers work best. (default: 11)
* @property {number} transAmp Transverse amplitude. Decorative. (default: 15)
* @property {number} tZero The start time in milliseconds.
* @property {number} t Time. (default: 0)
* @property {bool} playing Controls the state of the simulation.
* @property {number} xCent x-coord for the center of the spring.
* @property {number} yCent y-coord for the center of the spring.
* @property {radian} rotation Angle of orientation. Use 0 for a horizontal spring, and PI/2 for a vertical one.
* @property {number} oscamp  The oscillation amplitude as a fraction of the lengthOfSpring. A value of 0.2 is recommended as it will be 1/5 the length of the spring.

* @property {number} freq Calculates the frequency based on the spring constant k and the mass of the block m.
* @property {p5.Vector} equilibrium The equilibrium point.
* @property {p5.Vector} displacement The magnitude of displacement.
* @property {p5.Vector} velocity The velocity.
* @property {p5.Vector} acceleration The acceleration.
* @property Spring.update() {method} Updates the Spring object.
* @property Spring.display() {method} Displays the Spring object.


*/


/*spring*/
function Spring(pos_, k_, m_, lengthOfSpring_, oscAmp_,mu_) {
  boxsize = 70;
  //no of coils (purely decorative, odd numbers work better)
  this.noOfCoils = 11;
  //how long is the equilibrium length of the spring, in px
  this.lengthOfSpring = lengthOfSpring_;
  //the transverse amplitude (also purely decorative)
  this.transAmp = 15;
  //time variables
  this.tzero = millis();
  this.time = 0;
  this.play = true;
  //get the starting position of the spring.
  this.xcent = pos_.x;
  this.ycent = pos_.y;
  //how do we want it? horizontal (theta = 0), vertical? (theta = PI/2)
  this.rotation = 0;
  //how big should the oscillation amplitude be? (as a fraction of the lengthOfSpring. i.e 0.5 means it will have an Amplitude equal to half the length of the spring, which is kinda long. 0.2 works good)
  this.oscAmp = oscAmp_;
  //calculate the frequency based on the spring constant k and the mass of the block m
  //The second term in the sqrt accounts for the change in freq due to mu
  this.freq = sqrt(k_/m_- sq(mu_)/(4*sq(m_)));
  //friction coeff
  this.mu = mu_;
  //Mass
  this.m = m_;
  this.k = k_;


  //some kinematics values
  //where is equilibrium?
  this.equilibrium = createVector(this.lengthOfSpring, 0);
  //where is the mass?
  this.displacement = createVector(0, 0);
  //what is its velocity
  this.velocity = createVector(0, 0);
  //and its acceleration?
  this.acceleration = createVector(0, 0);

  //Function used to toggle animation
  this.setPlay = function(play_) {
    this.play=play_;
  }


this.update = function() {
  //Keep track of time
  if (this.play){
    //Animation is running so we update time
    this.time = millis()/1000-this.tzero;
  }
  else {
    //Animation pause "hold" time still
    this.tzero = millis()/1000-this.time;
  }
}

this.display = function() {

  push();
  //Calculate argument for sin and amplitude
  var theta = this.time * this.freq;
  var amp = this.oscAmp * exp((-1*this.mu*this.time)/(2*this.m));

  //Draw the mass at the end
  translate(this.xcent, this.ycent);
  rotate(this.rotation)
  fill(200);
  rect(this.lengthOfSpring - (boxsize / 2) + (this.lengthOfSpring - 60) * amp * sin(theta), -(boxsize / 2), boxsize, boxsize);
  noFill();
  stroke(80);
  strokeWeight(3);

  //Draw the spring
  beginShape();
  //cosmetic start
  curveVertex(-1, 0);
  curveVertex(0, 0);
  curveVertex(5, 0);
  curveVertex(20, 0);
  curveVertex(25, 0);
  //this part makes the coil
  for (var i = 0; i < this.lengthOfSpring - 60; i++) {
    curveVertex(30 + (i * (1 + amp * sin(theta))), -this.transAmp * sin(2 * PI * this.noOfCoils * i / this.lengthOfSpring));
  }
  //cosmetic end
  curveVertex(30 + (i * (1 + amp * sin(theta))) + 5, 0);
  curveVertex(30 + (i * (1 + amp * sin(theta))) + 20, 0);
  curveVertex(30 + (i * (1 + amp * sin(theta))) + 25, 0);
  curveVertex(30 + (i * (1 + amp * sin(theta))) + 30, 0);
  curveVertex(30 + (i * (1 + amp * sin((theta)))) + 31, 0);
  endShape();

  //update the kinematic variables
  this.displacement.x = this.equilibrium.x + ((this.lengthOfSpring-60) * amp * sin(theta));
  //TODO: Multiply Velocity and acceleration vals by actual Amplitude for final result
  this.velocity.x = sqrt(this.k/this.m) * amp * cos(theta);
  this.acceleration.x = -this.k/this.m * (amp * sin(theta));

  pop();
}
}