Main Tutorials

JavaFX Animated Ball Example

The Bouncing Ball is the “Hello World” of animations in JavaFx. It’s simple to write, easy to understand and reveals the potential of JavaFx even from this primitive stage.

We will start by creating a moving ball that will set the basis for the bouncing ball that will follow.

1. Moving Ball Example

Apart from the basic set up this code has only one important line. The line where we create the Timeline. This Timeline holds two important properties; the KeyFrame and the KeyValue. What we say to the Timeline in simple English is “move the ball from where it is, to the end of the Pane in 3 seconds”. Then we also ask it -kindly- to do it twice and voilà!

MovingBall.java

package com.mkyong.javafx.animatedball;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class MovingBall extends Application{
	
    @Override
    public void start(Stage stage) {
    	Pane canvas = new Pane();
    	Scene scene = new Scene(canvas, 300, 300);
    	Circle ball = new Circle(10, Color.RED);
        ball.relocate(0, 10);
        
        canvas.getChildren().add(ball);
        
        stage.setTitle("Moving Ball");
        stage.setScene(scene);
        stage.show();
        
        Bounds bounds = canvas.getBoundsInLocal();
        Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(3), 
                new KeyValue(ball.layoutXProperty(), bounds.getMaxX()-ball.getRadius())));
        timeline.setCycleCount(2);
        timeline.play();
    }
    
    public static void main(String[] args) {
        launch();
    }
}

Output:

javafx-animated-ball-example-1

2. Bouncing Ball

With a quick view on the code you can notice the similarities to the previous one. Our set up is pretty much the same except that the Timeline now has an EventHandler. The code inside the handle method moves the ball by dx and dy unless the ball is at the bounds of the Pane, where depending on where it is changes the dx and dy to negative step (in other words makes the ball move the other way).

BouncingBall.java

package com.mkyong.javafx.animatedball;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class BouncingBall extends Application{
	
    @Override
    public void start(Stage stage) {
    	
    	Pane canvas = new Pane();
    	Scene scene = new Scene(canvas, 300, 300, Color.ALICEBLUE);
    	Circle ball = new Circle(10, Color.CADETBLUE);
        ball.relocate(5, 5);
        
        canvas.getChildren().add(ball);
        
        stage.setTitle("Animated Ball");
        stage.setScene(scene);
        stage.show();
        
        Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20), 
                new EventHandler<ActionEvent>() {

        	double dx = 7; //Step on x or velocity
        	double dy = 3; //Step on y
        	
            @Override
            public void handle(ActionEvent t) {
            	//move the ball
            	ball.setLayoutX(ball.getLayoutX() + dx);
            	ball.setLayoutY(ball.getLayoutY() + dy);

                Bounds bounds = canvas.getBoundsInLocal();
                
                //If the ball reaches the left or right border make the step negative
                if(ball.getLayoutX() <= (bounds.getMinX() + ball.getRadius()) || 
                        ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius()) ){

                	dx = -dx;

                }

                //If the ball reaches the bottom or top border make the step negative
                if((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) || 
                        (ball.getLayoutY() <= (bounds.getMinY() + ball.getRadius()))){

                	dy = -dy;

                }
            }
        }));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    }
    
    public static void main(String[] args) {
        launch();
    }
}

Output:

javafx-animated-ball-example-2

3. Your first game

While experimenting with the Bouncing Ball example, I thought to myself what if I make it all transparent and add a MouseEvent that closes the application on click? Well… guess what… I ended up trying to catch a bouncing ball on my desktop! And that’s how I made my first game in JavaFx! Enjoy!

MyFirstGame.java

package com.mkyong.javafx.animatedball;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

public class MyFirstGame extends Application{
	
    @Override
    public void start(Stage stage) {
    	
    	Pane canvas = new Pane();
    	Scene scene = new Scene(canvas, 300, 300, Color.TRANSPARENT);
    	Circle ball = new Circle(10, Color.DARKSLATEBLUE);
        ball.relocate(5, 5);
        
        canvas.getChildren().add(ball);
                
        stage.initStyle(StageStyle.TRANSPARENT);
        scene.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
            	Platform.exit();
                System.exit(0);
            }
        });
        stage.setTitle("Animated Ball");
        stage.setScene(scene);
        stage.show();
        
        Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20), new EventHandler<ActionEvent>() {
        	double dx = 7; //Step on x or velocity
        	double dy = 3; //Step on y
        	
            @Override
            public void handle(ActionEvent t) {
            	//move the ball
            	ball.setLayoutX(ball.getLayoutX() + dx);
            	ball.setLayoutY(ball.getLayoutY() + dy);

                Bounds bounds = canvas.getBoundsInLocal();
                
                //If the ball reaches the left or right border make the step negative
                if(ball.getLayoutX() <= (bounds.getMinX() + ball.getRadius()) || 
                        ball.getLayoutX() >= (bounds.getMaxX() - ball.getRadius()) ){

                	dx = -dx;

                }

                //If the ball reaches the bottom or top border make the step negative
                if((ball.getLayoutY() >= (bounds.getMaxY() - ball.getRadius())) || 
                        (ball.getLayoutY() <= (bounds.getMinY() + ball.getRadius()))){

                	dy = -dy;

                }
                
            }
        }));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    }
    
    public static void main(String[] args) {
        launch();
    }
}

Output:

javafx-animated-ball-example-3

References

  1. Java 8 in Action – Raoul-Gabriel Urma, Mario Fusco, and Alan Mycroft
  2. Animation Basics – Oracle

About Author

author image
Marilena Panagiotidou is a senior at University of the Aegean, in the department of Information and Communication Systems Engineering. She is passionate about programming in a wide range of languages. You can contact her at [email protected] or through her LinkedIn.

Comments

Subscribe
Notify of
8 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
MAHMOUD
3 years ago

what should I do to make multiple balls instead of the single ball?

Aš Gražus Tamsoje
7 years ago

Thank you for source.
Why I cant use Group, but I must use Pane instead?

walid shaar
3 years ago

HI
new EventHandler<ActionEvent>() {
I have problem with EventHandler&lt a compiler not found “&lt”
thanks

tigrek
2 years ago
Reply to  walid shaar

it is < character for but there was an issue in display I guess

Abdelrahman Bayoumi
3 years ago
Reply to  walid shaar

.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler() {
@Override
public void handle(MouseEvent event) {
System.out.println(“do somthing”);
}
});

Guddu kumar
2 years ago

Thanks Bro

tigrek
2 years ago

Lookslike < character had problem it gives strange character but when I replaced it worked. Thanks

noname
3 years ago

hi, does anyone know how to make the circle differ from bigger to smaller during the runtime and how to make it change speed during the process