uni的分配 - 必须制作使用线程移动的弹跳球,并且可以使用向上和向下箭头键更改速度。
除了球随机消失在一些看不见的方格后面之外,我的工作得很好。它可能与左上角的速度标签有关,因为当我删除标签时,这不会再发生了。
问题的Gif:
控制类:
myFunc
球类:
public class Task3Control extends Application {
public void start(Stage stagePrimary) {
//create the ball
Task3Ball ball = new Task3Ball();
//create a label to show to ball's current speed
Label labelSpeed = new Label("Ball Speed: "+ball.getSpeed());
//create the root pane and place the ball and label within it
Pane paneRoot = new Pane();
paneRoot.getChildren().addAll(labelSpeed, ball.circle);
//create a thread to animate the ball and start it
Thread t = new Thread(ball);
t.start();
//increase and decrease the speed of the ball when the up and down arrow keys are pressed
//also update the label to reflect the new speed
paneRoot.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.UP) {
ball.increaseSpeed();
labelSpeed.setText("Ball Speed: "+ball.getSpeed());
}
else if (e.getCode() == KeyCode.DOWN) {
ball.decreaseSpeed();
labelSpeed.setText("Ball Speed: "+ball.getSpeed());
}
});
//Create a scene containing the root pane and place it in the primary stage
//Set the title of the window to 'Bouncing Ball Animation'
Scene scene = new Scene(paneRoot, 400, 300);
stagePrimary.setTitle("Bouncing Ball Animation");
stagePrimary.setScene(scene);
stagePrimary.show();
paneRoot.requestFocus();
}
答案 0 :(得分:2)
此问题似乎是由于x
的{{1}}和y
属性的不当更新造成的。
请注意,鉴于您的代码,JVM不需要保证Circle
的位置的任何修改对呈现线程可见,并且Circle
字段的任何修改都是对动画线程可见。
BTW:您没有将动画线程标记为守护程序线程,因此它会阻止JVM关闭。
将线程设置为守护程序:
speed
正确更新圈子位置
Thread t = new Thread(ball);
t.setDaemon(true);
t.start();
然而,为此目的使用// variable never updated so there are no issues with synchronisation
private final double radius = 20;
...
protected void moveBall() {
// do updates on the JavaFX application thread
Platform.runLater(() -> {
if (x - radius <= 0 || x + radius >= 400) {
dx *= -1;
}
if (y - radius <= 0 || y + radius >= 300) {
dy *= -1;
}
x += dx * speed;
y += dy * speed;
circle.setCenterX(x);
circle.setCenterY(y);
});
}
会更简单:
Timeline
public class Task3Ball {
private Timeline timeline;
...
protected void moveBall() {
if (x - radius <= 0 || x + radius >= 400) {
dx *= -1;
}
if (y - radius <= 0 || y + radius >= 300) {
dy *= -1;
}
x += dx * speed;
y += dy * speed;
circle.setCenterX(x);
circle.setCenterY(y);
}
public void startAnimation() {
if (timeline == null) {
// lazily create timeline
timeline = new Timeline(new KeyFrame(Duration.millis(20), event -> moveBall()));
timeline.setCycleCount(Animation.INDEFINITE);
}
// ensure the animation is playing
timeline.play();
}
}