0

I'm trying to make a program with balls that (first of all) bounces when closing into the borders of the screen.

However when checking the bounds.getmaxY() value I can see that the value is increasing and because of the if-loops are never used i guess.

public class bouncyFX extends Application {


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

@Override
public void start(final Stage primaryStage) {
    Scene scene = new Scene(pane, 500, 200);
    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(), 12, Color.AQUA);
            ball.relocate(event.getX(), event.getY());
            pane.getChildren().addAll(ball);
            final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {
                double deltaX = 2;
                double deltaY = 2;
                public void handle(final ActionEvent event) {
                    ball.setLayoutX(ball.getLayoutX() + deltaX);
                    ball.setLayoutY(ball.getLayoutY() + deltaY);
                    ball.Collision(deltaX, deltaY);

                    final Bounds bounds = pane.getBoundsInLocal();
                    final boolean atRightBorder = ball.getLayoutX() >= (bounds.getMaxX()-ball.getRadius());
                    final boolean atLeftBorder = ball.getLayoutX() <= (bounds.getMinX()+ball.getRadius());
                    final boolean atBottomBorder = ball.getLayoutY() >= (bounds.getMaxY()-ball.getRadius());
                    final boolean atTopBorder = ball.getLayoutY() <= (bounds.getMinY()+ball.getRadius());
                    if(atRightBorder || atLeftBorder)
                        deltaX *= -1;
                    if(atBottomBorder ||atTopBorder)
                        deltaY *= -1;
                }
            }));
            loop.setCycleCount(Timeline.INDEFINITE);
            loop.play();
        }
    });
}
Johan Rovala
  • 174
  • 1
  • 2
  • 14

3 Answers3

1

Your Bounds variable isn't changing at all, you just get a new instance of it every time.

I think what is happening here is that you change the layout of the ball before you query the pane for its bounds. The pane is growing to accommodate the change in the ball's position. So try

                final Bounds bounds = pane.getBoundsInLocal();
                final boolean atRightBorder = ball.getLayoutX() + deltaX >= (bounds.getMaxX()-ball.getRadius());
                final boolean atLeftBorder = ball.getLayoutX() + deltaX <= (bounds.getMinX()+ball.getRadius());
                final boolean atBottomBorder = ball.getLayoutY() + deltaY >= (bounds.getMaxY()-ball.getRadius());
                final boolean atTopBorder = ball.getLayoutY() + deltaY <= (bounds.getMinY()+ball.getRadius());
                if(atRightBorder || atLeftBorder)
                    deltaX *= -1;
                if(atBottomBorder ||atTopBorder)
                    deltaY *= -1;

                ball.setLayoutX(ball.getLayoutX() + deltaX);
                ball.setLayoutY(ball.getLayoutY() + deltaY);

                // not sure what this line does, so you will need to put it where it makes sense:
                ball.Collision(deltaX, deltaY);
James_D
  • 201,275
  • 16
  • 291
  • 322
0

Declaring value as final does not make the object immutable. It merely means that reference to the object will not be changed - i.e. each time you reference bounds, you will get the same object. Once assigned, final variable cannot be changed to point to another Bounds object.

Vladimir
  • 9,683
  • 6
  • 36
  • 57
  • So how am I supposed to achieve this? I've seen the exact(?) same solution being used here: http://stackoverflow.com/questions/20022889/how-to-make-the-ball-bounce-off-the-walls-in-javafx – Johan Rovala Feb 24 '15 at 13:51
  • As in my comment to @antonio's answer, [`Bounds`](http://docs.oracle.com/javase/8/javafx/api/javafx/geometry/Bounds.html) is actually immutable. The point is a new instance is requested on every animation frame. – James_D Feb 24 '15 at 14:12
0

A final variable cannot be assigned, but you can change it's attributes as you are not making it immutable.

Take a look at this article about defining immutable objects.

In your case, if you have access to the Bounds object you can achieve it with this solution, but if you can't modify the Bounds object to make it immutable you will need to write a wrapper class for Bounds.

antonio
  • 18,044
  • 4
  • 45
  • 61
  • [`Bounds`](http://docs.oracle.com/javase/8/javafx/api/javafx/geometry/Bounds.html) is immutable though (at least with respect to the "geometry" fields). – James_D Feb 24 '15 at 14:05