|
1 | 1 | package ch_15;
|
2 | 2 |
|
| 3 | +import javafx.animation.PathTransition; |
3 | 4 | import javafx.application.Application;
|
| 5 | +import javafx.collections.ObservableList; |
| 6 | +import javafx.scene.Scene; |
| 7 | +import javafx.scene.input.MouseButton; |
| 8 | +import javafx.scene.layout.Pane; |
| 9 | +import javafx.scene.shape.Circle; |
| 10 | +import javafx.scene.shape.Line; |
| 11 | +import javafx.scene.shape.Polyline; |
| 12 | +import javafx.scene.text.Font; |
| 13 | +import javafx.scene.text.Text; |
4 | 14 | import javafx.stage.Stage;
|
| 15 | +import javafx.util.Duration; |
5 | 16 |
|
6 | 17 | /**
|
7 | 18 | * **15.25 (Animation: ball on curve) Write a program that animates a ball moving along
|
|
10 | 21 | * a click on the left/right mouse button.
|
11 | 22 | */
|
12 | 23 | public class Exercise15_25 extends Application {
|
| 24 | + private final double sceneWidth = 600; |
| 25 | + private final double sceneHeight = 260; |
| 26 | + private final int fontSize = 16; |
| 27 | + |
| 28 | + private final double centerX; |
| 29 | + private final double centerY; |
| 30 | + |
| 31 | + public Exercise15_25() { |
| 32 | + centerX = sceneWidth / 2; |
| 33 | + centerY = sceneHeight / 2; |
| 34 | + } |
| 35 | + |
13 | 36 | @Override
|
14 | 37 | public void start(Stage primaryStage) throws Exception {
|
| 38 | + Pane pane = new Pane(); |
| 39 | + Polyline xAxis = new Polyline(); |
| 40 | + Polyline yAxis = new Polyline(); |
| 41 | + drawYAxis(pane, yAxis); |
| 42 | + drawXAxis(pane, xAxis); |
| 43 | + |
| 44 | + Polyline polyline1 = new Polyline(); |
| 45 | + ObservableList<Double> list = polyline1.getPoints(); |
| 46 | + int startXValue = -170; |
| 47 | + int endXValue = 170; |
| 48 | + for (int x = startXValue; x <= endXValue; x++) { |
| 49 | + list.add(x + centerX); |
| 50 | + double y = calculateY(x, centerY); |
| 51 | + list.add(y); |
| 52 | + if (isYIntersectingXAxis(y, centerY)) { |
| 53 | + Text text = new Text(x + centerX, centerY / 0.9, getXAxisLabel(x)); |
| 54 | + pane.getChildren().add(text); |
| 55 | + } |
| 56 | + |
| 57 | + } |
| 58 | + Circle point = new Circle(list.get(0), list.get(1), 10); |
| 59 | + PathTransition path = new PathTransition(Duration.millis(4000), polyline1, point); |
| 60 | + path.setCycleCount(PathTransition.INDEFINITE); |
| 61 | + pane.getChildren().addAll(xAxis, yAxis, polyline1, point); |
| 62 | + pane.setOnMouseClicked(e -> { |
| 63 | + if (e.getButton() == MouseButton.PRIMARY) { |
| 64 | + path.play(); |
| 65 | + } else if (e.getButton() == MouseButton.SECONDARY) { |
| 66 | + path.pause(); |
| 67 | + } |
| 68 | + }); |
| 69 | + primaryStage.setScene(new Scene(pane, sceneWidth, sceneHeight)); |
| 70 | + primaryStage.setTitle(getClass().getName()); |
| 71 | + primaryStage.show(); |
| 72 | + |
| 73 | + } |
| 74 | + |
| 75 | + private double calculateY(int x, double centerY) { |
| 76 | + return centerY - 50 * Math.sin((x / 100.0) * 2 * Math.PI); |
| 77 | + } |
| 78 | + |
| 79 | + private boolean isYIntersectingXAxis(double y, double centerY) { |
| 80 | + return y - centerY < 0.01 && y - centerY > -0.01; |
| 81 | + } |
| 82 | + |
| 83 | + private void drawXAxis(Pane pane, Polyline xAxis) { |
| 84 | + ObservableList<Double> xAxisList = xAxis.getPoints(); |
| 85 | + double limit = sceneWidth * 0.95; |
| 86 | + |
| 87 | + for (double x = 0; x < limit; x++) { |
| 88 | + xAxisList.add(x); |
| 89 | + xAxisList.add(centerY); |
| 90 | + } |
15 | 91 |
|
| 92 | + Line line1 = new Line(limit, centerY, limit - sceneWidth * 0.05, centerY * 0.875); |
| 93 | + Line line2 = new Line(limit, centerY, limit - sceneWidth * 0.05, centerY / 0.875); |
| 94 | + Text text = new Text(limit + (sceneWidth * 0.02), centerY, "X"); |
| 95 | + text.setFont(Font.font(fontSize)); |
| 96 | + pane.getChildren().addAll(line1, line2, text); |
16 | 97 | }
|
| 98 | + |
| 99 | + private void drawYAxis(Pane pane, Polyline yAxis) { |
| 100 | + |
| 101 | + ObservableList<Double> yAxisList = yAxis.getPoints(); |
| 102 | + double limit = sceneHeight * 0.95; |
| 103 | + |
| 104 | + for (double y = 0; y < limit; y++) { |
| 105 | + yAxisList.add(centerX); |
| 106 | + yAxisList.add(y + sceneHeight * 0.1); |
| 107 | + |
| 108 | + } |
| 109 | + Line line1 = new Line(centerX, sceneHeight * 0.1, centerX - sceneWidth * 0.03, sceneHeight * 0.22); |
| 110 | + Line line2 = new Line(centerX, sceneHeight * 0.1, centerX + sceneWidth * 0.03, sceneHeight * 0.22); |
| 111 | + Text text = new Text(limit + (sceneWidth * 0.2), sceneHeight * 0.1, "Y"); |
| 112 | + text.setFont(Font.font(fontSize)); |
| 113 | + pane.getChildren().addAll(line1, line2, text); |
| 114 | + } |
| 115 | + |
| 116 | + private String getXAxisLabel(double x) { |
| 117 | + if (isRoughlyEqual(x, 0)) { |
| 118 | + return "0"; |
| 119 | + } else if (isRoughlyEqual(x, 50)) { |
| 120 | + return "π"; |
| 121 | + } else if (isRoughlyEqual(x, -50)) { |
| 122 | + return "-π"; |
| 123 | + } else if (isRoughlyEqual(x, 100)) { |
| 124 | + return "2π"; |
| 125 | + } else if (isRoughlyEqual(x, -100)) { |
| 126 | + return "-2π"; |
| 127 | + } |
| 128 | + |
| 129 | + return ""; |
| 130 | + |
| 131 | + } |
| 132 | + |
| 133 | + private boolean isRoughlyEqual(double a, double b) { |
| 134 | + return a - b < 0.01 && a - b > -0.01; |
| 135 | + } |
| 136 | + |
17 | 137 | }
|
| 138 | + |
0 commit comments