Search code examples
javacollision-detectionphysics

Objects falls through the ground


Im programming a 2D Ball-SideScroller in Java using LWJGL.

My current problem is, that i have some sort of non deterministic behavior. If i press the 'R'-Button in my application - the Constructor of the main Class ("World") is called, but the position of the ball is changing nearly every time.

Here one ScreenShot that will explain the Situation:

http://img5.picload.org/image/lcopowc/landingpoint_0.png

upper-left: this is where the ball hits the ground - of course it should roll down then

upper-right: thats what happend here - quite ok, although there are 2 or 3 pixels between ball and ground

lower-left: the third is even worse - 80% of the ball is in the ground

lower-right: and last but not least - the worst ... here the ball just ignored the slope it landed on

i tried the following things to fix this problem:

  • changed the rendering from immediate to VBO

  • added a thread that updates the coordinates all the time (every ms)

  • checked the FPS-Rate, which is constant at 60

here some code from the method "ballReachedGround" although im not sure if the problem is really in that method

private boolean ballReachedGround(double slope) {
    if (velocityX > 0) {
        return checkFallRight(slope);
    } else if (velocityX < 0) {
        return checkFallLeft(slope);
    }
    return false;
}

private boolean checkFallRight(double slope) {
    if (ball.getY() + ball.getTransy() + ball.getRadius() >= realY2) {
        double xdiff = (ball.getX() + ball.getTransx() + ball.getRadius()) % 50;
        double actualHeight = realY1 + (xdiff / 50) * (realY2 - realY1);
        if (slope < Math.tan(Math.toRadians(-45))) {
            if (ball.getY() + ball.getTransy() + ball.getRadius() >= actualHeight) {
                if (ball.getY() + ball.getTransy() >= actualHeight) {
                    velocityX = 0;
                    return true;
                }
            }
            System.out.println(slope);
        } else {
            double angle = Math.toDegrees((Math.atan(slope)));
            double anglediff = ball.getRotate() - angle;
            ball.setTransy(ball.getTransy() - velocityX * timediff
                    * Math.tan(Math.toRadians(anglediff)));
            if (ball.getY() + ball.getTransy() + 40 >= actualHeight) {
                return true;
            }
            System.out.println(slope);
        }
    }
    return false;
}

Solution

  • The video was pretty clear. So your physics are wrong. Once you detected a collision, you should move the body out of your static scenery (=ground) the shortest way possible. That is how physical engines work. So, in other words, your parabolic trajectory of the ball seems good, but because of this is a simulation, it makes steps, so it isn't a continuous path. One frame it will be above the ground, and the next frame, it will be in the ground. Once you detected that, move the ball back up the closest way out. On edges, this might go to left or right, if you bounce against walls.