Pong Physics problem

In my pong game,I have tiles/blocks in my game. With these blocks, I have 4 rectangles for collision, theirs one for the left side,right side, top side, bottom side. One of the problems, is that when the left and top side intersect with each other, the balls y axis isn’t changed when they intersect.

Example : if dy(distance y) equals 3, and it intersects the left and top side rectangles, dy still equals 3.

This also happens with other rectangle(when left intersects bottom rectangle,when right intersects bottom top rectangle, etc.).

Source can be found here(updated link)
http://www.mediafire.com/?e66laoa29pys26c

Sounds to me as if your reaction to two collisions which are happening when in fact you should only react to one and drop the other.

would help if you tell us where in your code is this logic / the problem

Heres where the logic problem occurs.


 public void updateBounceTilesL(Rectangle l, Ball ball) {
        if (dx > 0) {
            if (l.intersects(ball.ball())) {
                if (!bounced) {
                    dx = bounceX(dx);
                    bounced = true;
                } else if (bounced) {
                    dx = dx * 1;
                }
                //System.out.println("Intersected left");
            } else if (!l.intersects(ball.ball())) {
                bounced = false;
            }
        }
    }

    public void updateBounceTilesR(Rectangle r, Ball ball) {
        if (dx < 0) {
            if (r.intersects(ball.ball())) {
                if (!bounced) {
                    if (dx > 0) {
                        dx = bounceX(dx);
                        bounced = true;
                    }
                } else if (bounced) {
                    dx = dx * 1;
                }
                //System.out.println("Intersected right");
            } else if (!r.intersects(ball.ball())) {
                bounced = false;
            }
        }
    }

    public void updateBounceTilesT(Rectangle t, Ball ball) {
        if (dy > 0) {
            if (t.intersects(ball.ball())) {
                if (!bounced) {
                    dy = bounceY(dy);
                    bounced = true;
                } else if (bounced) {
                    dy = dy * 1;
                }
                //System.out.println("Intersected Top");
            } else if (!t.intersects(ball.ball())) {
                bounced = false;
            }
        }
    }

    public void updateBounceTilesB(Rectangle b, Ball ball) {
        if (dy < 0) {
            if (b.intersects(ball.ball())) {
                if (!bounced) {
                    dy = bounceY(dy);
                    bounced = true;
                } else if (bounced) {
                    dy = dy * 1;
                }
                //System.out.println("Intersected Bottom");
            } else if (!b.intersects(ball.ball())) {
                bounced = false;
            }
        }
    }

ok so my first idea would be:

change these methods into boolean methods and instead of the bounced boolean, these methods return true or false

then, wherever you call these methods, if one of the is already true, dont check the others

you seem to check for it…

and the line dx = dx * 1; doesnt do anything

and it seems you do this * 1 thing more often

public AI() {
super(2);x * 1; 
...

not only does

x * 1;

doesnt do anything, because something multiplied with 1 is still the same thing, also, you dont pass the value to anything, you dont do anything with it.

Thanks for your advice, it helped me a lot. But now, I think I have a problem with my math, and I can’t seem to figure it out.
Heres the new code


 public boolean updateBounceTilesL(Rectangle l, Ball ball) {
        if (dx > 0 && l.x <= ball.x + ball.diameter) {
            if (l.intersects(ball.ball())) {
                dx = bounceX(dx);
                hit.play();
                return true;
            } else if (!l.intersects(ball.ball())) {
                return false;
            }
        }
        return false;
    }

    public boolean updateBounceTilesR(Rectangle r, Ball ball) {
        if (dx < 0 && r.x >= ball.x + ball.diameter) {
            if (r.intersects(ball.ball())) {
                dx = bounceX(dx);
                hit.play();
                return true;
            } else if (!r.intersects(ball.ball())) {
                return false;
            }
        }
        return false;
    }

    public boolean updateBounceTilesT(Rectangle t, Ball ball) {
        if (dy > 0 && t.y >= ball.y + ball.diameter) {
            if (t.intersects(ball.ball())) {
                dy = bounceY(dy);
                hit.play();
                return true;
            } else if (!t.intersects(ball.ball())) {
                return false;
            }
        }
        return false;
    }

    public boolean updateBounceTilesB(Rectangle b, Ball ball) {
        if (dy < 0 && b.y <= ball.y + ball.diameter) {
            if (b.intersects(ball.ball())) {
                dy = bounceY(dy);
                hit.play();
                return true;
            } else if (!b.intersects(ball.ball())) {
                return false;
            }
        }
        return false;
    }

eeeh well

if your Rectangle is the AWT Rectangle then to use .intersects I guess your Ball is a sub class of Shape
I haven’t done it like that, but if done right intersects() should return whether or not there is a collision

Actually haven’t done circle collision, but its one of these “program once - never look into again” codes

Circle collision is the easiest: test if the radii overlap :slight_smile:

Yeah its simple geometry. What I’m saying is that methods like these are black boxes that solve problems, and at some point I don’t know how it is it’s job, and I don’t care, but I have to be sure that it is doing it correctly of course =P

Actually, the ball has a rectangle for collision, and isn’t a sub class of anything. The ball isn’t very big, so I just used a rectangle for collision, since using a circle for collision is harder than using a rectangle. For some reason, when the ball hits the left or top side of the tiles, it goes through or doesn’t bounce the right way.

Circle collision detection:


if(distance(circle1.center(),circle2.center()) <= circle1.radius()+circle2.radius())
    //INTERSECTION!

public static int distance(Point p1, Point p2) {
    return Math.sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y));
}

Cannot be. The method is Rectangle.intersects(Rectangle r), it excepts an Rectangle
so your Ball class extends Rectangle D=
or else it wouldnt compile

Yeah thats fine

I think he means he used a Rectangle object as a variable inside his Ball class :wink:

That’s correct.

So far, I almost found a solution to my problem. (I added some more thin)

Here are the changes in the code(You can also see the diffrences in the codes, if you download the source.Link also updated
http://www.mediafire.com/?4eubm7v6u8cyakq).


    public void update() {
        boolean bounced = false;
        if (dx < 0) {
            ndx = Math.abs(dx);
        } else if (dx > 0) {
            ndx = dx - (dx * 2);
        }
        if (dy < 0) {
            ndy = Math.abs(dy);
        } else if (dy > 0) {
            ndy = dy - (dy * 2);
        }
        if (y + diameter > 460 || y < 0) {
            dx = 3;
            dy = 3;
            x = 250;
            y = 250;
        } else if (x + diameter + (diameter / 2) > 500 || x < 0) {
            if (!bounced) {
                dx = ndx;
                hit.play();
                bounced = true;
            }
        }
        if (moveable) {
            x = x + dx + pauseSpeedX;
            y = y + dy + pauseSpeedY;
        } else if (!moveable) {
            x = x + 0;
            y = y + 0;
        }
    }


    public boolean updateBounceTilesL(Rectangle l, Ball ball) {
        if (dx > 0) {
            if (l.intersects(ball.ball())) {
                dx = ndx;
                hit.play();
                return true;
            } else if (!l.intersects(ball.ball())) {
                return false;
            }
        }

        return false;
    }

    public boolean updateBounceTilesR(Rectangle r, Ball ball) {
        if (dx < 0) {
            if (r.intersects(ball.ball())) {
                dx = ndx;
                hit.play();
                return true;
            } else if (!r.intersects(ball.ball())) {
                return false;
            }
        }

        return false;
    }

    public boolean updateBounceTilesT(Rectangle t, Ball ball) {
        if (dy > 0) {
            if (t.intersects(ball.ball())) {
                dy = ndy;
                hit.play();
                return true;
            } else if (!t.intersects(ball.ball())) {
                return false;
            }
        }

        return false;
    }

    public boolean updateBounceTilesB(Rectangle b, Ball ball) {
        if (dy < 0) {
            if (b.intersects(ball.ball())) {
                dy = ndy;
                hit.play();
                return true;
            } else if (!b.intersects(ball.ball())) {
                return false;
            }
        }

        return false;
    }


ah yes

if (r.intersects(ball.ball()))

Ball.ball()… returns a Rectangle
I would assume that one would just do intersects(ball) ;D

That is also correct.
Also, sorry about the wrong download link.
Here’s the correct one.
http://www.mediafire.com/?e66laoa29pys26c

so what problem remains ? (not looking at your code, because lazy ;D)

For some reason, when the ball hits intersects the block diagonally the first time, it bounces the same direction.

(Example : before intersection, dx = 3, dy = 3, after intersection, dy = -3, dy = -3, where after intersection it should be dx = -3, dy = 3)