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
author image

Marilena

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 an3liram@gmail.com or through her LinkedIn. Read all published posts by

Comments

avatar
3000
newest oldest most voted
Aš Gražus Tamsoje
Guest
Aš Gražus Tamsoje

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

MAHMOUD
Guest
MAHMOUD

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

noname
Guest
noname

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

walid shaar
Guest
walid shaar

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

Abdelrahman Bayoumi
Guest
Abdelrahman Bayoumi

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