Пример анимированного шара 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(); } }
Выход: