2
\$\begingroup\$

I am using this code to detect collisions between two rectangular sprites.

intersect: function(other) {
    return this.x < other.x + other.width && other.x < this.x + this.width &&
        this.y < other.y + other.height && other.y < this.y + this.height;
},

My question is how can I account for rotation of the sprite. This will only work with the

initial rotational position of the sprite.

Can someone point me in the right direction?

Thanks.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

Each rectangle has 4 corners and 4 sides. If either corner are within the boundaries of the 4 sides of the other rectangle, or if a diagonal of one rectangle cross a diagonal of the other, they collide.

First, calculate the positions of all the corners, if you know your geometry this shouldn't be too hard.

From here on, vector maths will make it all a lot simpler, go read on the topic if needed. For this purpose we need only points, vectors and the concept of dot products, you can leave the more advanced stuff for later.

Specifically the property that the dot product of two vectors is positive if the angle between them is acute, and negative if it is obtuse is needed.

Look at my beautiful drawing, the angle between vector a and b is acute, this tells us that the point b is pointing to is on the inner side of c. a and d has the opposite property, so d is pointing to a point outside the rectangle. Perform such a check for each of the 4 sides.

Freehand rectangle FTW!

For the crossing diagonal part, you can check if two line pieces intersect by constructing a quadrilateral first taking an endpoint from the first line, then one from the second line, then the other endpoint from the first line, and finally the other endpoint of the second line. If the figure is convex, the lines pieces intersect. To find if a polygon is convex, you can take the determinant of each side as a vector and the following side, if either all of the results are positive, or all negative the polygon is convex.

One of my previous answers might prove useful: Vector problem: which one is the left / centre / right one?

\$\endgroup\$
17
  • \$\begingroup\$ Does this work if one sprite is large enough and contains the other sprite completely? There's no edge intersection in this case. \$\endgroup\$ Dec 11, 2011 at 14:11
  • \$\begingroup\$ @davidluzgouveia Yes, this method does not use edge intersection, it checks if there are corner points of one rectangle within the other, which would still be the case if one rectangle enclose the other completely. And then there is the diagonals crossing check which sorts out a few special cases where the rectangles do overlap but all 8 corners stick out. \$\endgroup\$ Dec 11, 2011 at 14:37
  • \$\begingroup\$ I see. I'll need to try this approach next time as it sounds much easier for rectangles than implementing the separating axis theorem, which is what I have done before in this situation. As an added note, would this work for any convex polygon too? \$\endgroup\$ Dec 11, 2011 at 16:15
  • \$\begingroup\$ Actually I might have made it a bit rectangle specific, rather than the dot product of b and a you should use the determinant of b and c to check how b is positioned relative to c. The crossing diagonal check obviously needs to be replaced for non 4 sided polygons, you need each corner to be connected to a diagonal which is checked, and you need the entire set of diagonals to be directly or indirectly connected through crossing one another. \$\endgroup\$ Dec 11, 2011 at 17:18
  • \$\begingroup\$ OK I just read through your answer and I am still fully absorbing this info. I was hoping there was a way to do this that wasnt too complicated but, looking around no choice but to hunker down and figure out the math required. \$\endgroup\$
    – Ray_Garner
    Dec 11, 2011 at 23:12
1
\$\begingroup\$

Problem

Checking to see if a corner is included is an interesting approach, and will catch all collisions if the sprites are moving slowly enough, but it will miss some fast-moving thin sprites. Consider this case:

    o---o
    |   |b
    |   |
o---+---+-o
|   |   | |a
o---+---+-o
    o---o

Here, the tall rectangle b and the wide rectangle a clearly intersect, but neither contains any vertices other than its own.

Solution

The people behind the games N and N+ (Metanet Software) have a brilliant tutorial here -- the long and the short of it is to use the separate axis theorem; for each face on both shapes, compute the normal for that face and project both shapes onto that line

aaaaaa          Normal 1:  a
a    a                     a 
a    a  bbbbbb             ab  ] overlap by 2
aaaaaa  b    b             ab
        bbbbbb              b

Normal 2:
aaaaaa
        bbbbbb
      ^
      no overlap

If the two shapes overlap, then all of their projections will overlap. If the two shapes do not overlap, then at least one of their projections will not overlap.

You're halfway there already

You might note that testing for overlap in the projection is very similar to what you're already doing for non-rotated rectangles. That's because for aligned rectangles, there are only two normals to project onto -- the X and Y axes.

In any case, the Metanet folks did a great job, and have interactive demos, so definitely check that out. Here's the link again. Or if it's down, use the wayback or google cached copies.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the additional idea I am looking at SAT type collision detection. My problem lies in that I dont understand how to project the lines into the imaginary surface if you will. I am trying to though. Trying really hard \$\endgroup\$
    – Ray_Garner
    Dec 15, 2011 at 1:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .