3
\$\begingroup\$

Ok so this is for a small uni project. My lecturer provided me with a framework for a simple brickbreaker game. I am currently trying to overcome to problem of detecting a collision between the two game objects. One object is always the ball and the other objects can either be the bricks or the bat.

public Collision hitBy( GameObject obj )
{
    //obj is the bat or the bricks
    //the current object is the ball

    // if ball hits top of object
    if(topX + width >= obj.topX && topX <= obj.topX + obj.width &&
       topY + height >= obj.topY - 2 && topY + height <= obj.topY){
        return Collision.HITY;
    }

    //if ball hits left hand side
    else if(topY + height >= obj.topY && topY <= obj.topY + obj.height &&
            topX + width >= obj.topX -2 && topX + width <= obj.topX){
        return Collision.HITX;
    }

    else return Collision.NO_HIT;
}

So far I have a method that is used to detect this collision. The the current obj is a ball and the obj passed into the method is the the bricks. At the moment I have only added statement to check for left and top collisions but do not want to continue as I have a few problems.

The ball reacts perfectly if it hits the top of the bricks or bat but when it hits the ball often does not change directing. It seems that it is happening toward the top of the left hand edge but I cannot figure out why.

I would like to know if there is another way of approaching this or if people know where I'm going wrong.

Lastly the collision.HITX calls another method later on the changes the x direction likewise with y.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Check out this post it may give you a little insight on this matter stackoverflow.com/questions/401847/… \$\endgroup\$
    – Savlon
    Mar 18, 2013 at 2:29
  • \$\begingroup\$ What game engine (framework) do you use ? Libgdx has a very comfortable tool, ContactListener, that elaborates the collisionvery well. \$\endgroup\$
    – Ion Farima
    Mar 18, 2013 at 9:04
  • 1
    \$\begingroup\$ FWIW, a full solution can be found in code.google.com/p/android-breakout . The collision detection code is extensively commented (start in moveBall(); most relevant bit is findFirstCollision().). \$\endgroup\$
    – fadden
    Nov 24, 2014 at 19:21

5 Answers 5

1
\$\begingroup\$

It doesn't change the direction because you didn't handle it.. you want something like ball bouncing

take a look at this example :

NOTE: I know you asked it for android/java but I did it in c# it was an assignement in WinForms :) but just look maybe it'll give some idea

 public void moveBall(Rectangle r)
 {
       x = ballLocation.X + vX;   // x and y are the new coordinate of the ball
       y = ballLocation.Y + vY;

       if (x + diameter > r.Width) // when the ball moves right and hits the right              
                                   // border of the form
       {
           // vX is the ball velocity on X axis
           // set new velocity on x axis but convert it to negative
           // so the ball will move left
           vX = new Random().Next(minVelocity, maxVelocity);
           vX = -vX;
       }
       else if (x < 0) // when the ball move left and hits the left border
       {
           // set new velocity (Note that I didn't convert it to negative 
           // because i'm getting a positive value)
           vX = new Random().Next(minVelocity, maxVelocity);
       }

       if (y + diameter > r.Height) // when the ball hits the bottom border of the  
                                    //form
       {
           // vY is the ball velocity on Y axis
           // set new velocity and convert it to negative 
           // so the ball will move up
           vY = new Random().Next(minVelocity, maxVelocity);
           vY = -vY;
       }
       else if (y < 0) // when the ball hits the upper border of the form
       {
           // set new velocity on Y axis
           // so the ball will move down
           vY = new Random().Next(minVelocity, maxVelocity);
       }
        // set the ball location to the new values
        ballLocation = new Rectangle(x, y, diameter, diameter);
    }   

Note : in all screens no matter if it's phone or pc or tv screen, the upper left corner is (0,0,RGB) means -> pixel which construct from point and one of the colors :RED ,GREEN,BLUE. So if you want to move object to :

Right:

add value to x axis

Left :

subtract value to x axis

Down:

add value to y axis

Up:

subtract value to y axis

\$\endgroup\$
1
  • \$\begingroup\$ And the corner then? \$\endgroup\$
    – super
    Mar 21, 2014 at 19:09
1
\$\begingroup\$

So from what I understand your coordinate system's origin is at the top left of the screen.

I think you need to get rid of your magic number in your IF statements first (I also split it up into two IF statements, easier to read):

// if ball hits top of object
if(topX + width >= obj.topX && topX <= obj.topX + obj.width) {
    if(topY + height >= obj.topY && topY + height <= obj.topY + obj.height) {
        return Collision.HITY;
    }
}

Now that might have fixed it partially, the next thing I would do is reset the position of the ball when it collides (if you're not doing so already somewhere else):

// if ball hits top of object
if(topX + width >= obj.topX && topX <= obj.topX + obj.width) {
    if(topY + height >= obj.topY && topY + height <= obj.topY + obj.height) {
        setY(obj.topY - height);
        return Collision.HITY;
    }
}

This way during the next frame update it won't think that ball and obj are colliding again. It may be executing this code multiple times before you can even see it on the screen. This is the same way I would do it for the left, right, and bottom collision.

\$\endgroup\$
1
\$\begingroup\$

Restated, you have the following problem:

You have two rectangles, and wish to categorize them into one of three categories:

  1. No collision
  2. A collision with the left or right
  3. A collision with the top or bottom

The first one is simple, and you should not write your own rectangle intersection function.

I see that your post is tagged java and android, so I will point you to the documentation for the Android Rect class: http://developer.android.com/reference/android/graphics/Rect.html

Part 1 of the problem can be addressed by use of the Rect class by taking the x,w,width,height as so:

Rect myRect = new Rect(topX,topY,topX+width,topY+height);
Rect otherRect = new Rect(obj.topX,obj.topY,obj.topX+obj.with,obj.topY+height);
if(Rect.intersects(myRect,otherRect)){
//collision
}else{
//no collision
}

The SECOND part of the problem requires the centers of the objects and the direction from one to the other, and can be done simply using Math.atan2.

double theAngle = Math.atan2(myRect.centerY()-otherRect.centerY(),myRect.centerX()-otherRect.centerX());

And this gives you the direction in which the center of your object is in relation to the center of the other object.

Of course, this still is not done.... you need to know what the spread of angles are for the corners of the other object, so you take the angles from the center of the other object to the corners in question (you will be able to filter out three of them based on whether or not the centerx/centery is less than or greater than the other object.

Once you've figured out the quadrant, you can figure out the angle at which you are on one face or the other, and then you're done.

\$\endgroup\$
1
  • \$\begingroup\$ you might even be able to do this using slope, and not involving trig at all. lemme know if you are interested in that, and I'll write it up. \$\endgroup\$ Jul 11, 2013 at 18:02
0
\$\begingroup\$

I made an Atari breakout game in my hs comp sci class, and I had trouble reflecting the ball off surfaces because I used x++ and y++, etc. to control the direction of the ball. To make this more efficient, I used vectors to control the speed and direction of my ball:

x+= speed * cos(theta);
Y+= speed * sin(theta);

Incrementing theta by Pi/2 radians (90 degrees) allows it to deflect easily on intersection and requires very few lines of code. You can even deflect it at an angle other than 90 degrees.

For your intersections, you could just think of the ball surrounded by a rectangle and use the axis aligned bounding box intersection method. Check whether the objects' borders are touching or within each other.

\$\endgroup\$
-1
\$\begingroup\$

If you want to make sure it handles the collision perfectly without over shooting the brick, you can use the method mentioned in this answer:

https://stackoverflow.com/questions/18704999/how-to-fix-circle-and-rectangle-overlap-in-collision-response/18790389#18790389

You give it the current position and future position of the ball and it gives you intersection time, the normal, and a point.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .