Search code examples
animationjavafxtimeline

how do i properly start a javafx animation using timeline?


I am trying to use code gathered off of this website to make an application that bounces circles around. when i click now - it creates a circle that just seems to vibrate in place and does not bounce off of the borders.

HERE IS THE CODE HAT SOLLVED MY ISSUE THANKS GUYS

@FXML
private AnchorPane anchorPane;
@FXML
private Label ballCountLabel;

public int ballCount = 0;
public int mouseClick = 0;

Circle[] balls = new Circle[1000];

@Override
public void initialize(URL url, ResourceBundle rb) {
    pane.setBackground(new Background(new BackgroundFill(Color.WHITE, CornerRadii.EMPTY, Insets.EMPTY)));
    AnchorPane.setTopAnchor(pane, 0.0);
    AnchorPane.setLeftAnchor(pane, 0.0);
    AnchorPane.setTopAnchor(pane, 0.0);
    AnchorPane.setRightAnchor(pane, 0.0);
}

@FXML
private void mouseAddBall(MouseEvent event) throws Exception {

    balls[mouseClick] = new Circle(15, Color.BLANCHEDALMOND);
    balls[mouseClick].relocate(event.getSceneX(), event.getSceneY());
    pane.getChildren().add(balls[mouseClick]);
    ballCount++;
    ballCountLabel.setText("Ball Count: " + ballCount);
    addBallMovement(balls[mouseClick]);
    mouseClick++;
}
public void addBallMovement(Circle b){

    final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {

        double deltaX = 3;
        double deltaY = 3;

        @Override
        public void handle(ActionEvent t) {
            b.setLayoutX(b.getLayoutX() + deltaX);
            b.setLayoutY(b.getLayoutY() + deltaY);

            final Bounds bounds = pane.getBoundsInParent();

            final boolean atRightBorder = b.getLayoutX() >= (bounds.getMaxX() - b.getRadius());
            final boolean atLeftBorder = b.getLayoutX() <= (bounds.getMinX() + b.getRadius());
            final boolean atBottomBorder = b.getLayoutY() >= (bounds.getMaxY() - b.getRadius());
            final boolean atTopBorder = b.getLayoutY() <= (bounds.getMinY() + b.getRadius());

            if (atRightBorder || atLeftBorder) {
                deltaX *= -1;
            }
            if (atBottomBorder || atTopBorder) {
                deltaY *= -1;
            }
        }
    }));
    loop.setCycleCount(Timeline.INDEFINITE);
    loop.play();

Solution

  • I changed Ball to Circle to test your code. You are changing to the next ball in the balls array before you add movement to the current ball. This is probably giving you a NullPointerException.

    Change

    balls[mouseClick] = new Circle(event.getSceneX(), event.getSceneY(), 
    Math.random() * 20);
    pane.getChildren().add(balls[mouseClick]);
    mouseClick++;
    ballCount++;
    ballCountLabel.setText("Ball Count: " + ballCount);
    addBallMovement(balls[mouseClick]);  //<--You want to move the current ball. This code needs to be before mouseClick++
    

    To:

    balls[mouseClick] = new Circle(event.getSceneX(), event.getSceneY(), 
    Math.random() * 20);
    pane.getChildren().add(balls[mouseClick]);
    addBallMovement(balls[mouseClick]);
    mouseClick++;
    ballCount++;
    ballCountLabel.setText("Ball Count: " + ballCount);