Rectangle Collision detection

I’m making a brick breaker game. For collision detection I am using Rectangle.intersects(). I construct a new Rectangle from the Ball object, and Brick extends rectangle. My problem is that the collision points seem to be off set by a few pixles. When the ball collides with the top or left side of a brick it is colliding before it should and from the bottom and right side it is colliding later than it should. The pictures illustrate this. Here is the code for the brick detection method. This method is inside the Ball class. My question is why is this happening.

/**
 * Check for brick collisions and adjust ball direction.
 */
public void detectBrick(Level level) {
    Rectangle r1 = new Rectangle(x, y, radius * 2, radius * 2);
    for (Brick b: Level.theBricks) {
            if (r1.intersects(b)) {
                if (y > b.y && y < b.y + Brick.BHEIGHT)
                    dx = -dx;
                else if (x > b.x && x < b.x + Brick.BWIDTH)
                    dy = -dy;
                else {
                    dx = -dx;
                    dy = -dy;

                }

// level.remove(b); // remove the brick after its been hit
break;
}
}
}

I fixed it. I forgot that the x and y coordinates of the Ball are at its center.
Rectangle r1 = new Rectangle(x - radius, y - radius, 2 * radius, 2 * radius);

Instead of using instantiating a new Rectangle every time, it would be much faster to do this:


if (objA.x - objA.width /2 >= objB.x + objB.width /2 &&
    objA.y - objA.height/2 >= objB.y + objB.height/2 &&
    objA.x + objA.width /2 <= objB.x + objB.width /2 &&
    objA.x + objA.height/2 <= objB.y - objB.height/2)
    {
        //collision = true
    }

That is how I originally intended to do it. But I thought it would be easier just to have Brick and Paddle extend Rectangle that way I could just use the intersects() method. How much of a difference would it make? Is it worth recoding?

I have another question. The level in the picture is an ArrayList of Bricks. It is populated and drawn in a class called Level. I was wondering how I would go about creating other levels. I looked into Panel’s and layout managers, specifically grid layout, but it didn’t seem to work out. I wasn’t able to draw the same way I would add a component to the panel.

Each Brick knows its position and dimensions. But it seems like a lot of work using a coordinate system to create levels. Any thoughts?

I was thinking of doing something like this. Im not sure how to go about creating levels without writing each method manually.

public class Level {

private HashMap<Point, Point> thePoints;
private ArrayList<Block> theBlocks;

/**
 * Constructor.
 */
public Level() {
    thePoints = new HashMap<Point, Point>();
    theBlocks = new ArrayList<Block>();
    buildMap();
    
}

/**
 * Associate a set of coordinates for each block location. Each block 
 * location will be numbered by row and column.
 */
public void buildMap() {
    for (int i = 0; i < 16; i++) {
        for (int j = 0; j < 10; j++) {
            Point p1 = new Point(i, j);
            Point p2 = new Point(i * 20, j * 40);
            thePoints.put(p1, p2);
        }
    }
}

/**
 * Determine the block coordinates and create the Block.
 * @param i the row
 * @param j the column
 */
public void buildBlock(int i, int j) {
    Point p1 = new Point(i, j);
    Point p2 = thePoints.get(p1);
    Block b = new Block(p2.x, p2.y);
    theBlocks.add(b);
}

/**
 * A solid grid of blocks with a 3 space border.
 */
public void createLevel1() {
    for (int i = 3; i < 13; i++) {
        for (int j = 3; j < 7; j++) {
            buildBlock(i, j);
            
        }
    }
}

public void createLevel2() {
    }

/**
 * Draw the level to the canvas.
 * @param g the graphics object.
 */
public void draw(Graphics g) {
    g.setColor(Color.black);
    for (Block b: theBlocks) {
        g.drawRect(b.x, b.y, b.width, b.height);       
    }
}

}

If you’re just multiplying by 20 to get the translated point, I really don’t recommend using a HashMap to do that. Instead, just use a method.


Point getTransformedPoint(Point p)
{
    return new Point(p.x * 20, p.y * 20);
}

Something like that.

I also wouldn’t extend Rectangle. Instead if you want to use Rectangle, store one in the class’s fields. It doesn’t make sense to extend Rectangle because your classes aren’t actually shapes.

You would do something like this:


public class MyClass
{
    private Rectangle bounds;

    public Rectangle getBounds()
    {
        return bounds;
    }

    public boolean intersects(MyClass mc)
    {
        return bounds.intersects(mc.getBounds());
    }
}

Yeah I guess the map was kind of useless. I rewrote the collision detection using math instead of the rectangle intersection. I think I have more control this way as well. Since that was the only purpose of the rectangles I scrapped them as well.

Since im using a mouse motion listener to move the paddle I think im having problems when the paddle is moving faster than the ball. The paddle will intersect the ball before the ball has a chance to check and respond. All my collision detection is handled by the ball.

And I have another issue. The program is starting to get scattered. The more features and things I add the more unorganized it seems to get and sometimes im not sure where things should go and which classes should be handling what. I only have two semesters of java. Any suggestions? Should I read up on design patterns or something?