Simple quick 2d collision detections for Circle/Rectangle/Polygon

Started by
5 comments, last by oliii 14 years, 9 months ago
Hey, Im having to write a lightweight and simple library in C# that handles collision detections for Circle/Rectangle/Polygon classes. Each one has to implement the following methods from the ICollisionHandler interface: - bool Contains(Point Position); - bool Intersects(ICollisionHandler CollisionHandler); As its for silverlight i cant rely upon alot of the stuff in the .net library so i just wanted to make my own quick implementations. Im pretty sure the circle collision detection for intersects was to add up the distance and the radiuses then /2 and compare it to the radius of one of the circles or something, but i cant remember off top of my head. Had a quick look but to be honest ive just moved house and im leeching off someone elses hub, and connection keeps dying. So if anyone can just reel off some code then thats brilliant! but im not expecting it, so any *specific* articles would be great. Contains should be fairly simple i would imagine, but i need to support the following Intersects: - Circle With Polygon - Circle With Rectangle - Circle With Circle - Rectangle With Polygon - Rectangle With Rectangle Dont need polygon with polygon... its currently holding me up on a project im working on while my net is off. Its kinda like a 2d map editor but the user can draw trigger areas (the above shapes) and then save them out to the file with some other data, then in the game it needs to check for collisions with them... Ive already done all the other work, like setting up the quadtree and seperating out all the triggers and things so its just adding these methods and im good to go! Any help would be great!
Advertisement
Discrete, I'm assuming? Or continuous? Also, do you only need a Boolean result, or do you need other info as well (e.g. contact points, penetration vector, time of collision, etc.)?
This should sort it out, for every tests you need, including polygon-polygon.

Everything is better with Metal.

Hey,

As i said above it implements an interface that just returns a bool for a contains check and an intersects check.

Doesnt need to be fancy just needs to be handed a circle/rectangle/polygon and tell you if it intersects or not (well if using the intersect method) or if using contains method it just sees if the given point is within the objects area...

Although its always going to be an ICollisionHandler internally it would check to see what type it is... so here would be a typical circle class:

public class Circle : ICollisionHandler{   // Private members   private double m_X, m_Y, m_Radius;   // Public properties for all members   ...   // The collision handler implemented methods   public bool Contains(Point Position)   {       // See if the point is contained within the circle       // then return true if it is or false if not   }   public bool Intersects(ICollisionHandler Entity)   {       if(Entity is Circle)       {            // Do circle vs circle intersection and return true if            // they intersect or false if not       }       else if(Entity is Rectangle)       {            // Do circle vs rectangle intersection       }       else if(Entity is Polygon)       {            // Do circle vs polygon intersection       }       return false; // wasnt any of above so no collision   }}


Hope that clears things up, and thanks for the quick response. It doesnt need to be 100% accurate, although the more accurate the better :D
Quote:As i said above it implements an interface that just returns a bool for a contains check and an intersects check.
Your post was fairly clear, but the questions were worth asking.

The only mention of 'bool' I see is in the function return values, but that doesn't necessarily mean that no other information need be computed (for example, a module could cache contact information when a collision occurs, and then make it available upon request).

Also, although your post strongly suggests that the tests are to be discrete rather than continuous, I don't see this specified anywhere in your post, and when requesting code or references related to collision detection this is one of the very first things you'll want to specify.

In any case, I'm guessing oliii's link has the info you need (although the link appears to be broken currently...).
Thanks for the response, will check out that link and would be great to have polygon vs polygon collision, just didnt want to complicate things... for some reason the page wont load keeps timing out or something, but this net connection is balls... so hopefully i can try and drive round the neighbourhood trying to find a more solid connection to view it :D
hmmm yes it's down. weird...

if you have a convex polygon (rectangle, oriented rectangle, triangle, polygon with no concave angles), it's quite simple.

Vector vectorSub(const Vector& a, const Vector& b){    Vector c(a.x-b.x, a.y-b.y);    return c;}float vectorDot(const Vector& a, const Vector& b){    float  d = a.x*b.x + a.y*b.y;    return d;}float vectorLength(const Vector& a){    float length_squared = a.x*a.x + a.y*a.y;    return sqrt(length_squared);}Vector vectorPerp(const Vector& a){    Vector p(-a.y, a.x);    return p;}// project polygon along an axis, and find it's dimensions.void polygonInterval(const Vector& axis, const Vector* a, int anum, float& min, float& max){    min = max = vectorDot(a[0], axis);    for(int i = 1; i < anum; i ++)    {        float d = vectorDot(a, axis);;        if(d < min) min = d;        else if (d > max) max = d;    }}// project slphere along an axis, and find it's dimensions.void sphereInterval(const Vector& axis, const Vector& c, float r, float& min, float& max){    float length = vectorLength(axis);    float cn = vectorDot(axis, c);    min = cn - (r * length);    max = cn + (r * length);}bool collidePolygonPolygonAxis(const Vector& axis, const Vector* a, int anum, const Vector* b, int bnum){    float mina, maxa;    float minb, maxb;    polygonInterval(axis, a, anum, mina, maxa);    polygonInterval(axis, b, bnum, minb, maxb);       return (mina <= maxb && minb <= maxa);}bool collidePolygonPolygon(const Vector* a, int anum, const Vector* b, int bnum){    for(int i = 0, j=anum-1; i < anum; j=i, i++)    {        Vector edge = vectorSub(a, a[j]);        Vector axis = vectorPerp(edge); // perpendicular to edge             if(!collidePolygonPolygonAxis(axis, a, anum, b, bnum))             return false;    }    for(int i = 0, j=bnum-1; i < bnum; j=i, i++)    {        Vector edge = vectorSub(b, b[j]);        Vector axis = vectorPerp(edge); // perpendicular to edge             if(!collidePolygonPolygonAxis(axis, a, anum, b, bnum))             return false;    }    return true;}bool collidePolygonSphereAxis(const Vector& axis, const Vector* a, int anum, const Vector& c, float r){    float mina, maxa;    float minb, maxb;    polygonInterval(axis, a, anum, mina, maxa);     sphereInterval(axis, c, r, minb, maxb);       return (mina <= maxb && minb <= maxa);}bool collidePolygonSphere(const Vector* a, int anum, const Vector& c, float r){    for(int i = 0, j=anum-1; i < anum; j=i, i++)    {        Vector edge = vectorSub(a, a[j]);        Vector axis = vectorPerp(edge); // perpendicular to edge             if(!collidePolygonSphereAxis(axis, a, anum, c, r))             return false;    }    for(int i = 0; i < anum; i++)    {        Vector axis = vectorSub(c, a);        if(!collidePolygonSphereAxis(axis, a, anum, c, r))             return false;    }    return true;}


you can treat your rectangle as a polygon with four corners.

Everything is better with Metal.

This topic is closed to new replies.

Advertisement