TavisReddick
spinning-collisions-01
Sketch created in Processing 3 for Creative Coding course: Week 3: extend the spinning top sketch.
The code follows:
/*
* Creative Coding
* Week 3, 04
* extending spinning top: based on work
* by Indae Hwang and Jon McCormack
* Updated 2016
* Copyright (c) 2014-2016 Monash University
*
* Pool balls collide, spin and absorb each other.
*
*/
int num; // the number of items in the array
float[] ballX; // x-position of ball
float[] ballY; // y-position of ball
float[] ballSpeed; // speed of movement of ball
float[] ballDirection; // direction of movement of ball in radians
float[] ballSpin; // spin (rotation speed and direction) of ball
float[] ballBaseline; // baseline of spinning ball text
color[] ballColour; // colour of ball
int [] ballSize; // current radius of ball
int [] ballCollisionState; // 0 = waiting for collision; 1 = in collision
float entropyValue = 0.98; // fraction of 'energy' retained after collisions etc.
color backgroundColour = #000000;
color baizeColour = #46AA4A;
color tableColour = #C1953B;
color colourFrom = #FF0000; // starts colour range of balls
color colourTo = #0000FF; // ends colour range of balls
int tableHeight = 480;
int tableWidth = 360;
int tableEdgedepth = 30;
int ballRadius = 15;
float spinEffect = 1.1; // how much spin adds to bounce angles off side
int opacity = 50;
// dimension variables
int centreX;
int centreY;
int centreLeft;
int centreRight;
int centreTop;
int centreBottom;
void setup() {
size(400, 520);
// initialise dimension variables
centreX = width/2;
centreY = height/2;
centreLeft = width/2 - tableWidth/2 - tableEdgedepth/2;
centreRight = width/2 + tableWidth/2 + tableEdgedepth/2;
centreTop = height/2 - tableHeight/2 - tableEdgedepth/2;
centreBottom = height/2 + tableHeight/2 + tableEdgedepth/2;
num = 8; // number of balls
// allocate size of arrays
ballX = new float[num];
ballY = new float[num];
ballSpeed = new float[num];
ballDirection = new float[num];
ballSpin = new float[num];
ballBaseline = new float[num];
ballColour = new color[num];
ballSize = new int[num];
ballCollisionState = new int[num];
// initial position of ball 0 in the top half of the screen
ballX[0] = centreX;
ballY[0] = centreTop + 2 * tableEdgedepth;
ballSpeed[0] = random(8, 12);
ballDirection[0] = PI*9.0/20.0 + random(PI/10.0);
//ballDirection[0] = PI/2;
//ballDirection[0] = PI/4;
ballSpin[0] = random(PI) - PI/2;
ballBaseline[0] = 0.0;
ballColour[0] = #FFFFFF;
ballSize[0] = ballRadius;
ballCollisionState[0] = 0;
// initialise positions of rest of balls
for (int i = 1; i < ballX.length; i++) {
ballX[i] = random(centreLeft + 2 * tableEdgedepth, centreRight - 2 * tableEdgedepth);
ballY[i] = random(centreTop + 4 * tableEdgedepth, centreBottom - 2 * tableEdgedepth);
ballSpeed[i] = 0.0;
ballDirection[i] = 0.0;
ballSpin[i] = 0.0;
ballBaseline[i] = 0.0;
ballColour[i] = lerpColor(colourFrom, colourTo, (i - 1.0)/(num - 2.0));
ballSize[i] = ballRadius;
ballCollisionState[i] = 0;
}
// draw background objects
background(0);
noStroke();
rectMode(CENTER);
fill(baizeColour);
rect(centreX, centreY, tableWidth - tableEdgedepth, tableHeight - tableEdgedepth);
fill(tableColour);
rect(centreLeft, centreY, tableEdgedepth, tableHeight); //left
rect(centreRight, centreY, tableEdgedepth, tableHeight); //right
rect(centreX, centreTop, tableWidth, tableEdgedepth); //top
rect(centreX, centreBottom, tableWidth, tableEdgedepth); //bottom
// text settings
textSize(ballRadius);
textAlign(CENTER, CENTER);
}
void draw() {
// blend the old frames into the background
blendMode(BLEND);
stroke(0, opacity);
// draw balls
for (int i = 0; i 0.0) {
fill(ballColour[i], opacity);
ellipse(ballX[i], ballY[i], ballSize[i], ballSize[i]);
translate(ballX[i], ballY[i]);
rotate(ballBaseline[i]);
fill(0, opacity);
textSize(ballSize[i]);
text(i, 0, 0);
resetMatrix();
}
}
// move balls
for (int i = 0; i < ballX.length; i++) {
float dx = cos(ballDirection[i]) * ballSpeed[i];
float dy = sin(ballDirection[i]) * ballSpeed[i];
ballX[i] += dx;
ballY[i] += dy;
}
// collision detection
// with sides
for (int i = 0; i < ballX.length; i++) {
if (ballX[i] centreRight - tableEdgedepth) {
ballDirection[i] = (-1 * PI - ballDirection[i]) * spinEffect;
}
if (ballY[i] centreBottom - tableEdgedepth) {
ballDirection[i] = (-1 * ballDirection[i]) * spinEffect;
}
}
// with other balls
for (int i = 0; i < ballX.length; i++) {
for (int j = 0; j < ballX.length; j++) {
if (i != j) { // a ball cannot collide with itself
if (dist(ballX[i], ballY[i], ballX[j], ballY[j]) <= ballRadius) {
if (ballCollisionState[i] == 0 && ballCollisionState[j] == 0) {
ballCollisionState[i] = 1;
ballCollisionState[j] = 1;
ballCollision(i, j);
}
} else {
ballCollisionState[i] = 0;
}
}
}
}
// spin balls
for (int i = 0; i ballSpeed[ball2] ? ball1 : ball2;
int loser = winner == ball1 ? ball2 : ball1;
ballSpeed[winner] = ballSpeed[ball1] + ballSpeed[ball2] * entropyValue;
ballSpeed[loser] = 0.0;
ballDirection[winner] = (ballDirection[ball1] + ballDirection[ball2] / 2) / PI;
float r1 = ballSize[ball1];
float r2 = ballSize[ball2];
ballSize[winner] = (int) sqrt(sq(r1) + sq(r2));
ballSize[loser] = 0;
ballColour[winner] = lerpColor(ballColour[winner], ballColour[loser], 0.4);
}
ballSpin[ball1] = ballSpin[ball1] * entropyValue / 2;
ballSpin[ball2] = ballSpin[ball1] * -1;
}
spinning-collisions-01
Sketch created in Processing 3 for Creative Coding course: Week 3: extend the spinning top sketch.
The code follows:
/*
* Creative Coding
* Week 3, 04
* extending spinning top: based on work
* by Indae Hwang and Jon McCormack
* Updated 2016
* Copyright (c) 2014-2016 Monash University
*
* Pool balls collide, spin and absorb each other.
*
*/
int num; // the number of items in the array
float[] ballX; // x-position of ball
float[] ballY; // y-position of ball
float[] ballSpeed; // speed of movement of ball
float[] ballDirection; // direction of movement of ball in radians
float[] ballSpin; // spin (rotation speed and direction) of ball
float[] ballBaseline; // baseline of spinning ball text
color[] ballColour; // colour of ball
int [] ballSize; // current radius of ball
int [] ballCollisionState; // 0 = waiting for collision; 1 = in collision
float entropyValue = 0.98; // fraction of 'energy' retained after collisions etc.
color backgroundColour = #000000;
color baizeColour = #46AA4A;
color tableColour = #C1953B;
color colourFrom = #FF0000; // starts colour range of balls
color colourTo = #0000FF; // ends colour range of balls
int tableHeight = 480;
int tableWidth = 360;
int tableEdgedepth = 30;
int ballRadius = 15;
float spinEffect = 1.1; // how much spin adds to bounce angles off side
int opacity = 50;
// dimension variables
int centreX;
int centreY;
int centreLeft;
int centreRight;
int centreTop;
int centreBottom;
void setup() {
size(400, 520);
// initialise dimension variables
centreX = width/2;
centreY = height/2;
centreLeft = width/2 - tableWidth/2 - tableEdgedepth/2;
centreRight = width/2 + tableWidth/2 + tableEdgedepth/2;
centreTop = height/2 - tableHeight/2 - tableEdgedepth/2;
centreBottom = height/2 + tableHeight/2 + tableEdgedepth/2;
num = 8; // number of balls
// allocate size of arrays
ballX = new float[num];
ballY = new float[num];
ballSpeed = new float[num];
ballDirection = new float[num];
ballSpin = new float[num];
ballBaseline = new float[num];
ballColour = new color[num];
ballSize = new int[num];
ballCollisionState = new int[num];
// initial position of ball 0 in the top half of the screen
ballX[0] = centreX;
ballY[0] = centreTop + 2 * tableEdgedepth;
ballSpeed[0] = random(8, 12);
ballDirection[0] = PI*9.0/20.0 + random(PI/10.0);
//ballDirection[0] = PI/2;
//ballDirection[0] = PI/4;
ballSpin[0] = random(PI) - PI/2;
ballBaseline[0] = 0.0;
ballColour[0] = #FFFFFF;
ballSize[0] = ballRadius;
ballCollisionState[0] = 0;
// initialise positions of rest of balls
for (int i = 1; i < ballX.length; i++) {
ballX[i] = random(centreLeft + 2 * tableEdgedepth, centreRight - 2 * tableEdgedepth);
ballY[i] = random(centreTop + 4 * tableEdgedepth, centreBottom - 2 * tableEdgedepth);
ballSpeed[i] = 0.0;
ballDirection[i] = 0.0;
ballSpin[i] = 0.0;
ballBaseline[i] = 0.0;
ballColour[i] = lerpColor(colourFrom, colourTo, (i - 1.0)/(num - 2.0));
ballSize[i] = ballRadius;
ballCollisionState[i] = 0;
}
// draw background objects
background(0);
noStroke();
rectMode(CENTER);
fill(baizeColour);
rect(centreX, centreY, tableWidth - tableEdgedepth, tableHeight - tableEdgedepth);
fill(tableColour);
rect(centreLeft, centreY, tableEdgedepth, tableHeight); //left
rect(centreRight, centreY, tableEdgedepth, tableHeight); //right
rect(centreX, centreTop, tableWidth, tableEdgedepth); //top
rect(centreX, centreBottom, tableWidth, tableEdgedepth); //bottom
// text settings
textSize(ballRadius);
textAlign(CENTER, CENTER);
}
void draw() {
// blend the old frames into the background
blendMode(BLEND);
stroke(0, opacity);
// draw balls
for (int i = 0; i 0.0) {
fill(ballColour[i], opacity);
ellipse(ballX[i], ballY[i], ballSize[i], ballSize[i]);
translate(ballX[i], ballY[i]);
rotate(ballBaseline[i]);
fill(0, opacity);
textSize(ballSize[i]);
text(i, 0, 0);
resetMatrix();
}
}
// move balls
for (int i = 0; i < ballX.length; i++) {
float dx = cos(ballDirection[i]) * ballSpeed[i];
float dy = sin(ballDirection[i]) * ballSpeed[i];
ballX[i] += dx;
ballY[i] += dy;
}
// collision detection
// with sides
for (int i = 0; i < ballX.length; i++) {
if (ballX[i] centreRight - tableEdgedepth) {
ballDirection[i] = (-1 * PI - ballDirection[i]) * spinEffect;
}
if (ballY[i] centreBottom - tableEdgedepth) {
ballDirection[i] = (-1 * ballDirection[i]) * spinEffect;
}
}
// with other balls
for (int i = 0; i < ballX.length; i++) {
for (int j = 0; j < ballX.length; j++) {
if (i != j) { // a ball cannot collide with itself
if (dist(ballX[i], ballY[i], ballX[j], ballY[j]) <= ballRadius) {
if (ballCollisionState[i] == 0 && ballCollisionState[j] == 0) {
ballCollisionState[i] = 1;
ballCollisionState[j] = 1;
ballCollision(i, j);
}
} else {
ballCollisionState[i] = 0;
}
}
}
}
// spin balls
for (int i = 0; i ballSpeed[ball2] ? ball1 : ball2;
int loser = winner == ball1 ? ball2 : ball1;
ballSpeed[winner] = ballSpeed[ball1] + ballSpeed[ball2] * entropyValue;
ballSpeed[loser] = 0.0;
ballDirection[winner] = (ballDirection[ball1] + ballDirection[ball2] / 2) / PI;
float r1 = ballSize[ball1];
float r2 = ballSize[ball2];
ballSize[winner] = (int) sqrt(sq(r1) + sq(r2));
ballSize[loser] = 0;
ballColour[winner] = lerpColor(ballColour[winner], ballColour[loser], 0.4);
}
ballSpin[ball1] = ballSpin[ball1] * entropyValue / 2;
ballSpin[ball2] = ballSpin[ball1] * -1;
}