繁体   English   中英

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

[英]Simulate a realistic Bounce in JavaFX animation

我正在使用类似于弹跳 Windows 徽标屏幕保护程序的 JavaFX 创建弹跳球动画。 我现在的代码不错,但它只会以顺时针方式弹起球。 这通常是好的,但最终球会自己绕着逆时针旋转,在这种情况下它看起来不再真实。 我一直在寻找一种方法来计算球应该如何弹跳; 在我看来,这真的归结为球进入的天使。 我正在使用AnimationTimer ,它每帧将球Translates一定量。 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]

... 问题是当球击中右边界时,它会向下和弹开,底部会向上和向左弹起,左边界:向上和向右,天花板:向右和向下。 大多数时候这很好,但有时它需要以另一种方式反弹。

好吧,在一个完美的物理学世界中,入角等于出角。 如果您使用的是 x/y 轴,对于离开 x 轴的反射,否定球速度的 y 分量。 对于 y 轴的反射,否定球速度的 x 分量。

我使用层和检测用于桨控制的键盘敲击在 javascript 中重新编写了 pong(这是在 '00 或 '01 中使用 Netscape 4.7x)。 我作弊了,并设置了向 8 个方向移动球的功能。 如果球沿着一个轴(直线左/右或上/下)移动,一个快速随机数会提供不同的反弹。 否则,以相同的角度弹入。

这是一个反射法线周围向量的函数。 它可用于创建反弹,通过反射球在其反弹的墙壁法线(或另一个物体侧面的法线)周围的球的速度矢量。

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

它是我根据此问题中的示例代码创建的示例突破游戏的实现的一部分。

为基于向量的反射显示的代码使用此问题的答案中提供的公式,该公式直接转换为 JavaFX 类:

请注意,如果您搜索,有许多数学教程和 Stackoverflow 问题讨论了执行反射的函数和方法。

在突围游戏中,球从墙壁或砖块等垂直或水平表面反弹的特殊情况是,球反弹的线平行于坐标系的 x 轴和 y 轴,因此可以执行反弹通过否定速度向量的 x 或 y 值。 如果您希望使用这种简化的示例,请参阅此问题中示例代码或其他关于反射的问题的答案。

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