From 4cde40675e7bb213ffda8f9ab51f700b140da04c Mon Sep 17 00:00:00 2001 From: Daniel Shiffman Date: Fri, 15 Mar 2013 22:56:44 -0400 Subject: [PATCH] updating CircleCollision to follow PVector syntax --- .../Topics/Motion/CircleCollision/Ball.pde | 135 ++++++++++++++++-- .../CircleCollision/CircleCollision.pde | 122 +--------------- 2 files changed, 132 insertions(+), 125 deletions(-) diff --git a/java/examples/Topics/Motion/CircleCollision/Ball.pde b/java/examples/Topics/Motion/CircleCollision/Ball.pde index 93548b96d..7cb12eb8c 100644 --- a/java/examples/Topics/Motion/CircleCollision/Ball.pde +++ b/java/examples/Topics/Motion/CircleCollision/Ball.pde @@ -1,16 +1,131 @@ -class Ball{ - float x, y, r, m; +class Ball { + PVector position; + PVector velocity; - // default constructor - Ball() { + float r, m; + + Ball(float x, float y, float r_) { + position = new PVector(x, y); + velocity = PVector.random2D(); + velocity.mult(3); + r = r_; + m = r*.1; } - Ball(float x, float y, float r) { - this.x = x; - this.y = y; - this.r = r; - m = r*.1; + void update() { + position.add(velocity); + } + + void checkBoundaryCollision() { + if (position.x > width-r) { + position.x = width-r; + velocity.x *= -1; + } + else if (position.x < r) { + position.x = r; + velocity.x *= -1; + } + else if (position.y > height-r) { + position.y = height-r; + velocity.y *= -1; + } + else if (position.y < r) { + position.y = r; + velocity.y *= -1; + } + } + + void checkCollision(Ball other) { + + // get distances between the balls components + PVector bVect = PVector.sub(other.position, position); + + // calculate magnitude of the vector separating the balls + float bVectMag = bVect.mag(); + + if (bVectMag < r + other.r) { + // get angle of bVect + float theta = bVect.heading(); + // precalculate trig values + float sine = sin(theta); + float cosine = cos(theta); + + /* bTemp will hold rotated ball positions. You + just need to worry about bTemp[1] position*/ + PVector[] bTemp = { + new PVector(), new PVector() + }; + + /* this ball's position is relative to the other + so you can use the vector between them (bVect) as the + reference point in the rotation expressions. + bTemp[0].position.x and bTemp[0].position.y will initialize + automatically to 0.0, which is what you want + since b[1] will rotate around b[0] */ + bTemp[1].x = cosine * bVect.x + sine * bVect.y; + bTemp[1].y = cosine * bVect.y - sine * bVect.x; + + // rotate Temporary velocities + PVector[] vTemp = { + new PVector(), new PVector() + }; + + vTemp[0].x = cosine * velocity.x + sine * velocity.y; + vTemp[0].y = cosine * velocity.y - sine * velocity.x; + vTemp[1].x = cosine * other.velocity.x + sine * other.velocity.y; + vTemp[1].y = cosine * other.velocity.y - sine * other.velocity.x; + + /* Now that velocities are rotated, you can use 1D + conservation of momentum equations to calculate + the final velocity along the x-axis. */ + PVector[] vFinal = { + new PVector(), new PVector() + }; + + // final rotated velocity for b[0] + vFinal[0].x = ((m - other.m) * vTemp[0].x + 2 * other.m * vTemp[1].x) / (m + other.m); + vFinal[0].y = vTemp[0].y; + + // final rotated velocity for b[0] + vFinal[1].x = ((other.m - m) * vTemp[1].x + 2 * m * vTemp[0].x) / (m + other.m); + vFinal[1].y = vTemp[1].y; + + // hack to avoid clumping + bTemp[0].x += vFinal[0].x; + bTemp[1].x += vFinal[1].x; + + /* Rotate ball positions and velocities back + Reverse signs in trig expressions to rotate + in the opposite direction */ + // rotate balls + PVector[] bFinal = { + new PVector(), new PVector() + }; + + bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y; + bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x; + bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y; + bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x; + + // update balls to screen position + other.position.x = position.x + bFinal[1].x; + other.position.y = position.y + bFinal[1].y; + + position.add(bFinal[0]); + + // update velocities + velocity.x = cosine * vFinal[0].x - sine * vFinal[0].y; + velocity.y = cosine * vFinal[0].y + sine * vFinal[0].x; + other.velocity.x = cosine * vFinal[1].x - sine * vFinal[1].y; + other.velocity.y = cosine * vFinal[1].y + sine * vFinal[1].x; + } + } + + + void display() { + noStroke(); + fill(204); + ellipse(position.x, position.y, r*2, r*2); } } - diff --git a/java/examples/Topics/Motion/CircleCollision/CircleCollision.pde b/java/examples/Topics/Motion/CircleCollision/CircleCollision.pde index b40d4936a..05e2a350a 100644 --- a/java/examples/Topics/Motion/CircleCollision/CircleCollision.pde +++ b/java/examples/Topics/Motion/CircleCollision/CircleCollision.pde @@ -6,135 +6,27 @@ * Foundation Actionscript Animation: Making Things Move! */ - Ball[] balls = { new Ball(100, 400, 20), new Ball(700, 400, 80) }; -PVector[] vels = { - new PVector(2.15, -1.35), - new PVector(-1.65, .42) -}; - void setup() { size(640, 360); - noStroke(); } void draw() { background(51); - fill(204); - for (int i = 0; i < 2; i++){ - balls[i].x += vels[i].x; - balls[i].y += vels[i].y; - ellipse(balls[i].x, balls[i].y, balls[i].r*2, balls[i].r*2); - checkBoundaryCollision(balls[i], vels[i]); + + for (Ball b : balls) { + b.update(); + b.display(); + b.checkBoundaryCollision(); } - checkObjectCollision(balls, vels); + + balls[0].checkCollision(balls[1]); } -void checkObjectCollision(Ball[] b, PVector[] v){ - // get distances between the balls components - PVector bVect = new PVector(); - bVect.x = b[1].x - b[0].x; - bVect.y = b[1].y - b[0].y; - // calculate magnitude of the vector separating the balls - float bVectMag = sqrt(bVect.x * bVect.x + bVect.y * bVect.y); - if (bVectMag < b[0].r + b[1].r){ - // get angle of bVect - float theta = atan2(bVect.y, bVect.x); - // precalculate trig values - float sine = sin(theta); - float cosine = cos(theta); - - /* bTemp will hold rotated ball positions. You - just need to worry about bTemp[1] position*/ - Ball[] bTemp = { - new Ball(), new Ball() - }; - - /* b[1]'s position is relative to b[0]'s - so you can use the vector between them (bVect) as the - reference point in the rotation expressions. - bTemp[0].x and bTemp[0].y will initialize - automatically to 0.0, which is what you want - since b[1] will rotate around b[0] */ - bTemp[1].x = cosine * bVect.x + sine * bVect.y; - bTemp[1].y = cosine * bVect.y - sine * bVect.x; - - // rotate Temporary velocities - PVector[] vTemp = { - new PVector(), new PVector() - }; - vTemp[0].x = cosine * v[0].x + sine * v[0].y; - vTemp[0].y = cosine * v[0].y - sine * v[0].x; - vTemp[1].x = cosine * v[1].x + sine * v[1].y; - vTemp[1].y = cosine * v[1].y - sine * v[1].x; - - /* Now that velocities are rotated, you can use 1D - conservation of momentum equations to calculate - the final velocity along the x-axis. */ - PVector[] vFinal = { - new PVector(), new PVector() - }; - // final rotated velocity for b[0] - vFinal[0].x = ((b[0].m - b[1].m) * vTemp[0].x + 2 * b[1].m * - vTemp[1].x) / (b[0].m + b[1].m); - vFinal[0].y = vTemp[0].y; - // final rotated velocity for b[0] - vFinal[1].x = ((b[1].m - b[0].m) * vTemp[1].x + 2 * b[0].m * - vTemp[0].x) / (b[0].m + b[1].m); - vFinal[1].y = vTemp[1].y; - - // hack to avoid clumping - bTemp[0].x += vFinal[0].x; - bTemp[1].x += vFinal[1].x; - - /* Rotate ball positions and velocities back - Reverse signs in trig expressions to rotate - in the opposite direction */ - // rotate balls - Ball[] bFinal = { - new Ball(), new Ball() - }; - bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y; - bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x; - bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y; - bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x; - - // update balls to screen position - b[1].x = b[0].x + bFinal[1].x; - b[1].y = b[0].y + bFinal[1].y; - b[0].x = b[0].x + bFinal[0].x; - b[0].y = b[0].y + bFinal[0].y; - - // update velocities - v[0].x = cosine * vFinal[0].x - sine * vFinal[0].y; - v[0].y = cosine * vFinal[0].y + sine * vFinal[0].x; - v[1].x = cosine * vFinal[1].x - sine * vFinal[1].y; - v[1].y = cosine * vFinal[1].y + sine * vFinal[1].x; - } -} - -void checkBoundaryCollision(Ball ball, PVector vel) { - if (ball.x > width-ball.r) { - ball.x = width-ball.r; - vel.x *= -1; - } - else if (ball.x < ball.r) { - ball.x = ball.r; - vel.x *= -1; - } - else if (ball.y > height-ball.r) { - ball.y = height-ball.r; - vel.y *= -1; - } - else if (ball.y < ball.r) { - ball.y = ball.r; - vel.y *= -1; - } -}