Home >Java >javaTutorial >Case Study: Bouncing Balls
This section presents a program that displays bouncing balls and enables the user to add and remove balls.
Section presents a program that displays one bouncing ball. This section presents a program that displays multiple bouncing balls. You can use two buttons to suspend and resume the movement of the balls, a scroll bar to control the ball speed, and the + or - button add or remove a ball, as shown in Figure below.
The example in Section only had to store one ball. How do you store the multiple balls in this example? The Pane’s getChildren() method returns an ObservableList, a subtype of List, for storing the nodes in the pane. Initially, the list is empty. When a new ball is created, add it to the end of the list. To remove a ball, simply remove the last one in the list.
Each ball has its state: the x-, y-coordinates, color, and direction to move. You can define a class named Ball that extends javafx.scene.shape.Circle. The x-, y-coordinates and the color are already defined in Circle. When a ball is created, it starts from the upper-left corner and moves downward to the right. A random color is assigned to a new ball.
The MultiplBallPane class is responsible for displaying the ball and the MultipleBounceBall class places the control components and implements the control. The relationship of these classes is shown in Figure below. The code below gives the program.
package application; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.application.Application; import javafx.beans.property.DoubleProperty; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ScrollBar; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.util.Duration; public class MultipleBounceBall extends Application { @Override // Override the start method in the Application class public void start(Stage primaryStage) { MultipleBallPane ballPane = new MultipleBallPane(); ballPane.setStyle("-fx-border-color: yellow"); Button btAdd = new Button("+"); Button btSubtract = new Button("-"); HBox hBox = new HBox(10); hBox.getChildren().addAll(btAdd, btSubtract); hBox.setAlignment(Pos.CENTER); // Add or remove a ball btAdd.setOnAction(e -> ballPane.add()); btSubtract.setOnAction(e -> ballPane.subtract()); // Pause and resume animation ballPane.setOnMousePressed(e -> ballPane.pause()); ballPane.setOnMouseReleased(e -> ballPane.play()); // Use a scroll bar to control animation speed ScrollBar sbSpeed = new ScrollBar(); sbSpeed.setMax(20); sbSpeed.setValue(10); ballPane.rateProperty().bind(sbSpeed.valueProperty()); BorderPane pane = new BorderPane(); pane.setCenter(ballPane); pane.setTop(sbSpeed); pane.setBottom(hBox); // Create a scene and place the pane in the stage Scene scene = new Scene(pane, 250, 150); primaryStage.setTitle("MultipleBounceBall"); // Set the stage title primaryStage.setScene(scene); // Place the scene in the stage primaryStage.show(); // Display the stage } public static void main(String[] args) { Application.launch(args); } private class MultipleBallPane extends Pane { private Timeline animation; public MultipleBallPane() { // Create an animation for moving the ball animation = new Timeline(new KeyFrame(Duration.millis(50), e -> moveBall())); animation.setCycleCount(Timeline.INDEFINITE); animation.play(); // Start animation } public void add() { Color color = new Color(Math.random(), Math.random(), Math.random(), 0.5); getChildren().add(new Ball(30, 30, 20, color)); } public void subtract() { if(getChildren().size() > 0) { getChildren().remove(getChildren().size() - 1); } } public void play() { animation.play(); } public void pause() { animation.pause(); } public void increaseSpeed() { animation.setRate(animation.getRate() + 0.1); } public void decreaseSpeed() { animation.setRate(animation.getRate() > 0 ? animation.getRate() - 0.1 : 0); } public DoubleProperty rateProperty() { return animation.rateProperty(); } protected void moveBall() { for(Node node: this.getChildren()) { Ball ball = (Ball)node; // Check boundaries if(ball.getCenterX() < ball.getRadius() || ball.getCenterX() > getWidth() - ball.getRadius()) { ball.dx *= -1; // Change ball move direction } if(ball.getCenterY() < ball.getRadius() || ball.getCenterY() > getHeight() - ball.getRadius()) { ball.dy *= -1; // Change ball move direction } // Adjust ball position ball.setCenterX(ball.dx + ball.getCenterX()); ball.setCenterY(ball.dy + ball.getCenterY()); } } } class Ball extends Circle { private double dx = 1, dy = 1; Ball(double x, double y, double radius, Color color) { super(x, y, radius); setFill(color); // Set ball color } } }
The add() method creates a new ball with a random color and adds it to the pane (line 73). The pane stores all the balls in a list. The subtract() method removes the last ball in the list (line 78).
When the user clicks the + button, a new ball is added to the pane (line 32). When the user clicks the - button, the last ball in the array list is removed (line 33).
The moveBall() method in the MultipleBallPane class gets every ball in the pane’s list and adjusts the balls’ positions (lines 114–115).
The above is the detailed content of Case Study: Bouncing Balls. For more information, please follow other related articles on the PHP Chinese website!