Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Circle/Rectangle Collision Detection Response Issue! #10

Open
GameDeveloperAf opened this issue Sep 24, 2019 · 4 comments
Open

Circle/Rectangle Collision Detection Response Issue! #10

GameDeveloperAf opened this issue Sep 24, 2019 · 4 comments

Comments

@GameDeveloperAf
Copy link

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 =>
collisiondetection

@GameDeveloperAf GameDeveloperAf changed the title Circle/Rectangle Collision Detection Response! Circle/Rectangle Collision Detection Response Issue! Sep 24, 2019
@jeffThompson
Copy link
Owner

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?

@GameDeveloperAf
Copy link
Author

GameDeveloperAf commented Sep 25, 2019

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:

  1. 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.
  1. 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;

@jeffThompson
Copy link
Owner

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.

@GameDeveloperAf
Copy link
Author

Not a problem! When you have time then add responses to your site!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants