# collision between a rect and a circle?

• 05-13-2010, 10:21 PM
CyanPrime
collision between a rect and a circle?
Okay, I'm trying to create a method to handle collisions between a rect and a circle. this is how far I've gotten, but now I'm stumped. It only works properly if px and py < the circles center. The code is in Java, but once I get it working I will port it to c++. It shouldn't be hard to understand though.

Here's the method
Code:

```    public boolean col(){             float planeAngle = (float) Math.toDegrees(Math.atan2(px - (px + pwidth), -(py - py)));             float planeWidth = rotate(px + pwidth,py + pheight, px,py,planeAngle,true);             float planeHeight = rotate(px + pwidth,py + pheight, px,py,planeAngle,false);             float planeCentX = (planeWidth/2);             float planeCentY = (planeHeight/2);                         float dist = (float) Math.sqrt(Math.pow((bx + (bsize/2)) - planeCentX, 2) + Math.pow(-((by + (bsize/2)) - planeCentY), 2));             if(dist <= (bx + (bsize/2)))                     return true;                                 else                     return false;     }```
and here is the full source: (requires slick)
Code:

```import org.newdawn.slick.AppGameContainer; import org.newdawn.slick.BasicGame; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; public class ColTest extends BasicGame{             float px = 50;         float py = 50;         float pheight = 50;         float pwidth = 50;                 float bx = 200;         float by = 200;         float bsize = 200;                 float pspeed = 3;     Input input;         public ColTest()     {         super("ColTest");     }       @Override     public void init(GameContainer gc)                         throws SlickException {             }     @Override     public void update(GameContainer gc, int delta)                         throws SlickException         {             input = gc.getInput();                         try{                            if(input.isKeyDown(Input.KEY_UP))                                py-=pspeed;                                         if(input.isKeyDown(Input.KEY_DOWN))                                py+=pspeed;                                         if(input.isKeyDown(Input.KEY_LEFT))                                px-=pspeed;                                         if(input.isKeyDown(Input.KEY_RIGHT))                                px+=pspeed;             }                         catch(Exception e){}         }       public void render(GameContainer gc, Graphics g)                         throws SlickException     {                            g.drawString("col: " + col(), 10, 10);                     g.fillRect(px, py, 50, 50);                     g.fillOval(200, 200, 200, 200);     }         public boolean col(){             float planeAngle = (float) Math.toDegrees(Math.atan2(px - (px + pwidth), -(py - py)));             float planeWidth = rotate(px + pwidth,py + pheight, px,py,planeAngle,true);             float planeHeight = rotate(px + pwidth,py + pheight, px,py,planeAngle,false);             float planeCentX = (planeWidth/2);             float planeCentY = (planeHeight/2);                         float dist = (float) Math.sqrt(Math.pow((bx + (bsize/2)) - planeCentX, 2) + Math.pow(-((by + (bsize/2)) - planeCentY), 2));             if(dist <= (bx + (bsize/2)))                     return true;                                 else                     return false;     }         public float rotate(float x, float y, float ox, float oy, float a, boolean b)     {         float dst = (float) Math.sqrt(Math.pow(x-ox,2.0)+ Math.pow(y-oy,2.0));         float oa = (float) Math.atan2(y-oy,x-ox);         if(b)                 return (float) Math.cos(oa + Math.toRadians(a))*dst+ox;         else                 return (float) Math.sin(oa + Math.toRadians(a))*dst+oy;     }         public static void main(String[] args)                         throws SlickException     {         AppGameContainer app =                         new AppGameContainer( new ColTest() );           app.setShowFPS(false);         app.setAlwaysRender(true);         app.setTargetFrameRate(60);         app.setDisplayMode(800, 600, false);         app.start();     } }```
• 05-13-2010, 11:22 PM
slicer4ever
the idea for rect->circle collision, is to make the rect into a circle, which can sound confusing at first, but truely isn't that complicated, i'll outline the steps, and let you figure out the code:

Part 1 - get the radius to the edge of the rectangle that is closest to circle
1. Get Angle from Rect->circle(center of rect)
2. Find what side the angle touchs on the Rect(i.e if u draw a line between the circle and the center of the rectangle, what side does it touch?)
3. Find the distance from the center to the side the line is touching(leg a)
4. Find the Angle between the leg a and the line between the rect+circle
5. Subtract 90 from the angle u just found
6. use law of sines to find the radius( R = LegA/sin(AngleFromStep5) )
Part 2 - Do circle-circle collision
1. find distance between both objects
2. subtract distance from the R u just found, and the circle's radius
3. if <= 0 u have collision

if anyone else has a better or more efficent method, please post, i thought of this one when i was making my game impact
that's about all u have to do
• 05-15-2010, 07:45 AM
Davee
I'm no game developer or maths expert but this is what I'd do.

1) Calculate which side is closest to the circle, if it's a corner, jump to step 7.
2) Get the gradient of this side.
3) Get the perpendicular gradient of this side.
4) Get the equation of a straight line through the circle center with this gradient. This will get the line with the shortest distance.
5) Get the co-ordinates of intersection of this line with the side.
6) If the co-ordinates are beyond the ranges of the straight line, then there is NO collision.
7) With this co-ordinate, find the magnitude of circle-centre->side.
8) if magnitude >circle radius, no collision else collision.

Not sure if this a good method.