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:
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;
}
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:
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.