Share Your Code

point-rectangle collision detection

Posted by tetu, Posted on September 20, 2011

the routine detects the collision between a rectangle (rotated at an arbitrary angle) and a point (x,y)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
local function hitTest(rectangle,x,y)
        --coordinates of the four vertices
        local points={{-rectangle.width/2,-rectangle.height/2},{-rectangle.width/2,rectangle.height/2},{rectangle.width/2,rectangle.height/2},{rectangle.width/2,-rectangle.height/2}}
        local npoints={}                --coordinates of the four vertices for the rotated rectangle
        local positionVectors={}
        for i=1,#points do
                local c=math.cos(rectangle.rotation*math.pi/180)
                local s=math.sin(rectangle.rotation*math.pi/180)
                positionVectors[i]={rectangle.x+c*points[i][1]-s*points[i][2]-x,rectangle.y+s*points[i][1]+c*points[i][2]-y}
        end
        local vecs={}
        local combos={}
        for i=1,#points do
                if i~=#points do
                        combos[i]={i+1,i}
                else
                        combos[i]={1,#points}
                end
        end
        for i=1,#combos do
                vecs[i]={positionVectors[combos[i][1]][1]-positionVectors[combos[i][2]][1],positionVectors[combos[i][1]][2]-positionVectors[combos[i][2]][2]}
        end
        local sign=positionVectors[1][1]*vecs[1][2]-positionVectors[1][2]*vecs[1][1]
        local flag=true
        for j=2,4 do
                local nsign=positionVectors[j][1]*vecs[j][2]-positionVectors[j][2]*vecs[j][1]
                if sign*nsign<0 then
                        flag=false
                        break
                end
        end
        return flag
end

the points array holds the coordinates of the four vertices relative to the geometric center of the rectangle. the method can be used to detect collision between a point and any other convex polygon, as long as we know the coordinates of its vertices relative to its center.
for an isosceles right triangle whose hypotenuse is parallel to the x-axis, the points array would be:

1
points={{-triangle.width/2,triangle.height/2},{0,-triangle.height/2},{triangle.width/2,triangle.height/2}}


Replies

canupa.com
User offline. Last seen 2 weeks 3 days ago. Offline
Joined: 20 Jun 2011

awesome what you can do with just a little bit of math :) thanks

tetu
User offline. Last seen 16 weeks 6 days ago. Offline
Joined: 3 May 2010

cross products :)

line 25 should change to j=2,#points for non rectangular shapes