1

I'm experimenting with a simple Break Out clone to get an understanding of Game States, Game Loops etc.

One of the things I'm having difficulty with is the collision detection.

I have a GameItem class that is extended by Ball, Brick and Paddle. In this class I have a getBounds() method to return the bounding Rectangle of the object, a collision(GameItem item) method to determine whether 2 GameItem objects have collided as well as methods for hitTop(), hitBottom(), hitLeft() and hitRight() to determine which side the object collided with the other.

These methods are as follows:

public Rectangle getBounds()
{
    return new Rectangle(x, y, width, height);
}

public boolean collision(GameItem item)
{       
    return getBounds().intersects(item.getBounds());        
}   

public boolean hitTop(GameItem item)
{       
    return getY()+getHeight()>=item.getY();     
}

public boolean hitLeft(GameItem item)
{
    return getX()+getWidth()>=item.getX();
}   

public boolean hitBottom(GameItem item)
{
    return getY()<=item.getY()+item.getHeight();
}

public boolean hitRight(GameItem item)
{
    return getX()<=item.getX()+item.getWidth();
}

The ball class has a method called checkBallCollissions(GameItem item) to determine when the ball has hit another object. This is as follows:

public boolean checkBallCollisions(GameItem item)
{
    if(this.collision(item))
    {
        if(this.hitTop(item))
        {
            this.setVY(-1*this.getVY());
            return true;
        }
        else if(this.hitBottom(item))
        {
            this.setVY(-1*this.getVY());
            return true;
        }
        else if(this.hitLeft(item))
        {
            this.setVX(-1*this.getVX());
            return true;
        }
        else if(this.hitRight(item))
        {
            this.setVX(-1*this.getVX());
            return true;
        }
        return false;
    }
    return false;
}

Which would be called as follows:

ball.checkBallCollisions(paddle);

As you can see, if it hits one of the 4 edges, the x/y direction is reversed accordingly.

However, this doesn't work. Analysing the code it seems there's an obvious issue that I can't fathom a solution to.

The 3 images below show a collision of the ball with an object from above, below and the right.

enter image description here enter image description here enter image description here

With the code as it is, it first detects a collision based on the bounding Rectangles and the intersects() method. It then determines which side it hit. If it hits from above it works. However, when it hits form the bottom or right then hitTop() will return true since getY()+getHeight()>=item.getY() is true for both these cases (i.e the bottom edge of the ball has a greater y value than the top edge of the object it's colliding with).

What conditions am I missing to resolve this and have perfect collision detection?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
nvaughan84
  • 463
  • 6
  • 13

2 Answers2

0

for circles you use the circle's radius rather than bounds, as bounds is a rectangle. i believe there are methods for doing that in java but i do not know them yet, so a little research should do it.

also, for advanced collision people tend to use vectors, again i never fiddled with them before so you will have to research that as well.

here is something to get you going:

Java area and intersection

bakriawad
  • 345
  • 2
  • 10
0

The issue here is that as you mentioned "hitTop() will return true since getY()+getHeight()>=item.getY() is true for both these cases (i.e the bottom edge of the ball has a greater y value than the top edge of the object it's colliding with)."

In order to fix this you also need a check to ensure that the y position of the circle is less than the y position of the gameobject + height of gameobject (possibly subtracting some offset from it as well).

Which should look something like this (not worrying about offset):

public boolean hitTop(GameItem item)
{       
    return getY() + getHeight() >= item.getY() && 
        getY() < item.getY() + item.getHeight();     
}

You will need to do this for all of the collisions.

Aflah Bhari
  • 108
  • 2
  • 6