# Circle Collision with Swapping Velocities

Circle Collision with Swapping Velocities by Ira Greenberg.

Based on Keith Peter’s Solution in Foundation Actionscript Animation: Making Things Move!

```
Ball[] balls =  {
new Ball(100, 400, 20),
new Ball(700, 400, 80)
};

void setup() {
size(640, 360);
}

void draw() {
background(51);

for (Ball b : balls) {
b.update();
b.display();
b.checkBoundaryCollision();
}

balls.checkCollision(balls);
}

class Ball {
PVector position;
PVector velocity;

float radius, m;

Ball(float x, float y, float r_) {
position = new PVector(x, y);
velocity = PVector.random2D();
velocity.mult(3);
radius = r_;
m = radius*.1;
}

void update() {
position.add(velocity);
}

void checkBoundaryCollision() {
if (position.x > width-radius) {
position.x = width-radius;
velocity.x *= -1;
} else if (position.x < radius) {
position.x = radius;
velocity.x *= -1;
} else if (position.y > height-radius) {
position.y = height-radius;
velocity.y *= -1;
} else if (position.y < radius) {
position.y = radius;
velocity.y *= -1;
}
}

void checkCollision(Ball other) {

// Get distances between the balls components
PVector distanceVect = PVector.sub(other.position, position);

// Calculate magnitude of the vector separating the balls
float distanceVectMag = distanceVect.mag();

// Minimum distance before they are touching
float minDistance = radius + other.radius;

if (distanceVectMag < minDistance) {
float distanceCorrection = (minDistance-distanceVectMag)/2.0;
PVector d = distanceVect.copy();
PVector correctionVector = d.normalize().mult(distanceCorrection);
other.position.add(correctionVector);
position.sub(correctionVector);

// get angle of distanceVect
float theta  = distanceVect.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 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.position.x and bTemp.position.y will initialize
automatically to 0.0, which is what you want
since b will rotate around b */
bTemp.x  = cosine * distanceVect.x + sine * distanceVect.y;
bTemp.y  = cosine * distanceVect.y - sine * distanceVect.x;

// rotate Temporary velocities
PVector[] vTemp = {
new PVector(), new PVector()
};

vTemp.x  = cosine * velocity.x + sine * velocity.y;
vTemp.y  = cosine * velocity.y - sine * velocity.x;
vTemp.x  = cosine * other.velocity.x + sine * other.velocity.y;
vTemp.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
vFinal.x = ((m - other.m) * vTemp.x + 2 * other.m * vTemp.x) / (m + other.m);
vFinal.y = vTemp.y;

// final rotated velocity for b
vFinal.x = ((other.m - m) * vTemp.x + 2 * m * vTemp.x) / (m + other.m);
vFinal.y = vTemp.y;

// hack to avoid clumping
bTemp.x += vFinal.x;
bTemp.x += vFinal.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.x = cosine * bTemp.x - sine * bTemp.y;
bFinal.y = cosine * bTemp.y + sine * bTemp.x;
bFinal.x = cosine * bTemp.x - sine * bTemp.y;
bFinal.y = cosine * bTemp.y + sine * bTemp.x;

// update balls to screen position
other.position.x = position.x + bFinal.x;
other.position.y = position.y + bFinal.y;

position.add(bFinal);

// update velocities
velocity.x = cosine * vFinal.x - sine * vFinal.y;
velocity.y = cosine * vFinal.y + sine * vFinal.x;
other.velocity.x = cosine * vFinal.x - sine * vFinal.y;
other.velocity.y = cosine * vFinal.y + sine * vFinal.x;
}
}

void display() {
noStroke();
fill(204);
ellipse(position.x, position.y, radius*2, radius*2);
}
}```

## Functions Used

ellipse()

Draws an ellipse (oval) to the screen

Learn More
mag()

Calculates the magnitude (or length) of a vector

Learn More
fill()

Sets the color used to fill shapes

Learn More
size()

Defines the dimension of the display window width and height in units of pixels

Learn More
cos()

Calculates the cosine of an angle

Learn More
sin()

Calculates the sine of an angle

Learn More
setup()

The setup() function is run once, when the program starts

Learn More
copy()

Copies a region of pixels from the display window to another area of the display window and copies a region of pixels from an image used as the srcImg parameter into the display window

Learn More
draw()

Called directly after setup(), the draw() function continuously executes the lines of code contained inside its block until the program is stopped or noLoop() is called

Learn More
background()

The background() function sets the color used for the background of the Processing window

Learn More
noStroke()

Disables drawing the stroke (outline)

Learn More
PVector

A class to describe a two or three dimensional vector, specifically a Euclidean (also known as geometric) vector

Learn More