4
\$\begingroup\$

I just want to see if any part of one "rectangle" overlaps the other. Is this the correct code?

 bool checkCollide(int x, int y, int oWidth, int oHeight, int x2, int y2, int o2Width, int o2Height){
    bool collide;
    collide = false;

    if(x >= x2 && x <= x2+o2Width && y >= y2 && y <= y2+o2Height){
        collide = true;
    }

    if(x+oWidth >= x2 && x+oWidth <= x2+o2Width && y >= y2 && y <= y2+o2Height){
        collide = true;
    }

    if(x >= x2 && x<= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height){
        collide = true;
    }

    if(x+oWidth >= x2 && x+oWidth <= x2+o2Width && y+oHeight >= y2 && y+oHeight <= y2+o2Height){
        collide = true;
    }   
    return collide;
}
\$\endgroup\$
1
  • \$\begingroup\$ Is it meant to work for x and y less than zero also? \$\endgroup\$
    – Peter K.
    May 21 '11 at 15:42
8
\$\begingroup\$

No, this is not correct; it only verifies whether the vertices of one rectangle are inside the other, not the other way around. Try calling it with the following parameters:

checkCollide(2,2,4,4, 1,3,2,2);
checkCollide(1,3,2,2, 2,2,4,4);

They should print the same result, but they don't. This case can be seen in the picture below.enter image description here

Update: even if you repeat the checks changing x/x2, y/y2, etc, this still won't catch all the cases: two rectangles may intersect even if none of their vertices are inside the other rectangle - see the other picture below.

enter image description here

A more generic solution should use a segment intersection routine to check whether for all segments in one rectangle whether they intersect with any the segments on the other one.

\$\endgroup\$
3
\$\begingroup\$

Besides the correctness of the code, since this is a code review site I'd also point out that it can be rewritten to make it more readable. I'd say your code (which is incorrect, see my other answer), would be easier understood if you were explicit about the intent of each if statement (i.e., is the point inside a rectangle). Below is a version of the code which IMO is a lot more readable (and happens to be smaller).

    bool isInside(int pointX, int pointY, int rectX, int rectY, int rectWidth, int rectHeight)
    {
        return
            (rectX <= pointX && pointX <= rectX + rectWidth) &&
            (rectY <= pointY && pointY <= rectY + rectHeight);
    }

    bool checkCollide(int x, int y, int oWidth, int oHeight, int x2, int y2, int o2Width, int o2Height)
    {
        bool collide =
            isInside(x, y,                    x2, y2, x2 + o2Width, y2 + o2Height) ||
            isInside(x + oWidth, y,           x2, y2, x2 + o2Width, y2 + o2Height) ||
            isInside(x, y + oHeight,          x2, y2, x2 + o2Width, y2 + o2Height) ||
            isInside(x + oWidth, y + oHeight, x2, y2, x2 + o2Width, y2 + o2Height);

        return collide;
    }
\$\endgroup\$
1
\$\begingroup\$

Firstly, I suggest the use of Rect structs/objects to hold rectangles rather then passing a whole bunch of parameters.

Secondly, the algorithm is simpler then that.

Imagine the problem in 1D. You want to know whether two lines collide:

----------------------------|
         |----------------------------

The lines collide if the second starts after the first begins, and the first begins after the second starts.

To check for 2D collision just check for 1D collision in both x/y. If they both collide so do the rectangles.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.