Your browser does not support the canvas tag.

previous        Show / Hide Source        Download        next
//phillip dasilva-damaskin
//id = 991469514
//bouncing balls, aka infini bounce
//without conservation of force applied
//i couldnt implement noise() to anything useful

//start
void setup()
{
  size(400, 400);
  background(0);
  ellipseMode(CENTER);
  frameRate(60);

  //place the first ball at a random spot
  c1x = random(diameter / 2, 400 - diameter / 2);
  c1y = diameter;

  //then place the other balls relative to the first ball
  c2x = c1x + diameter / 2;
  c2y = c1y;
  c3x = c1x - diameter / 2;
  c3y = c1y;
  c4x = c1x;
  c4y = c1y + diameter / 2;
}

//variable spam
int diameter = 60;

//bounce effect
float b1 = 0f;
float b2 = 0f;
float b3 = 0f;
float b4 = 0f;

//distances between all objects
float d1to2 = 0;
float d1to3 = 0;
float d1to4 = 0;
float d2to3 = 0;
float d2to4 = 0;
float d3to4 = 0;

//red
float c1x = 150;
float c1y = 40;
float c1yv = 0;
float c1xv = 0;

//yellow
float c2x = 160;
float c2y = 40;
float c2yv = 0;
float c2xv = 0;

//green
float c3x = 250;
float c3y = 40;
float c3yv = 0;
float c3xv = 0;

//blue
float c4x = 300;
float c4y = 40;
float c4yv = 0;
float c4xv = 0;

//simulation settings
float gravity = 0.3;
float bounciness = 1;
float friction = 0.1;

//impact effects
float im1 = 0;
float im2 = 0;
float im3 = 0;
float im4 = 0;

//mouse drag states
boolean d1 = false;
boolean d2 = false;
boolean d3 = false;
boolean d4 = false;

//mouse offset variables
float mx = 0f;
float my = 0f;

void draw()
{
  background(0);

  drawBackground();
  drawHoldEffect();

  //impact effects
  //red
  fill(255, 48, 13, 255 - im1 * 2); 
  ellipse(c1x, c1y, im1, im1);
  //yellow
  fill(255, 207, 13, 255 - im2 * 2); 
  ellipse(c2x, c2y, im2, im2);
  //green
  fill(40, 255, 44, 255 - im3 * 2);
  ellipse(c3x, c3y, im3, im3);
  //blue
  fill(31, 85, 255, 255 - im4 * 2); 
  ellipse(c4x, c4y, im4, im4);

  //ball
  noStroke();
  //red
  fill(255 + b1, 48 + b1, 13 + b1);
  ellipse(c1x, c1y, diameter, diameter);
  //yellow
  fill(255 + b2, 207 + b2, 13 + b2); 
  ellipse(c2x, c2y, diameter, diameter);
  //green
  fill(40 + b3, 255 + b3, 44 + b3); 
  ellipse(c3x, c3y, diameter, diameter);
  //blue
  fill(31 + b4, 84 + b4, 255 + b4); 
  ellipse(c4x, c4y, diameter, diameter);

  calculateDistances();
  checkBounds();
  doGravity();
  addPositions();
  checkCollisions();
}

void drawBackground()
{
  //how many squares to draw per axis
  int div = 8;
  float sizeX = width / div;
  float sizeY = height / div;
  for(int x = 0; x < div;x++)
  {
    for(int y = 0; y < div;y++)
    {
      //checkered pattern
      //if the y value is even, then the x value will be 255 if x is odd
      //if the y value is odd, then the x value will be 255 if x is even
      
      int value = (y % 2 == 0) ? (x % 2 != 0) ? 35 : 0 : (x % 2 == 0) ? 35 : 0;
      fill(value, value, value);
      rect(x * sizeX, y * sizeY, sizeX, sizeY);
    }
  }
}

void drawHoldEffect()
{
  //draw a pulse effect on the ball thats being held
  if (d1 || d2 || d3 || d4)
  {
    float s = (sin(frameCount * 0.2) + 5) * 5;
    fill(255, 255, 255, 50);
    
    float hx = c1x;
    float hy = c1y;
    if(d2)
    {
      hx = c2x;
      hy = c2y;
    }
    else if(d3)
    {
      hx = c3x;
      hy = c3y;
    }
    else if(d4)
    {
      hx = c4x;
      hy = c4y;
    }
    
    ellipse(hx, hy, diameter + s, diameter + s);
  }
}

void calculateDistances()
{
  d1to2 = sqrt(sq(c2x - c1x) + sq(c2y - c1y));
  d1to3 = sqrt(sq(c3x - c1x) + sq(c3y - c1y));
  d1to4 = sqrt(sq(c4x - c1x) + sq(c4y - c1y));
  d2to3 = sqrt(sq(c3x - c2x) + sq(c3y - c2y));
  d2to4 = sqrt(sq(c4x - c2x) + sq(c4y - c2y));
  d3to4 = sqrt(sq(c4x - c3x) + sq(c4y - c3y));
}

void checkBounds()
{
  //ground collision for all balls
  if (c1y + diameter / 2 >= height)
  {
    c1yv *= -bounciness;
    c1y = height - (diameter / 2);
    im1 = diameter - 10;
    b1 = 80;
  }
  if (c2y + diameter / 2 >= height)
  {
    c2yv *= -bounciness;
    c2y = height - (diameter / 2);
    im2 = diameter - 10;
    b2 = 80;
  }
  if (c3y + diameter / 2 >= height)
  {
    c3yv *= -bounciness;
    c3y = height - (diameter / 2);
    im3 = diameter - 10;
    b3 = 80;
  }
  if (c4y + diameter / 2 >= height)
  {
    c4yv *= -bounciness;
    c4y = height - (diameter / 2);
    im4 = diameter - 10;
    b4 = 80;
  }

  //ceiling collisions
  if (c1y - diameter / 2 <= 0)
  {
    c1yv *= -bounciness;
    c1y = (diameter / 2);
    im1 = diameter - 10;
    b1 = 80;
  }
  if (c2y - diameter / 2 <= 0)
  {
    c2yv *= -bounciness;
    c2y = (diameter / 2);
    im2 = diameter - 10;
    b2 = 80;
  }
  if (c3y - diameter / 2 <= 0)
  {
    c3yv *= -bounciness;
    c3y = (diameter / 2);
    im3 = diameter - 10;
    b3 = 80;
  }
  if (c4y - diameter / 2 <= 0)
  {
    c4yv *= -bounciness;
    c4y = (diameter / 2);
    im4 = diameter - 10;
    b4 = 80;
  }

  //right wall collisions
  if (c1x + diameter / 2 >= width)
  {
    c1xv *= -bounciness;
    c1x = width - (diameter / 2);
    im1 = diameter - 10;
    b1 = 80;
  }
  if (c2x + diameter / 2 >= width)
  {
    c2xv *= -bounciness;
    c2x = width - (diameter / 2);
    im2 = diameter - 10;
    b2 = 80;
  }
  if (c3x + diameter / 2 >= width)
  {
    c3xv *= -bounciness;
    c3x = width - (diameter / 2);
    im3 = diameter - 10;
    b3 = 80;
  }
  if (c4x + diameter / 2 >=width)
  {
    c4xv *= -bounciness;
    c4x = width - (diameter / 2);
    im4 = diameter - 10;
    b4 = 80;
  }

  //left wall collisions
  if (c1x - diameter / 2 <= 0)
  {
    c1xv *= -bounciness;
    c1x = (diameter / 2);
    im1 = diameter - 10;
    b1 = 80;
  }
  if (c2x - diameter / 2 <= 0)
  {
    c2xv *= -bounciness;
    c2x = (diameter / 2);
    im2 = diameter - 10;
    b2 = 80;
  }
  if (c3x - diameter / 2 <= 0)
  {
    c3xv *= -bounciness;
    c3x = (diameter / 2);
    im3 = diameter - 10;
    b3 = 80;
  }
  if (c4x - diameter / 2 <= 0)
  {
    c4xv *= -bounciness;
    c4x = (diameter / 2);
    im4 = diameter - 10;
    b4 = 80;
  }
}

void mousePressed()
{
  //checks if a mouse is inside a ball
  //if it is, set the drag state for that ball to true
  //then stop the method execution
  
  float mto1 = sqrt(sq(c1x - mouseX) + sq(c1y - mouseY));
  if (mto1 < diameter)
  {
    d1 = true;
    return;
  }
  float mto2 = sqrt(sq(c2x - mouseX) + sq(c2y - mouseY));
  if (mto2 < diameter)
  {
    d2 = true;
    return;
  }
  float mto3 = sqrt(sq(c3x - mouseX) + sq(c3y - mouseY));
  if (mto3 < diameter)
  {
    d3 = true;
    return;
  }
  float mto4 = sqrt(sq(c4x - mouseX) + sq(c4y - mouseY));
  if (mto4 < diameter)
  {
    d4 = true;
    return;
  }
}

void mouseReleased()
{
  //when the mouse gets released, add some force to it
  //based on the mouse velocity
  float force = 2;

  if (d1)
  {
    c1yv = (mouseY - pmouseY) * force;
    c1xv = (mouseX - pmouseX) * force;
  }
  if (d2)
  {
    c2yv = (mouseY - pmouseY) * force;
    c2xv = (mouseX - pmouseX) * force;
  }
  if (d3)
  {
    c3yv = (mouseY - pmouseY) * force;
    c3xv = (mouseX - pmouseX) * force;
  }
  if (d4)
  {
    c4yv = (mouseY - pmouseY) * force;
    c4xv = (mouseX - pmouseX) * force;
  }

  d1 = false;
  d2 = false;
  d3 = false;
  d4 = false;
}

void checkCollisions()
{
  //this checks collisions between each of the balls
  //6 possible unique combinations
  
  float horizontalForce = 4;
  float verticalForce = 32;

  if (d1to2 < diameter)
  {
    //sets the bounce effect
    b1 = 80;
    b2 = 80;

    //sets the impact effect size
    im1 = diameter - 10;
    im2 = diameter - 10;
    
    //vector for calculating bounce direction
    //magnitude
    float l = sqrt(sq((c2x - c1x)) + sq((c2y - c1y)));
    //normalized x and y
    float dx = (c2x - c1x) / l;
    float dy = (c2y - c1y) / l;

    //sets the velocity of both balls to the opposite of the
    //bounce vector
    c1yv = -dy * bounciness * verticalForce;
    c1xv = -dx * bounciness * horizontalForce;

    c2yv = dy * bounciness * verticalForce;
    c2xv = dx * bounciness * horizontalForce;

    //clamps positions of both balls so they dont overlap
    c1x = c2x - ((diameter + 1) * dx);
    c1y = c2y - ((diameter + 1) * dy);

    c2x = c1x + ((diameter + 1) * dx);
    c2y = c1y + ((diameter + 1) * dy);
  }
  if (d1to3 < diameter)
  {
    b1 = 80;
    b3 = 80;

    im1 = diameter - 10;
    im3 = diameter - 10;
    float l = sqrt(sq((c3x - c1x)) + sq((c3y - c1y)));
    float dx = (c3x - c1x) / l;
    float dy = (c3y - c1y) / l;

    c1yv = -dy * bounciness * verticalForce;
    c1xv = -dx * bounciness * horizontalForce;

    c3yv = dy * bounciness * verticalForce;
    c3xv = dx * bounciness * horizontalForce;

    c1x = c3x - ((diameter + 1) * dx);
    c1y = c3y - ((diameter + 1) * dy);

    c3x = c1x + ((diameter + 1) * dx);
    c3y = c1y + ((diameter + 1) * dy);
  }
  if (d1to4 < diameter)
  {
    b1 = 80;
    b4 = 80;

    im1 = diameter - 10;
    im4 = diameter - 10;
    float l = sqrt(sq((c4x - c1x)) + sq((c4y - c1y)));
    float dx = (c4x - c1x) / l;
    float dy = (c4y - c1y) / l;

    c1yv = -dy * bounciness * verticalForce;
    c1xv = -dx * bounciness * horizontalForce;

    c4yv = dy * bounciness * verticalForce;
    c4xv = dx * bounciness * horizontalForce;

    c1x = c4x - ((diameter + 1) * dx);
    c1y = c4y - ((diameter + 1) * dy);

    c4x = c1x + ((diameter + 1) * dx);
    c4y = c1y + ((diameter + 1) * dy);
  }
  if (d2to3 < diameter)
  {
    b2 = 80;
    b3 = 80;

    im2 = diameter - 10;
    im3 = diameter - 10;
    float l = sqrt(sq((c3x - c2x)) + sq((c3y - c2y)));
    float dx = (c3x - c2x) / l;
    float dy = (c3y - c2y) / l;

    c2yv = -dy * bounciness * verticalForce;
    c2xv = -dx * bounciness * horizontalForce;

    c3yv = dy * bounciness * verticalForce;
    c3xv = dx * bounciness * horizontalForce;

    c2x = c3x - ((diameter + 1) * dx);
    c2y = c3y - ((diameter + 1) * dy);

    c3x = c2x + ((diameter + 1) * dx);
    c3y = c2y + ((diameter + 1) * dy);
  }
  if (d2to4 < diameter)
  {
    b2 = 80;
    b4 = 80;

    im2 = diameter - 10;
    im4 = diameter - 10;
    float l = sqrt(sq((c4x - c2x)) + sq((c4y - c2y)));
    float dx = (c4x - c2x) / l;
    float dy = (c4y - c2y) / l;

    c2yv = -dy * bounciness * verticalForce;
    c2xv = -dx * bounciness * horizontalForce;

    c4yv = dy * bounciness * verticalForce;
    c4xv = dx * bounciness * horizontalForce;

    c2x = c4x - ((diameter + 1) * dx);
    c2y = c4y - ((diameter + 1) * dy);

    c4x = c2x + ((diameter + 1) * dx);
    c4y = c2y + ((diameter + 1) * dy);
  }
  if (d3to4 < diameter)
  {
    b3 = 80;
    b4 = 80;

    im3 = diameter - 10;
    im4 = diameter - 10;
    float l = sqrt(sq((c4x - c3x)) + sq((c4y - c3y)));
    float dx = (c4x - c3x) / l;
    float dy = (c4y - c3y) / l;

    c3yv = -dy * bounciness * verticalForce;
    c3xv = -dx * bounciness * horizontalForce;

    c4yv = dy * bounciness * verticalForce;
    c4xv = dx * bounciness * horizontalForce;

    c3x = c4x - ((diameter + 1) * dx);
    c3y = c4y - ((diameter + 1) * dy);

    c4x = c3x + ((diameter + 1) * dx);
    c4y = c3y + ((diameter + 1) * dy);
  }
}

void addPositions()
{
  //checks if the ball is on the floor
  //if it is, then apply horizontal friction
  //to slow it down
  if (c1yv == 0 && c1y == height - diameter / 2)
  {
    c1xv *= 1 - friction;
  }
  if (c2yv == 0 && c2y == height - diameter / 2)
  {
    c2xv *= 1 - friction;
  }
  if (c3yv == 0 && c3y == height - diameter / 2)
  {
    c3xv *= 1 - friction;
  }
  if (c4yv == 0 && c4y == height - diameter / 2)
  {
    c4xv *= 1 - friction;
  }

  //if its being dragged, then set the position of the ball
  //to the mouse position
  //otherwise, apply the velocities to the positions
  if (d1)
  {
    c1x = mouseX;
    c1y = mouseY;
  }
  else
  {
    c1y += c1yv * gravity;
    c1x += c1xv;
  }

  if (d2)
  {
    c2x = mouseX;
    c2y = mouseY;
  }
  else
  {
    c2y += c2yv * gravity;
    c2x += c2xv;
  }

  if (d3)
  {
    c3x = mouseX;
    c3y = mouseY;
  }
  else
  {
    c3y += c3yv * gravity;
    c3x += c3xv;
  }

  if (d4)
  {
    c4x = mouseX;
    c4y = mouseY;
  }
  else
  {
    c4y += c4yv * gravity;
    c4x += c4xv;
  }
}

void doGravity()
{
  //increase the y velocity overtime, which makes the ball go down
  c1yv++;
  c2yv++;
  c3yv++;
  c4yv++;

  //increase the impact values
  im1 += 10;
  im2 += 10;
  im3 += 10;
  im4 += 10;
  
  //decrease the bounce values until its 0
  b1 -= 10;
  b2 -= 10;
  b3 -= 10;
  b4 -= 10;

  if (b1 < 0) b1 = 0;
  if (b2 < 0) b2 = 0;
  if (b3 < 0) b3 = 0;
  if (b4 < 0) b4 = 0;
}