简体   繁体   中英

Simulate a realistic Bounce in JavaFX animation

I am creating a Bouncing Ball Animation with JavaFX similar to the bouncing windows logo screen saver. The code I have now is decent but it will only bounce the ball in a clockwise manner. This is good generally but eventually the ball works itself around to a counter-clockwise rotation in which case it no longer looks realistic. I am stuck trying to find a way to calculate how the ball should bounce; in my mind it really comes down to what angel the ball comes in at. I am Using an AnimationTimer which Translates the ball a set amount each frame. When the Bounds of the ball meet a boundary the translating direction is changed it is at this meeting that I need a suggestion... BallAnimation is an inner class.

    class BallAnimation extends AnimationTimer{
     private final Sphere ball;
     private double movex = 0;
     private double movey = 0;
     private double xvariation = 0;
     private double yvariation = 0;
     private boolean right = true;
     private boolean up = false;
     private boolean changeColorRandomly = true;

    private double rate = 1;



    public BallAnimation(Sphere ball){
        this.ball = ball;
        ball.setLayoutX(200);
        ball.setLayoutY(50);
    }

    public void handle(long now){
        move(right,up);

        Bounds ballBounds = ball.localToScene(ball.getBoundsInLocal());

        if(ballBounds.intersects(rightWall.getBoundsInParent())){
            calculateMotion(rightWall);  
            randomBounceAngle();
            setRandomColor(); 
        }
        if(ballBounds.intersects(leftWall.getBoundsInParent())){
            calculateMotion(leftWall);
            randomBounceAngle();
            setRandomColor(); 
        }
        if(ballBounds.intersects(ceiling.getBoundsInParent())){
            calculateMotion(ceiling);
            randomBounceAngle();
            setRandomColor(); 
        }
        if(ballBounds.intersects(floor.getBoundsInParent())){
            calculateMotion(floor);
            randomBounceAngle();
            setRandomColor(); 
        }


    }

    private void calculateMotion(Line touchedWall){
        if(touchedWall.equals(rightWall)){
            right = false;
            up = false;

        }
        if(touchedWall.equals(leftWall)){
            right = true;
            up = true;
        }
        if(touchedWall.equals(ceiling)){
            right = true;
            up = false;
        }
        if(touchedWall.equals(floor)){
            right = false;
            up = true;
        }



    }

    public void move(boolean right, boolean up){
        if(right && !up){
            ball.setTranslateX((movex += (getRate() + xvariation)));
            ball.setTranslateY((movey += (getRate() + yvariation)));  
        }
        if(right && up){
            ball.setTranslateX((movex += (getRate() + xvariation)));
            ball.setTranslateY((movey -= (getRate() + yvariation)));
        }
        if(!right && up){
            ball.setTranslateX((movex -= (getRate() + xvariation)));
            ball.setTranslateY((movey -= (getRate() + yvariation)));
        }
        if(!right && !up){
            ball.setTranslateX((movex -= (getRate() + xvariation)));
            ball.setTranslateY((movey += (getRate() + yvariation)));
        }
        System.out.println("("+movex+", "+movey+")");

    }

    public double getRate(){
        return rate;
    }

    public void setRate(double rate){
        this.rate = rate; 
    }

    public void randomBounceAngle(){
        double ran = Math.random();
        if(ran >= .50){
            //shallow bounce angle
            xvariation = 3;
            yvariation = 2;

        }else{
            //sharp bounce angle
            xvariation = 2;
            yvariation = 3;
        }
    }

![弹跳球[1]

... The problem is when the ball hits the right boundary it bounces down and away, the bottom it bounces up and left, left boundary: up and right, ceiling: right and down. This is fine most of the time but sometimes it needs to bounce the other way.

Well, in a world of perfect physics, in angle is equal to out angle. If you are using an x/y axis, For reflection off the x-axis, negate the y component of the ball's velocity. For reflection off the y-axis, negate the x component of the ball's velocity.

I re-wrote pong in javascript using layers and detecting keyboard strokes for paddle control (this was in '00 or '01 with Netscape 4.7x). I cheated, and set up functions to move the ball in 8 directions. If the ball was traveling along an axis (straight left/right or up/down) a quick random number provided a different bounce coming out. Otherwise, bounce out at same angle in.

Here is a function to reflect a vector around a normal. It can be used to create a bounce, by reflecting the velocity vector of the ball around the normal of the wall (or the normal of the side of another object) that the ball is bouncing off of.

private Point2D reflect(Point2D vector, Point2D normal) {
    return vector.subtract(normal.multiply(vector.dotProduct(normal) * 2));
}

It is part of an implementation for a sample breakout game I created based on the example code in this question .

The code shown for the vector-based reflection uses the formula provided in the answer to this question, which is translated directly to JavaFX classes:

Please note that, if you search, there are many math tutorials and Stackoverflow questions that talk about functions and methods for performing reflection.

A particular case for balls bouncing off vertical or horizontal surfaces such as walls or bricks in a breakout game is that the lines which the ball is bouncing off of are parallel to the x and y axes of the coordinate system, so the bounce can be performed by negating the x or y values of the velocity vector. See the example code in this question or answers to other questions on reflection for an example of this simplification if it is something you wish to use.

if (topWall) {
    dy = dy * -1;
}
            
if (leftWall || rightWall) {
    dx = dx * -1;
}

if(bottomWall) {
    dy = dy * -1;
}
        

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM