Collision detection with SVG


Collision detection in SVG are really powerful. There are already SVG built in functions called getIntersectionList() and checkIntersection(). These function are not fully supported in all Browser, and they just check for bounding box collisions anyway. So we try to avoid these problems and build a simple collision detection by our own. Since SVG objects are Vector based, its really easy to to check for a collision of two objects with simple math.

  There are many different algorithms that may be used to perform collision detection, with different performance or accuracy outcomes.

 

simple collision detection

Basic bounding box collision detection, the fast way to detect collision. Each object on the screen have bounding boxes, which is the smallest rectangle in which the object fits exactly. With a simple math function is it possible to check if two of these rectangles overlap.

SVG_collisionAppears

 

As you can see, the collision detection is really inaccurately. Since we are just checking for the intersection of the Bounding boxes, this is an expected behavior. In some cases this might be enough for a collision detection.

 

advanced collision detection

Based of the simple bounding box collision, we create a more precise collision detection. We start to compute the precise collision detection only if a bounding box collision is detected. Once the basic collision detection appears, we define some points on the contour of the colliding objects, based on the precision value. To get these points we use the getPointAtLength() function. In this case, where we just have circles, we calculate the these points with some math.
A precision of 10 means, 10 points on the whole path to calculate if they are colliding with something. We test which of these points is inside the closed path of the colliding object, to check if a collision appears. More precision equals more points to compute.

 

Most of the code is used to display the debug lines, and it is not a very clean code either. The relevant part of the code is the isPointInPoly() function. We have to provide two variables to the function. The poly variable is an array of points with x and y positions which build a closed path. The pt variable is the position of the point which we want to check if it is inside the closed path or not. If so, a collision is detected.

 

conclusion

Basic vector collision detection made easy, decide by your own how precise and how fast collision detection appears. This is just the a basic example and let plenty of room for optimization. It highly depends on the precision value how much optimization is to implement.

  • Grzegorz Nowak

    (x – a)^2 + (y – b)^2 <= r^2 for circle, similar ellipse for point inside… collision 2 circle (cx1-cx2)^2 + (cy1-cy2) <= (r1 + r2)^2
    at now I look some info about cubic sort in collision in map to don't calculate many shapes to all shapes…

  • Ryan Verdel

    This is very impressive. Question: If there were multiple svg objects that I wanted to prevent from overlapping each other, how would I use this to do so when they hit?

  • markusT_inkfood

    Either you remove all velocity from the object once it detects a collision, or pass the velocity to the object which it collides with.

    Take look at this elastic collision example http://www.inkfood.com/elastic-collision/

    Hope that helps

  • fregat

    What am I doing wrong?

    Function isPointInPoly(poly, pt) work with tringles, bunt dont work with custom shapes, for exmaple:

    Triangle:

    [{“x”:”1039″,”y”:”79″},{“x”:”1115″,”y”:”168″},{“x”:”1115″,”y”:”82″}]

    Point:

    {“x”:1072.989990234375,”y”:94.54998779296875}

    Custom shape:

    [{“x”:”926″,”y”:”80″},{“x”:”791″,”y”:”129″},{“x”:”793″,”y”:”201″},{“x”:”909″,”y”:”205″}]

    Point:

    {“x”:867.7300415039062,”y”:128.22994995117187}”

    Hope for a hint

  • fregat

    it turned out that everything worked well

  • Devin F

    Very nice example! Good work.