方法无法识别 JavaFX 应用程序中的调用

Method not recognizing the call this in JavaFX application

我正在开发一个程序,显示圆圈与墙壁和自身发生碰撞。

我在使用补偿碰撞的方法时遇到了问题。

public class bouncyFX extends Application {
    public ArrayList<Ball> arr = new ArrayList<Ball>();


    public static void main(String[] args) {
        launch(args);
    }
    static Pane pane;

    @Override
    public void start(final Stage primaryStage) {
        pane = new Pane();
        final Scene scene = new Scene(pane, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
        pane.setOnMouseClicked(new EventHandler<MouseEvent>() {
            public void handle(final MouseEvent event) {
                final Ball ball = new Ball(event.getX(), event.getY(), 40, Color.AQUA);
                ball.circle.relocate(event.getX(), event.getY());
                pane.getChildren().addAll(ball.circle);
                arr.add(ball);
                final Bounds bounds = pane.getBoundsInLocal();
                final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {
                    double deltaX = ball.ballDeltaX;
                    double deltaY = ball.ballDeltaY;
                    public void handle(final ActionEvent event) {
                        ball.circle.setLayoutX(ball.circle.getLayoutX() + deltaX);
                        ball.circle.setLayoutY(ball.circle.getLayoutY() + deltaY);

                        final boolean atRightBorder = ball.circle.getLayoutX() >= (bounds.getMaxX()-ball.circle.getRadius());
                        final boolean atLeftBorder = ball.circle.getLayoutX() <= (bounds.getMinX()+ball.circle.getRadius());
                        final boolean atBottomBorder = ball.circle.getLayoutY() >= (bounds.getMaxY()-ball.circle.getRadius());
                        final boolean atTopBorder = ball.circle.getLayoutY() <= (bounds.getMinY()+ball.circle.getRadius());
                        if(atRightBorder || atLeftBorder)
                            deltaX *= -1;
                        if(atBottomBorder || atTopBorder)
                            deltaY *= -1;
                        for(int i = 0; i<arr.size(); i++){
                            for(int j = i+1; j<arr.size()-1; j++){
                               arr.get(i).collisionMagnitued(arr.get(j));
                            }
                        }
                    }
                }));
                loop.setCycleCount(Timeline.INDEFINITE);
                loop.play();
            }
        });
    }
    class Ball{
        public Circle circle;
        public double ballDeltaX = 3;
        public double ballDeltaY = 3;

        public void AddBall(Ball b){
            arr.add(b);
        }

        public Ball(double X, double Y, double Rad, Color color) {
            circle = new Circle(X, Y, Rad);
            circle.setFill(color);
        }

        private boolean defineCollision(Ball b){
            double xd = this.circle.getLayoutX() - b.circle.getLayoutX();
            double yd = this.circle.getLayoutY() - b.circle.getLayoutY();
            double sumRad = this.circle.getRadius() + b.circle.getRadius();
            double squareRad = Math.pow(sumRad, 2);

            double distSquare = Math.pow(xd, 2) + Math.pow(yd, 2);
            if(distSquare <= squareRad){
                return true;
            }return false;
        }
        public void collisionMagnitued(Ball b){
            if(this.defineCollision(b)){
                double tempDeltaX = ballDeltaX;
                double tempDeltaY = ballDeltaY;

                if((this.ballDeltaX < 0 && b.ballDeltaX > 0) || (this.ballDeltaX >0 && b.ballDeltaX <0)){
                    this.ballDeltaX *= -this.ballDeltaX;
                    b.ballDeltaX *= -b.ballDeltaX;
                    System.out.println("tredje");
                }
                if((this.ballDeltaY < 0 && b.ballDeltaY > 0) || (this.ballDeltaY > 0 && b.ballDeltaY < 0)){
                    this.ballDeltaY *= -this.ballDeltaY;
                    b.ballDeltaY *= -b.ballDeltaY;
                    System.out.println("fjärde");
                }
                else{
                    System.out.println("Knull");
                    this.ballDeltaX *= -1;
                    b.ballDeltaX *= -1;
                }
            }
        }
    }
}

球(或圆圈)已创建并按预期在边界上弹跳。

当我在最后一个方法中获取打印语句时,碰撞检测方法起作用了。但是,似乎我的 ArrayList 没有填充对象或尝试比较参数 Ball 和调用该方法的 Ball 的方法有问题。

我离题了吗?不确定我应该如何从这里出发。

我发现你的逻辑有几个问题:

第一个问题是,当球 "bounce" 超出窗格的边界时,您不会更改它们的 ballDeltaXballDeltaY 值(您只需更改本地值在动画循环中并使用本地值更新位置)。所以两个球第一次碰撞时,它们的 ballDeltaXballDeltaY 值都等于 +3(初始值),这可能并不代表动画循环将它们移动的实际方向。在事实上,您实际上从未使用 ballDeltaXballDeltaY 的任何更新值来计算新位置;您获得这些变量的初始值,将它们复制到 deltaXdeltaY,然后使用 deltaXdeltaY 计算新位置。因此,如果您更改 ballDeltaXballDeltaY,动画循环永远不会看到更改。

for 循环在我看来是错误的;我认为他们不会比较列表的最后两个元素。 (当 i = arr.size()-2 在外循环的倒数第二次迭代中,你的内循环是 for (int j = arr.size() - 1; j < arr.size() -1; j++) {...} 当然永远不会迭代。)我认为你希望边界条件是 i < arr.size() - 1j < arr.size(),即反过来。

然后您在 collisionMagnitued(...) 中的 if/else 结构可能不是您想要的。我不确定你想在那里实现什么,但是 else 子句只有在第二个 iffalse 时才会启动,而不管第一个 [=] 中发生什么27=].

最后,您将在每次单击鼠标时启动一个新动画。因此,举例来说,如果您有三个球在周围弹跳,则您有三个动画循环 运行,每个循环都在球碰撞时更新值。您只需要开始一个循环;如果它引用一个空列表,它应该不会造成任何伤害。