Exemple de balle animée JavaFX
Le Bouncing Ball est le «Hello World» des animations en JavaFx. Il est simple à écrire, facile à comprendre et révèle le potentiel de JavaFx même à partir de cette étape primitive.
Nous commencerons par créer une balle en mouvement qui jettera les bases de la balle rebondissante qui suivra.
1. Exemple de balle en mouvement
Outre la configuration de base, ce code n'a qu'une seule ligne importante. La ligne où nous créons lesTimeline
. CeTimeline
possède deux propriétés importantes; lesKeyFrame
et lesKeyValue
. Ce que nous disons auxTimeline
en anglais simple, c'est "déplacez la balle de là où elle est, à la fin desPane
en 3 secondes". Ensuite, nous lui demandons aussi - gentiment - de le faire deux fois et voilà!
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(); } }
Sortie:
2. Balle rebondissante
Avec un aperçu rapide du code, vous pouvez remarquer les similitudes avec le précédent. Notre configuration est à peu près la même sauf que leTimeline
a maintenant unEventHandler
. Le code à l'intérieur de la méthode de poignée déplace la balle dedx
etdy
sauf si la balle est aux limites desPane
, où selon l'endroit où elle se trouve change lesdx
et dy
au pas négatif (en d'autres termes fait bouger la balle dans l'autre sens).
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(); } }
Sortie:
3. Votre premier match
En expérimentant avec l'exemple Bouncing Ball, je me suis dit que se passerait-il si je rendais tout transparent et ajoutais unMouseEvent
qui ferme l'application au clic? Eh bien… devinez quoi… J'ai fini par essayer d'attraper une balle qui rebondit sur mon bureau! Et c’est ainsi que j’ai créé mon premier jeu en JavaFx! Prendre plaisir!
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(); } }
Sortie: