# Bouncy

Dan Shiffman gave us several code examples of how to simulate springs and pendulums (pendula?). I was really stuck for ideas, and I thought it might be fun to stack some of them together. Somehow, all I could think of was one of those bouncy rubber bats that many people use for Halloween decorations. To do this, I put together a spring with a bob, and added a pendulum to each end of the bob. This was the result:

Main sketch code:

```[code lang="java"]//Kim Ash
//approximates a bouncy bat toy

Bob bob;
Spring spring;
//Pendulum p1, p2;

void setup()
{
size(640, 360);
smooth();
spring = new Spring(width/2,10,100);
bob = new Bob(width/2,100);

}

void draw()
{
background(199, 252,252);
// Apply a gravity force to the bob
PVector gravity = new PVector(0,1);
bob.applyForce(gravity);

// Connect the bob to the spring (this calculates the force)
spring.connect(bob);
// Constrain spring distance between min and max
spring.constrainLength(bob,30,200);
//springA.constraingLength(bob,30,200);

// Update bob
bob.update();
// If it's being dragged
bob.drag(mouseX,mouseY);

// Draw everything
spring.displayLine(bob); // Draw a line between spring and bob
bob.display();
spring.display();
bob.updatePendulum();

fill(255);
}

// For mouse interaction with bob

void mousePressed()  {
bob.clicked(mouseX,mouseY);
}

void mouseReleased()  {
bob.stopDragging();
}[/code]```

Bob class:

```[code lang="java"]
// Bob class, just like our regular Mover (location, velocity, acceleration, mass)

class Bob {
PVector location;
PVector velocity;
PVector acceleration;
float mass = 10;
Pendulum p1, p2;

// Arbitrary damping to simulate friction / drag
float damping = 0.98;

// For mouse interaction
PVector drag;
boolean dragging = false;

// Constructor
Bob(float x, float y) {
location = new PVector(x,y);
velocity = new PVector();
acceleration = new PVector();
drag = new PVector();
p1 = new Pendulum(new PVector(location.x + mass, location.y), 50, -PI/2);
p2 = new Pendulum(new PVector(location.x - mass, location.y), 50, PI/2);
}

void updatePendulum() {
p1.setOrigin(new PVector(location.x + mass, location.y));
p2.setOrigin(new PVector(location.x - mass, location.y));
}

// Standard Euler integration
void update() {
velocity.mult(damping);
acceleration.mult(0);
p1.update();
p2.update();
}

// Newton's law: F = M * A
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
}

// Draw the bob
void display() {
stroke(0);
fill(100);
if (dragging) {
fill(255);
}
ellipse(location.x,location.y,mass*2,mass*2);
p1.display();
p2.display();
}

// The methods below are for mouse interaction

// This checks to see if we clicked on the mover
void clicked(int mx, int my) {
float d = dist(mx,my,location.x,location.y);
if (d < mass) {
dragging = true;
drag.x = location.x-mx;
drag.y = location.y-my;
}
}

void stopDragging() {
dragging = false;
}

void drag(int mx, int my) {
if (dragging) {
location.x = mx + drag.x;
location.y = my + drag.y;
}
}
}[/code]```

Spring class:

```[code lang="java"]class Spring {

// Location
PVector anchor;

// Rest length and spring constant
float len;
float k = 0.1;

// Constructor
Spring(float x, float y, int l) {
anchor = new PVector(x,y);
len = l;
}

// Calculate spring force
void connect(Bob b) {
// Vector pointing from anchor to bob location
PVector force = PVector.sub(b.location,anchor);
// What is distance
float d = force.mag();
// Stretch is difference between current distance and rest length
float stretch = d - len;

// Calculate force according to Hooke's Law
// F = k * stretch
force.normalize();
force.mult(-1 * k * stretch);
b.applyForce(force);
}

// Constrain the distance between bob and anchor between min and max
void constrainLength(Bob b, float minlen, float maxlen) {
PVector dir = PVector.sub(b.location,anchor);
float d = dir.mag();
// Is it too short?
if (d < minlen) {
dir.normalize();
dir.mult(minlen);
// Reset location and stop from moving (not realistic physics)
b.velocity.mult(0);
// Is it too long?
} else if (d > maxlen) {
dir.normalize();
dir.mult(maxlen);
// Reset location and stop from moving (not realistic physics)
b.velocity.mult(0);
}
}

void display() {
fill(100);
rectMode(CENTER);
rect(anchor.x,anchor.y,10,10);
}

void displayLine(Bob b) {
stroke(0);
line(b.location.x,b.location.y,anchor.x,anchor.y);
}

}[/code]```

Pendulum class:

```[code lang="java"]class Pendulum  {

PVector location;    // Location of pendulum ball
PVector origin;      // Location of arm origin
float r;             // Length of arm
float angle;         // Pendulum arm angle
float aVelocity;     // Angle velocity
float aAcceleration; // Angle acceleration
float damping;       // Arbitary damping amount

// This constructor could be improved to allow a greater variety of pendulums
Pendulum(PVector origin_, float r_, float a) {
// Fill all variables
origin = origin_.get();
location = new PVector();
r = r_;
angle = a;

aVelocity = 0.0;
aAcceleration = 0.0;
damping = 0.995;   // Arbitrary damping
}

void go() {
update();
display();
}

// Function to update location
void update() {
float G = 0.4;                              // Arbitrary universal gravitational acceleration
aAcceleration = (-1 * G / r) * sin(angle);  // Calculate acceleration (see: http://www.myphysicslab.com/pendulum1.html)
aVelocity += aAcceleration;                 // Increment velocity
aVelocity *= damping;                       // Arbitrary damping
angle += aVelocity;                         // Increment angle
}

void display() {
location.set(r*sin(angle),r*cos(angle),0);         // Polar to cartesian conversion
location.add(origin);                              // Make sure the location is relative to the pendulum's origin

stroke(0);
// Draw the arm
line(origin.x,origin.y,location.x,location.y);
ellipseMode(CENTER);
fill(175);
// Draw the ball
ellipse(location.x,location.y,16,16);
}

void setOrigin(PVector v) {
origin.x = v.x;
origin.y = v.y;
}
}[/code]```