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

时间:2017-02-05 22:55:10

标签: java javafx

我正在使用类似于弹跳窗口徽标屏幕保护程序的JavaFX创建弹跳球动画。我现在的代码很不错,但它只会以顺时针方式反弹球。这一般情况良好,但最终球会以逆时针方向旋转,在这种情况下它看起来不再真实。我试图找到一种计算球如何反弹的方法;在我看来,这真的归结为球的天使。我正在使用AnimationTimer Translates每个球的Bounds球。当球的 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; } } 遇到边界时,翻译方向改变了,在这次会议上我需要一个建议...... BallAnimation是一个内部阶级。

login.SuccessfulLogin(testdata);
            login.clickLink(By.xpath(testdata.getParam("MenuLocator")));
            login.WaitForElementVisibilty(By.xpath(testdata.getParam("loginLocator")));
            login.compareValue(testcase, "", expectedResultMap.get("MenuLoginTxt"),
                    driver.findElement(By.xpath(testData.getParam("loginLocator"))).getText());     
            // here should enter the code to close the menu!        
            log.info("User Logged in Successfully");

![bouncing ball[1]

......问题是当球击中右边界时它会向下弹跳并向下弹跳,底部会向上弹跳并向左,向左和向右,向上和向下:向上和向下弹跳。这在大多数情况下都很好,但有时它需要以反方式反弹。

2 个答案:

答案 0 :(得分:2)

嗯,在完美物理世界中,角度等于出角度。如果使用x / y轴,则对于x轴的反射,否定球的速度的y分量。对于偏离y轴的反射,否定球的速度的x分量。

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

答案 1 :(得分:1)

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

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

它是我根据 sample breakout game 中的示例代码创建的 this question 实现的一部分。

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

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

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

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

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