Пример анимированного шара JavaFX
Прыгающий мяч - это «Привет, мир» анимаций в JavaFx. Его просто написать, легко понять и раскрыть потенциал JavaFx даже на этой примитивной стадии.
Мы начнем с создания движущегося мяча, который станет основой для следующего подпрыгивающего мяча.
1. Пример движущегося мяча
Помимо базовой настройки в этом коде есть только одна важная строка. Строка, в которой мы создаемTimeline. ЭтотTimeline обладает двумя важными свойствами; KeyFrame иKeyValue. То, что мы говоримTimeline на простом английском языке, это «переместите мяч с того места, где он находится, к концуPane за 3 секунды». Тогда мы также просим его - любезно - сделать это дважды и вуаля!
MovingBall.java
package com.techfou.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();
}
}
Выход:

2. Прыгающий мяч
При быстром просмотре кода вы можете заметить сходство с предыдущим. Наша установка почти такая же, за исключением того, чтоTimeline теперь имеетEventHandler. Код внутри метода handle перемещает мяч наdx иdy, если только мяч не находится на границеPane, где в зависимости от того, где он находится, изменяютсяdx и dy на отрицательный шаг (другими словами, заставляет мяч двигаться в другую сторону).
BouncingBall.java
package com.techfou.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() {
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();
}
}
Выход:

3. Ваша первая игра
Экспериментируя с примером Bouncing Ball, я подумал, что если я сделаю все прозрачным и добавлюMouseEvent, закрывающее приложение при нажатии? Ну… угадайте, что… В итоге я пытался поймать прыгающий мяч на своем рабочем столе! Так я сделал свою первую игру на JavaFx! Наслаждайтесь!
MyFirstGame.java
package com.example.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() {
@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() {
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();
}
}
Выход:
