Orb Tips
Reducing Glitchiness
If your code is glitchy/laggy/stuttery there may be a few ways to help
- Reduce the FPS to 10,15,20. Even try really low 4,5 in severe cases
- Don’t draw too much to the screen. 1000 orbs is probably too many!
- If you are loading images, make sure the original .png file is already the right size that you want to show on screen (resize it in another app)
Intensive remove glitchiness
Replace
// Animation loop
while (true) {
// Clear the canvas
StdDraw.clear(StdDraw.WHITE);
// Update and draw all orbs
for (Orb orb : orbs) {
orb.update(DELTA_T);
orb.draw();
}
// Show the frame
StdDraw.show();
StdDraw.pause(1000 / FPS);
}
with
// Animation loop
while (true) {
// Clear the canvas
StdDraw.clear(StdDraw.WHITE);
currentTime = System.nanoTime();
deltaT = currentTime - lastTime; // time since last frame
deltaT /= 1_000_000_000.0; // convert to seconds
lastTime = currentTime; // reset lastTime to now
if (deltaT <= 0) { // in case it's 0, set it to 30FPS
deltaT = 1.0 / 30.0;
}
double frameRate = 1.0 / deltaT;
// Update and draw all orbs
for (Orb orb : orbs) {
orb.update(deltaT); // use the actual deltaT
orb.draw();
}
// Show the frame
StdDraw.show();
// Don't pause!!
}
Real 2D Collisions
I made some code to calculate orb-orb collision with bouncing if you’re interested! Based on equations found here.
public void bounceOrbs2(Orb other) {
// Position vectors
double x1 = this.x;
double y1 = this.y;
double x2 = other.x;
double y2 = other.y;
// Velocity vectors
double v1x = this.vx;
double v1y = this.vy;
double v2x = other.vx;
double v2y = other.vy;
// Delta velocity: v1 - v2
double delta_vx = v1x - v2x;
double delta_vy = v1y - v2y;
// Delta position: x1 - x2
double delta_xx = x1 - x2;
double delta_xy = y1 - y2;
// Normalize delta_x
double delta_x_magnitude = Math.sqrt(delta_xx * delta_xx + delta_xy * delta_xy);
double delta_x_norm_x = delta_xx / delta_x_magnitude;
double delta_x_norm_y = delta_xy / delta_x_magnitude;
// Scale normalized vector by (radius1 + radius2)
double combined_radius = this.radius + other.radius;
double delta_x_scaled_x = delta_x_norm_x * combined_radius;
double delta_x_scaled_y = delta_x_norm_y * combined_radius;
// New position for this orb: x1 = x2 + delta_x_scaled
x1 = x2 + delta_x_scaled_x;
y1 = y2 + delta_x_scaled_y;
// Masses (using radius as mass, BUT YOU tweak)
double m1 = this.radius;
double m2 = other.radius;
// Calculate dot products
double delta_v_dot_delta_x = delta_vx * delta_x_scaled_x + delta_vy * delta_x_scaled_y;
double delta_x_dot_delta_x = delta_x_scaled_x * delta_x_scaled_x + delta_x_scaled_y * delta_x_scaled_y;
// Calculate velocity changes
double scalar1 = delta_v_dot_delta_x * (m2 + m2) / (m1 + m2) / delta_x_dot_delta_x;
double scalar2 = delta_v_dot_delta_x * (m1 + m1) / (m1 + m2) / delta_x_dot_delta_x;
// Update v1: v1 = v1 - delta_x_scaled * scalar1
v1x = v1x - delta_x_scaled_x * scalar1;
v1y = v1y - delta_x_scaled_y * scalar1;
// Update v2: v2 = v2 + delta_x_scaled * scalar2
v2x = v2x + delta_x_scaled_x * scalar2;
v2y = v2y + delta_x_scaled_y * scalar2;
// Apply velocity changes to orbs
this.vx = v1x;
this.vy = v1y;
other.vx = v2x;
other.vy = v2y;
// Move both orbs apart proportionally
// This is required because in one frame
// The orbs can "overlap" which is not right
// This code 'reverses' them so they're just touching
double total_overlap = combined_radius - delta_x_magnitude;
double ratio1 = m2 / (m1 + m2);
double ratio2 = m1 / (m1 + m2);
this.x += delta_x_norm_x * total_overlap * ratio1;
this.y += delta_x_norm_y * total_overlap * ratio1;
other.x -= delta_x_norm_x * total_overlap * ratio2;
other.y -= delta_x_norm_y * total_overlap * ratio2;
}