I am attempting to detect collisions between two shapes using intersects
, however, the detection is not working.
Printing out the Circle
objects reveal the x and y positions are set as 0. I suspected that maybe the position getter and setter methods were not working correctly, however, printing out this information reveals non-zero values.
Why is the detection not working?
Thank you.
Edit: The below code is now working. See comments for detail of the issue / solution.
Main Class
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel {
public static List<Circle> circleList = new ArrayList<>();
private static Random random = new Random();
public Main() {
for (int i = 0; i < 2; i++) {
circleList.add(new Circle(random.nextInt(500), random.nextInt(500)));
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Circle CircleShape : circleList) {
CircleShape.collision();
CircleShape.drawCircle(g);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
}
}
Circle Class
import java.awt.Graphics;
public class Circle extends Shape {
public Circle(int x, int y) {
super(x, y);
super.setSize(200, 200);
}
public void drawCircle(Graphics g) {
g.setColor(colour);
g.fillOval(x, y, 200, 200);
}
public void collision() {
for (Circle CircleShape : Main.circleList) {
System.out.println(CircleShape);
System.out.println(CircleShape.getxPos());
if (this.intersects(CircleShape)) {
System.out.println("collision detected");
} else {
System.out.println("no collision detected");
}
}
}
}
Shape Class
import java.awt.Color;
import java.awt.Rectangle;
public class Shape extends Rectangle {
//int x, y;
Color colour;
public Shape(int x, int y) {
//this.setxPos(x);
//this.setyPos(y);
this.setPos(x, y);
}
/*
public int getxPos() {
return this.x;
}
public void setxPos(int x) {
this.x = x;
}
public int getyPos() {
return this.y;
}
public void setyPos(int y) {
this.y = y;
}
*/
public void setPos(int x, int y) {
super.setLocation(x, y);
}
public Point getPos() {
return new Point(x, y);
}
}
The intersects
method expect x, y, width and height properties to be correctly set, because they are used to detect if an object collides with another.
So, in your setter methods you need to invoke super.setLocation(newX, newY)
, and you should provide a valid width and height too.
So, it should be:
public void setxPos(int x) {
this.x = x;
super.setLocation(x, y);
}
public void setyPos(int y) {
this.y = y;
super.setLocation(x, y);
}
and
public Circle(int x, int y) {
super(x, y);
super.setSize(200, 200);
}
Or, you could just use the already provided methods from class Rectangle
:
public Circle(int x, int y, int width, int height) {
super(x, y, width, height);
}
And also use setLocation
instead of setxPos
and setyPos
.
The complete code would become like this:
Shape
class
import java.awt.Color;
import java.awt.Rectangle;
public class Shape extends Rectangle {
Color colour;
public Shape(int x, int y, int width, int height) {
// provided by the Rectangle class. Needed for proper collision detection
super(x, y, width, height);
}
}
Circle
class:
import java.awt.Graphics;
public class Circle extends Shape {
public Circle(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void drawCircle(Graphics g) {
g.setColor(super.colour);
// instead of writing values here, we get them from width and height fields
g.fillOval(x, y, (int) getWidth(), (int) getHeight());
}
public void collision() {
for (Circle CircleShape : Main.circleList) {
System.out.println(CircleShape);
System.out.println(CircleShape.getLocation().x);
if (this.intersects(CircleShape)) {
System.out.println("collision detected");
} else {
System.out.println("no collision detected");
}
}
}
}
Main
class:
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JPanel {
public static List<Circle> circleList = new ArrayList<>();
private static Random random = new Random();
public Main() {
for (int i = 0; i < 2; i++) {
// width and height are specified here instead of inside the Circle.drawCircle method.
circleList.add(new Circle(random.nextInt(500), random.nextInt(500), 200, 200));
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Circle CircleShape : circleList) {
CircleShape.collision();
CircleShape.drawCircle(g);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new Main());
}
}