//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;
}