0
votes

I have some problem checking if the 2 rectangles has a collision given with 4 points, so I have a rect1 with p1(x,y) for lower left corner and p2(x,y) for upper right corner, same as rect2.


So this is my graph illustration:

Image

This is my sample code so far:

    int[][] rect1 = {{2,0},{3,1}};
    int[][] rect2 = {{0,0},{1,2}};
    if(rect1[1][0] >= rect2[0][0] && rect1[1][1] >= rect2[0][1] && rect1[0][0] <= rect2[1][0] && rect1[0][1] <= rect2[1][1])
    {
        System.out.println("Collision");
    } else {
        System.out.println("No Collision");
    }

I'm not pretty sure if I got it correctly with this code, can anyone give my some idea? (I'm beginner!)

2
Worth noting: Java has a Rectangle.intersects method - Eric

2 Answers

0
votes

Short Answer: Yes

Essentially you have four conditions you have to check to be sure you have colliding rectangles:

  • The first rectangle's upper right corner must be right of the second's bottom left corner
  • The first rectangle's upper right corner must be above the second's bottom left corner
  • The first rectangle's bottom left corner must be left of the second's upper right corner
  • The first rectangle's bottom left corner must be below the second's upper right corner

Refactor your code like follows and it will become clearer how the above four conditions are met:

public class HelloWorld {

     public static void main(String []args){
        int[][] rect1 = {{1,5},{4,8}};
        int[][] rect2 = {{4,1},{7,4}};
        if( isRect1UpperRightCornerRightOfRect2BottomLeftCorner(rect1, rect2) && 
            isRect1UpperRightCornerAboveRect2BottomLeftCorner(rect1, rect2) && 
            isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(rect1, rect2) && 
            isRect1BottomLeftCornerBelowRect2UpperRightCorner(rect1, rect2) ) {
            System.out.println("Collision");
        } else {
            System.out.println("No Collision");
        }
     }

     private static boolean isRect1UpperRightCornerRightOfRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
        return rect1[1][0] >= rect2[0][0];
     }

     private static boolean isRect1UpperRightCornerAboveRect2BottomLeftCorner(int[][] rect1, int[][] rect2) {
         return rect1[1][1] >= rect2[0][1];
     }

     private static boolean isRect1BottomLeftCornerLeftOfRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
         return rect1[0][0] <= rect2[1][0];
     }

     private static boolean isRect1BottomLeftCornerBelowRect2UpperRightCorner(int[][] rect1, int[][] rect2) {
         return rect1[0][1] <= rect2[1][1];
     }
}

Also here is a good interactive website showing visually how the above would work. Note the corners are flipped.

0
votes

First, your code do not compiles in the if block. There is an unmatched opening parenthesis. I will remove it.

So, lets add some intermediate variables to better see the meaning of the code:

int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};

int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];

int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];

if (rect1X2 >= rect2X1 && rect1Y2 >= rect2Y1 && rect1X1 <= rect2X2 && rect1Y1 <= rect2Y2)
{
    System.out.println("Collision");
} else {
    System.out.println("No Collision");
}

Now, lets separate the logic of each axis:

int[][] rect1 = {{2,0},{3,1}};
int[][] rect2 = {{0,0},{1,2}};

int rect1X1 = rect1[0][0];
int rect1X2 = rect1[1][0];
int rect1Y1 = rect1[0][1];
int rect1Y2 = rect1[1][1];

int rect2X1 = rect2[0][0];
int rect2X2 = rect2[1][0];
int rect2Y1 = rect2[0][1];
int rect2Y2 = rect2[1][1];

boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
boolean yCollides = rect1Y2 >= rect2Y1 && rect1Y1 <= rect2Y2;

if (xCollides && yCollides)
{
    System.out.println("Collision");
} else {
    System.out.println("No Collision");
}

How can we get a collision for one axis? There are 15 forms of how the two objects are positioned along an axis in relation to each other:

Case 1 - Full coincident collision:

X-----X
X-----X

Cases 2, 3, 4, 5, 6 and 7 - Full non-coincident collision:

X---X              X---X          X-----X
X-----X          X-----X            X---X


X-----X            X-X            X-----X
  X-X            X-----X          X---X

Cases 8 and 9 - Partial collision:

X---X              X---X
  X---X          X---X

Cases 10 and 11 - Barely colliding:

X--X                X--X
   X--X          X--X

Cases 12 and 13 - Just touching (not colliding):

X--X                 X-X
    X-X          X--X

Cases 14 and 15 - Far apart (not colliding):

X-X                  X-X
    X-X          X-X

Your code should separate the cases 1 to 11 from the cases 12 to 15 in each axis. Lets see what it does:

boolean xCollides = rect1X2 >= rect2X1 && rect1X1 <= rect2X2;
  • Case 1: true and true -> true
  • Case 2: true and true -> true
  • Case 3: true and true -> true
  • Case 4: true and true -> true
  • Case 5: true and true -> true
  • Case 6: true and true -> true
  • Case 7: true and true -> true
  • Case 8: true and true -> true
  • Case 9: true and true -> true
  • Case 10: true and true -> true
  • Case 11: true and true -> true
  • Case 12: false and true -> false
  • Case 13: true and false -> false
  • Case 14: false and true -> false
  • Case 15: true and false -> false

So, your code is able to separate the cases 1 to 11 from cases 12 to 15, and thus it is correct for axis X. The code for axis Y is equivalent to the code to axis X (just under a different axis), so it is also correct. Finally, we conclude that your entire code is correct.