-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBall.pde
149 lines (123 loc) · 4.63 KB
/
Ball.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Code Adapted by: Shyamal Chandra
class Ball {
PVector position;
PVector velocity;
float radius, m;
int red, green, blue;
final float velocity_constant = 10;
final float guassian_constant = 5;
Ball(float x, float y, float r_, float red, float green, float blue) {
position = new PVector(x, y);
velocity = PVector.random2D();
velocity.mult(r_/velocity_constant);
radius = r_;
m = radius*.1;
this.red = int(red);
this.green = int(green);
this.blue = int(blue);
}
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) {
/*
this.red = int(random(255));
this.green = int(random(255));
this.blue = int(random(255));
*/
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[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 * distanceVect.x + sine * distanceVect.y;
bTemp[1].y = cosine * distanceVect.y - sine * distanceVect.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(red,green,blue);
ellipse(position.x, position.y, radius*2, radius*2);
}
}