Search code examples
c++mathcollision-detection

2D Collision Detection Code


Does anyone know a very simple physics engine, or just a set of basic functions that could complete these tasks: Simple point, line, and rectangle collision detection? I looked at Box2D but it is way too advanced for what I am making. I just need some simple code. Thanks in advance!


Solution

  • Here's my shot at point/line collision detection. The important thing is to avoid trig functions, divisions, and other expensive operations so as not to slow things down too much.

    As GMan's comment notes, you need to bear in mind that the point will be moving. So you'll have the current position of the point (let's call it A) and the possible new position of the point (B). You need to find out if, when the point moves from A to B, it would collide with a line.

    Let's call the start and end points of the line C and D. A collision will occur only if the lines AB and CD intersect.

    Let's describe the line AB using the standard equation Ux + Vy + W = 0. After some algebra, the equation comes out as:

    (ay - by) x + (bx - ax) y + ax by - bx ay = 0
    

    We can describe the line CD in terms of a parameter t and constants X Y U V:

    x = X + Ut
    y = Y + Vt
    

    It's helpful if we set t=0 at point C, and t=1 at point D. By considering t=0 we can work out X and Y. And by considering t=1 we can work out U and V. This gives

    x = cx + (dx - cx) t
    y = cy + (dy - cy) t
    

    To find the intersection point of the two lines, substitute these into the equation we found for AB, which gives

    (ay - by) (cx + (dx - cx) t) + (bx - ax) (cy + (dy - cy) t) + ax by - bx ay = 0
    

    This reduces to

    t = (ax by - bx ay + bx cy - cx by + cx ay - ax cy) / q
    

    where q = (ay - by)(cx - dx) - (ax - bx)(cy - dy)

    • If q is zero, the lines are parallel and do not meet.
    • If 0 < t < 1 then the line extrapolated from AB intersects CD.

    But we still don't know that this intersection is actually between the points A and B. So we need to repeat all the previous steps, swapping AB and CD, and writing the line AB in terms of a parameter s. This gives:

    s = (cx dy - dx cy + dx ay - ax dy + ax cy - cx ay) / q
    
    • If 0 < s < 1 then the line extrapolated from CD intersects AB.

    That's it. So in your code you start by calculating q. If q is zero then the lines are parallel. Otherwise, go on to calculate t and s. If 0 < t < 1 and 0 < s < 1 then a collision is about to happen. To find the location of the collision, substitute t or s back into the original equations for CD.

    For extra speed you can remove the divisions by q - it's possible to just check whether the top half of each fraction is in the correct range, and then each check should only need 10 multiplication operations.