Search code examples
javajava-8collision-detectiongame-physicsrectangles

How to detect which side has been hit of a Rectangle in Java


I am making a game of Breakout in Java and I have come to the point where I need to be able to detect which side of the Brick has been intersected by the Ball. Currently I am using the intersects method, however this only detects intersections, not specifically which side has been hit. This is the method (I have added in some comments):

public boolean intersects(Rectangle r) {
    // The width of the Brick as tw
    int tw = this.width;
    // The height of the Brick as th
    int th = this.height;
    // The width of the given Rectangle as rw
    int rw = r.width;
    // The height of the given Rectangle as rh
    int rh = r.height;
    // Check if the given Rectangle or Brick does not exist
    if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) {

        // If not, then return false because there is nothing to collide/intersect
        return false;
    }

    // The x location of Brick as tx
    int tx = this.brickLocation.x;
    // The y location of Brick as ty
    int ty = this.brickLocation.y;
    // The x location of the given Rectangle as rx
    int rx = r.x;
    // The y location of the given Rectangle as ry
    int ry = r.y;

    // RW = RW + RX
    rw += rx;
    // RH = RH + RY
    rh += ry;
    // TW = TW + TX
    tw += tx;
    // TH = TH + TY
    th += ty;

    //      overflow || intersect
    return ((rw < rx || rw > tx) &&
            (rh < ry || rh > ty) &&
            (tw < tx || tw > rx) &&
            (th < ty || th > ry));
}

And I have now put this method into one of my classes and I am customizing it, however I am having trouble making it so that it detects which side has been hit because the final return statement is just so interconnected, you can't just take one of those lines, because in order for it to know where that side ends it needs to know the other sides, and that's what it does here, if it has intersected all of the sides (and no limit is put on the outreach of the sides - though of course visibly they are limited) then it returns true, and if not then not and it hasn't touched the shape because otherwise it would have done.

And what I would like to be able to do is to make it so that there are if statements which decide what int is returned (I will change its return type from boolean to int), and thus which side it has hit so that it can bounce off in the appropriate fashion. But because these are so interdependent I have no idea how to separate them:

    //      overflow || intersect
    return ((rw < rx || rw > tx) &&
            (rh < ry || rh > ty) &&
            (tw < tx || tw > rx) &&
            (th < ty || th > ry));

I have seen many similar questions here, but either they are in a different language, don't have any answers, or don't have any answers which answer the question and have been accepted. So I was wondering if anybody can suggest to me how I separate these so that it can detect which side has been hit, because I am out of ideas?
Or perhaps is there a Java method already which can do this for me and I don't have to override an already existing one? I have the latest version of the Oracle JDK 8.


Solution

  • One way you can do that is when moving the ball I assume you do something like this:

    ball.x += speedX;
    ball.y += speedY;
    

    You can turn that to this:

    ball.x += speedX;
    if (intersects(ball, brick))
    {
        //Ball touched brick on left/right side (depending if speedX is positive or negative)
    }
    ball.y += speedY;
    if (intersects(ball, brick))
    {
        //Ball touched brick on top/bottom side (depending if speedY is positive or negative)
    }