简体   繁体   English

在 JavaFX 动画中模拟真实的反弹

[英]Simulate a realistic Bounce in JavaFX animation

I am creating a Bouncing Ball Animation with JavaFX similar to the bouncing windows logo screen saver.我正在使用类似于弹跳 Windows 徽标屏幕保护程序的 JavaFX 创建弹跳球动画。 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.我正在使用AnimationTimer ,它每帧将球Translates一定量。 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.Bounds球相遇的边界上的平移方向上发生变化,也就是在这次会议上,我需要一个建议... BallAnimation是一个内部类。

    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.如果您使用的是 x/y 轴,对于离开 x 轴的反射,否定球速度的 y 分量。 For reflection off the y-axis, negate the x component of the ball's velocity.对于 y 轴的反射,否定球速度的 x 分量。

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).我使用层和检测用于桨控制的键盘敲击在 javascript 中重新编写了 pong(这是在 '00 或 '01 中使用 Netscape 4.7x)。 I cheated, and set up functions to move the ball in 8 directions.我作弊了,并设置了向 8 个方向移动球的功能。 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:为基于向量的反射显示的代码使用此问题的答案中提供的公式,该公式直接转换为 JavaFX 类:

Please note that, if you search, there are many math tutorials and Stackoverflow questions that talk about functions and methods for performing reflection.请注意,如果您搜索,有许多数学教程和 Stackoverflow 问题讨论了执行反射的函数和方法。

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.在突围游戏中,球从墙壁或砖块等垂直或水平表面反弹的特殊情况是,球反弹的线平行于坐标系的 x 轴和 y 轴,因此可以执行反弹通过否定速度向量的 x 或 y 值。 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;
}
        

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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