CollisionDetection
CollisionDetection copied to clipboard
Circle/Rectangle Collision Detection Response Issue!
There is no problem with the collision detection test! It works! But there is not a collision detection response! I want that when the circle touches the square, and the circle must stay outside of the rectangle! Image =>

There is a response! Or, more specifically, the functions return true if there is collision but it's up to you to do something with it.
The Circle/Rectangle function from here:
boolean circleRect(float cx, float cy, float radius, float rx, float ry, float rw, float rh) {
// temporary variables to set edges for testing
float testX = cx;
float testY = cy;
// which edge is closest?
if (cx < rx) testX = rx; // test left edge
else if (cx > rx+rw) testX = rx+rw; // right edge
if (cy < ry) testY = ry; // top edge
else if (cy > ry+rh) testY = ry+rh; // bottom edge
// get distance from closest edges
float distX = cx-testX;
float distY = cy-testY;
float distance = sqrt( (distX*distX) + (distY*distY) );
// if the distance is less than the radius, collision!
if (distance <= radius) {
return true;
}
return false;
}
That final return statement sends back a boolean depending on if there is collision or not. In the example, it sets the value hit.
If I understand correctly, you want to keep the circle from entering the square. If it's moving automatically, you could just not update the position if there is a hit.
// check if current circle position + its speed is hitting...
boolean hit = circleRect(cx+circleSpeedX, cy+circleSpeedY, sx,sy, sw,sh);
// only if it is not hitting, update it's position
if (!hit) {
cx += circleSpeedX;
cy += circleSpeedY;
}
If you wanted the circle to bounce back, you'd need to do something like:
if (!hit) {
circleSpeedX *= -1; // reverse direction
circleSpeedY *= -1;
cx += circleSpeedX;
cy += circleSpeedY;
}
To do this with a mouse will be a little trickier – probably using pmouseX and pmouseY. If you want to get the circle to rub along the edge of the square, that will take a lot more work and might require something like Box2D.
Does that answer your question?
Thanks for replying. I know this method. The circle rubs along the edge of the square with your method, as I wanted, it's worked. But It's not an accurate method! Because when I change the speed and the circle stays far away from the square more than before.
Your method means that when the circle touches to the square and then, minus Circle's Speed from the Circle's X and Y position. Yeah, it works a little bit correct just with a small speed. But When I change the speed a little bit of the circle and then it returns with the different wrong value! You can see in this video => https://www.youtube.com/watch?v=h_ti1cx5tCA&feature=youtu.be Please watch without skipping, This response is not accurate!
// The circle rubs along the edge of the square in this method as I wanted. It's worked, but it's not accurate.
if (distance <= radius)
{
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS))
{
circlePos.x += circleSpeed;
circlePos.y += circleSpeed;
}
}
I used your method in Square/Square and Circle/Circle before, and then I saw that this is not an accurate way for a response. And I left this way! I do not use this method! Please visit my website => http://learngraphx.byethost12.com/opengl-17.html and there you will see Circle to circle collision detection with a response in another method. I could use it with your method in Circe/Circle too, but it's not accurate, but I used another way for Square/Square and Circle/Circle Collision Detection Response, please check out my website, and you can see, and scroll down to watch the result of Circle/Circle Collision Detection Response in my website!
Below you can see, my responses methods for Square/Square and Circle/Circle:
- I used this method for Square/Square Collision Detection Response. Code for Square/Square:
// When I pressed W:
firstSquarePosition.y = secondSquarePosition.y + secondSquareMinVertex - firstSquareMaxVertex;
// When I pressed S:
firstSquarePosition.y = secondSquarePosition.y + secondSquareMaxVertex - firstSquareMinVertex;
// When I pressed A:
firstSquarePosition.x = secondSquarePosition.x + secondSquareMaxVertex - firstSquareMinVertex;
// When I pressed D:
firstSquarePosition.x = secondSquarePosition.x + secondSquareMinVertex - firstSquareMaxVertex;
// As you can see that I could use it as your method, but that method is not accurate.
- I used this way for Circle/Circle Collision Detection Response. Code for Circle/Circle:
// Firstly, I get the distance between the circle's centers
// And then I used the Pythagorean Theorem to compute the distance.
float xDistance = glm::abs(firstCirclePosition.x - secondCirclePosition.x);
float yDistance = glm::abs(firstCirclePosition.y - secondCirclePosition.y);
float distance = glm::sqrt(xDistance * xDistance + yDistance * yDistance);
// Then I defining unit X and unit Y. Another name is "I normalized them". I divided xDdistance and yDistance to distance
float xNormalise = xDistance / distance;
float yNormalise = yDistance / distance;
// The next step is calculating for response
// When I pressed S or A. This is for the Upper Right Side:
firstCirclePosition.x = secondCirclePosition.x + (firstCircleRadius + secondCircleRadius) * xNormalise;
firstCirclePosition.y = secondCirclePosition.y + (firstCircleRadius + secondCircleRadius) * yNormalise;
// When I pressed S or D. This is for the Upper Left Side:
firstCirclePosition.x = secondCirclePosition.x - (firstCircleRadius + secondCircleRadius) * xNormalise;
firstCirclePosition.y = secondCirclePosition.y + (firstCircleRadius + secondCircleRadius) * yNormalise;
// When I pressed W or D. This is for the Lower Left Side:
firstCirclePosition.x = secondCirclePosition.x - (firstCircleRadius + secondCircleRadius) * xNormalise;
firstCirclePosition.y = secondCirclePosition.y - (firstCircleRadius + secondCircleRadius) * yNormalise;
// When I pressed W or A. This is for the Lower Right Side:
firstCirclePosition.x = secondCirclePosition.x + (firstCircleRadius + secondCircleRadius) * xNormalise;
firstCirclePosition.y = secondCirclePosition.y - (firstCircleRadius + secondCircleRadius) * yNormalise;
And as you can see that I used another method for Square/Square and Circle/Circle Collision Detection for Response! And it did not take a lot more work as you said. In my response methods if I change the speed of the circle or square and still it returns a correct value with my methods in Square/Square and Circle/Circle, but with your methods returns a different wrong value each time when I change the speed. I made Square/Square, Circle/Circle collision detection with correct responses, and now I have stuck in Circle/Square Collision Detection Response. I can not figure out how to calculate for the Circle/Square Collision Detection Response. I want an accurate method for Circle/Square Collision Detection Response like mine responses! For example like this:
// This is just an example, this is not the right calculating. I want to show that I want calculate the for Circle/Square response like this method! I hope that you understood what I meant!
circlePos.x = squarePos.x + (radius + squareWidth + sqaureHeight) * xNormalise;
circlePos.y = squarePos.y + (radius + squareWidth + sqaureHeight) * yNormalise;
I'm going to have to take a look at your post a little more closely when I have a minute, but I think you're describing the "bullet through paper problem." If the step of your object (speed) is too far, it can miss triggering the collision. It's mentioned at the bottom of this example in the book and has been on my list of things to add to the site when I have time. For now, you could try the resources I've listed there for potential solutions.
Not a problem! When you have time then add responses to your site!