# Collision method for multiple circles

This is a bouncing ball program. There is 1 dynamic circle and 3 static ones. The static ones are obstacles for the dynamic circle, and the dynamic circle is supposed to bounce off of the static circles.

So I have an ArrayList of static circles:

public static List<Circle> circles_Static = new ArrayList<Circle>();


Something is wrong with my method for checking if the dynamic circle collides with any of the static ones. Currently, the dynamic circle starts bouncing all over the canvas extremely quickly and even disappears. So, if I don't use this method and call each static circle separately and see if it collides with the dynamic one, it's working perfecly. There's definitely something wrong with how the method is working and I really can't see what it may be.

Here's the method:

    public void collision() {
for (int i = 0; i < circles_Static.size(); i++) {
double dx = circles_Static.get(i).getLayoutX() - circle1.getLayoutX();
double dy = circles_Static.get(i).getLayoutY() - circle1.getLayoutY();
double distance = (dx * dx) + (dy * dy);

if (distance < minDistance * minDistance) {
double angle = Math.atan2(dy, dx);
double targetX = circle1.getLayoutX() + Math.cos(angle) * minDistance;
double targetY = circle1.getLayoutX() + Math.sin(angle) * minDistance;
double ax = (targetX - circles_Static.get(i).getLayoutX()) * spring;
double ay = (targetY - circles_Static.get(i).getLayoutY()) * spring;
c1SpeedX -= ax;
c1SpeedY -= ay;
return;

}
}
}


You can find the full source code below:

public class VideoGame1 extends Application {

public static List<Circle> circles_Static = new ArrayList<Circle>();
public static Circle circle1;
public static Circle c1_Static;
public static Circle c2_Static;
public static Circle c3_Static;
public static Pane canvas;
double spring = 1;
private long counter = 0;
double c1SpeedX = 1;
double c1SpeedY = 1;

@Override
public void start(Stage primaryStage) {

canvas = new Pane();
Scene scene = new Scene(canvas, 800, 600);

primaryStage.setTitle("Ball Game");
primaryStage.setScene(scene);
primaryStage.show();

c1_Static = new Circle(100, Color.BLACK);
c1_Static.relocate(300, 200);

c2_Static = new Circle(20, Color.CORNFLOWERBLUE);
c2_Static.relocate(550, 250);

c3_Static = new Circle(40, Color.CORAL);
c3_Static.relocate(500, 500);

circle1 = new Circle(30, Color.BLUE);
circle1.relocate(100, 60);

Timeline loop;
loop = new Timeline(new KeyFrame(Duration.millis(1), new EventHandler<ActionEvent>() {

@Override
public void handle(ActionEvent t) {
if (counter++ % 2 == 0) {
// Moves the ball
circle1.setLayoutX(circle1.getLayoutX() + c1SpeedX);
circle1.setLayoutY(circle1.getLayoutY() + c1SpeedY);

// Dynamic ball bounces off the walls
final Bounds bounds = canvas.getBoundsInLocal();
boolean leftWall = circle1.getLayoutX() <= (bounds.getMinX() + circle1.getRadius());
boolean topWall = circle1.getLayoutY() <= (bounds.getMinY() + circle1.getRadius());
boolean rightWall = circle1.getLayoutX() >= (bounds.getMaxX() - circle1.getRadius());
boolean bottomWall = circle1.getLayoutY() >= (bounds.getMaxY() - circle1.getRadius());

//Check if dynamic ball collides with any of the static balls

collision(); ////// HERE ////////

// So the issue has gotta be on the line above. The collision() method.

// If the bottom or top wall has been touched, the ball reverses direction.
if (bottomWall || topWall) {

c1SpeedY = c1SpeedY * -1;

}
// If the left or right wall has been touched, the ball reverses direction.
if (leftWall || rightWall) {
c1SpeedX = c1SpeedX * -1;
}
}

}

public void collision() {
for (int i = 0; i < circles_Static.size(); i++) {
double dx = circles_Static.get(i).getLayoutX() - circle1.getLayoutX();
double dy = circles_Static.get(i).getLayoutY() - circle1.getLayoutY();
double distance = (dx * dx) + (dy * dy);

if (distance < minDistance * minDistance) {
double angle = Math.atan2(dy, dx);
double targetX = circle1.getLayoutX() + Math.cos(angle) * minDistance;
double targetY = circle1.getLayoutX() + Math.sin(angle) * minDistance;
double ax = (targetX - circles_Static.get(i).getLayoutX()) * spring;
double ay = (targetY - circles_Static.get(i).getLayoutY()) * spring;
c1SpeedX -= ax;
c1SpeedY -= ay;
return;

} else {
break;
}

}
}

}));

loop.setCycleCount(Timeline.INDEFINITE);
loop.play();
}

public static void main(String[] args) {
launch(args);
}

}

• P.S. The algorithm in the method itself is working perfectly, because I've already tested it a dozen times by comparing each circle separately. I think the problem is the ArrayList of static circles. – Gregg1989 Nov 24 '13 at 1:03

double targetY = circle1.getLayoutX() + Math.sin(angle) * minDistance;

Certainly you meant getLayoutY.
As a side note, it is useless to compute angle = atan2(y,x) if the only thing you are doing afterwards is cos(angle) or sin(angle). The cosine and sine of the angle are simply x/sqrt(x²+y²) and y/sqrt(x²+y²), which is also a lot faster to compute.