0
votes

I've done my first BreakOut Game while completing an assignment for Stanford University CS Online Course for java.

However I noticed during play testing that when the ball sometimes hits a brick while travelling diagonally it ends up hitting several bricks in a row in a unnatural way.

I'm guessing I have to improve a bit my collision detection code and I tried several things already to no avail.

I'm using the ACM library for this program. An imaginary Rectangle surrounds my ball and I use the 4 corners of that rectangle to detect collision.

During the game, since I added several addons (items that drop and give you bonus) there are lot of velocity changes in the game - the vx variable change a lot.

I think this is related to my problem, because I noticed that it's when the ball travels at more speed than more of this several bricks destroyed in a row problem.

I´ll add the relevant code here. You can however check out all of the code here: https://gist.github.com/frodosda/5604272

// Defines the initial Direction of the Ball - inside the "MoveBall" Method
    vx = rGen.nextDouble(1.0, 3.0); // Random Horizontal Direction
    if (rGen.nextBoolean(0.5)) vx = -vx;
    vy = 2.0; // Vertical Direction

/** Checks if the ball collided or not with an object */

private void verificarColisaoBola () {

    GObject objColisao = getObjColisao(); // The object with wich the ball colided

    if (objColisao == raquete) { // If colidded with paddle
        vy = -vy; // Change vertical tranjectory of ball
        // prevents that the ball get "glued" to the paddle
        bola.setLocation(bola.getX(),bola.getY() - PADDLE_HEIGHT / 2);

        // Changes the direction of the ball when it hits the borders of the paddle - provides the player more control
        if ((bola.getX() < raquete.getX() + 0.20 * raquete.getWidth() && vx > 0)
            || (bola.getX() > raquete.getX() + 0.80 * raquete.getWidth() && vx < 0)) {
            vx = -vx;
        }

    } else if (objColisao != null) { // Colision with a brick
        remove (objColisao); // remove the brick
        nTijolos--; // counts one less brick
        vy = -vy; // Changes vertical direction
}

/** Finds if the limits of the ball - 4 corners - hits an object  
 * @return The object that collided with the ball - or null */

private GObject getObjColisao () {
    if (getElementAt (bola.getX(), bola.getY()) != null) { // Top left corner
        return getElementAt (bola.getX(), bola.getY());
    } else if (getElementAt (bola.getX() + bola.getWidth(), bola.getY()) != null) { // Top Right corner
        return getElementAt (bola.getX() + bola.getWidth(), bola.getY());
    } else if (getElementAt (bola.getX(), bola.getY() + bola.getWidth()) != null) { // Bottom Left corner
        return getElementAt (bola.getX(), bola.getY() + bola.getWidth());
    } else if (getElementAt (bola.getX() + bola.getWidth(), bola.getY() + bola.getWidth()) != null) { // Bottom Right corner
        return getElementAt (bola.getX() + bola.getWidth(), bola.getY() + bola.getWidth());
    } else {
        return null;
    }
}

Thanks in advance for your help!

1

1 Answers

0
votes

You need to check your time step. A velocity with large time steps will often cause objects to hit multiple items in the next time step. So make your time step smaller to make the collision detection occur more frequently.

You should also do some smarter analysis and check for the first brick you would have hit, ( the one with the max/min x or y value), then stop there. Then you will need to calculate the final location of the ball after this collision so that even with the large time step the ball acts like it should.