Circle and Rectangle collision

前端 未结 1 2019
攒了一身酷
攒了一身酷 2020-12-22 02:42

I have a program in Processing for a bouncing ball and a rectangle. I can get the collision for the sides of the rectangle correct, but I have no idea how to get the corners

相关标签:
1条回答
  • 2020-12-22 03:23

    The problem isn't that you need to detect the corner collision. The problem is that you current collision detection doesn't move the ball to a side when a collision is detected.

    Call frameRate(5) in your setup() function to better see what's going on:

    bad collision

    Notice that the ball intersects the top of the box, so you multiply the vy variable by -1. That causes the circle to start moving up. But the next frame, the circle is still colliding with the rectangle, because it hasn't moved up enough yet. So your code detects that collision, multiples vy by -1 again, and the ball moves back down. Next frame the same thing happens, until the ball eventually stop colliding with the rectangle.

    To fix this problem, when you detect a collision, you need to move the ball so that it's no longer colliding with the rectangle in the next frame.

    Here is an example of how to do that for the top side:

    if (circleY + radius > mouseY - boxH && circleX > mouseX - boxW && circleX < mouseX + boxW) { 
        vy *= -1; //top
        circleY = mouseY-boxH-radius;
    }
    

    good collision

    You'll have to add similar logic for the other sides, but the general idea is the same: make sure that the ball will not be colliding in the next frame, otherwise it'll keep bouncing on the edge like that.

    Edit: Taking a closer look at your collision logic, something is still off: you're only ever checking three sides, when you really should be checking all four sides.

    Let's take this one for example:

    if (circleY + radius > mouseY - boxH && circleX > mouseX - boxW && circleX < mouseX + boxW){ 
        println("top");  
        vy *= -1; //top
    }
    

    You're checking that the ball is below the top of the rectangle, to the right of the left of the rectangle, and to the left of the right of the rectangle. That's going to be true for this case:

    no collision

    Add a println() statement to each of your if statements (see the example in the if statement above) and notice what happens when the ball is below the paddle, or to the right of the paddle.

    You need to refactor your logic so that you're checking all four sides, not just three. If I were you, I'd write a function that takes the next position of the ball and returns a boolean value of true if that position collides with the rectangle. Then you can check before moving the ball on the X and Y axis, which tells you how to bounce. Something like this:

      if (collides(circleX + vx, circleY)) {
        vx*=-1;
      } 
      else {
        circleX += vx;
      }
      if (collides(circleX, circleY + vy)) {
        vy*=-1;
      } 
      else {
        circleY += vy;
      }
    

    This takes the place of your four separate if statements, and it solves your above problem as well.

    0 讨论(0)
提交回复
热议问题