簡體   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