Как создавать новый шар каждые 5 секунд (5000 миллисекунд) в JavaFX?

#java #javafx

#java #javafx

Вопрос:

Я новичок в JavaFX, и я создаю простую программу. Чего я пытаюсь добиться, так это создавать мяч каждые 5 секунд, который отскакивает от стен, и все шары должны двигаться каждые десятки раз в секунду (10 миллисекунд). Кроме того, не стесняйтесь оставлять другие предложения по моему коду.

Вот исходный код:

общедоступный класс Main расширяет приложение {

 @Override
public void start(Stage stage) {

    //Sets the title, adds a group, and background color
    BorderPane canvas = new BorderPane();
    Scene scene = new Scene(canvas, 640, 480, Color.WHITE);
    Circle ball = new Circle(10, Color.RED);
    ball.relocate(0, 10);
    
    canvas.getChildren().add(ball);
    
    stage.setTitle("Title");
    stage.setScene(scene);
    stage.show();
       
    Timeline timeline = new Timeline(new KeyFrame(Duration.millis(20), new EventHandler<ActionEvent>() {
        double dx = 5;                  //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(args);
}
 

}

Комментарии:

1. Подсказка: ведите список шаров, а затем просматривайте этот список, чтобы обновить положение каждого шара. Используйте таймер / поток для создания новых шаров и добавления их в список, чтобы их можно было обновлять.

Ответ №1:

Вот один из способов сделать это, как предложено в комментариях:

  • Создайте пользовательский объект, содержащий шар и информацию о его ориентации.
  • Добавьте вновь созданный объект в список и шар в холст.
  • Перебирайте все шары и размещайте их на основе информации об их ориентации.
  • По достижении желаемого времени добавьте новый шар.

Для простоты вам не нужны какие-либо сопутствующие материалы. Возможно, их использование улучшит реализацию (но я сейчас не касаюсь этого). 🙂

Вот демонстрация использования пунктов, о которых я упоминал.

 import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

public class CanvasBallCreation_Demo extends Application {
    List<Ball> balls = new ArrayList<>();
    BorderPane canvas;
    double dx = 5;                  //Step on x or velocity
    double dy = 3;                  //Step on y
    double refresh = 20;//ms
    double addBallDuration = 5000;//ms
    double temp = 0;
    SecureRandom rnd = new SecureRandom();

    @Override
    public void start(Stage stage) {
        canvas = new BorderPane();
        Scene scene = new Scene(canvas, 640, 480, Color.WHITE);
        addBall();

        stage.setTitle("Title");
        stage.setScene(scene);
        stage.show();

        Timeline timeline = new Timeline(new KeyFrame(Duration.millis(refresh), e->moveBalls()));
        timeline.setCycleCount(Timeline.INDEFINITE);
        timeline.play();
    }

    private void addBall(){
        Ball ball = new Ball();
        balls.add(ball);
        canvas.getChildren().add(ball.getBall());
    }

    private void moveBalls() {
        temp = temp   refresh;
        if(temp>addBallDuration){
            temp = 0;
            addBall();
        }
        Bounds bounds = canvas.getBoundsInLocal();
        balls.forEach(obj -> {
            Circle ball = obj.getBall();
            double tx = obj.getTx();
            double ty = obj.getTy();
            ball.setLayoutX(ball.getLayoutX()   dx*tx);
            ball.setLayoutY(ball.getLayoutY()   dy*ty);

            //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())) {
                obj.setTx(-tx);
            }

            //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()))) {
                obj.setTy(-ty);
            }
        });
    }

    class Ball {
        Circle ball = new Circle(10, Color.RED);
        double tx = 1;
        double ty = 1;
        public Ball(){
            // Placing the ball at a random location between 0,0 and 10,10 to generate random paths
            ball.relocate(rnd.nextInt(10), rnd.nextInt(10));
        }

        public Circle getBall() {
            return ball;
        }

        public double getTx() {
            return tx;
        }

        public void setTx(double tx) {
            this.tx = tx;
        }

        public double getTy() {
            return ty;
        }

        public void setTy(double ty) {
            this.ty = ty;
        }
    }
}
 

Ответ №2:

Есть несколько вариантов, java.util.concurrent.TimeUnit или Thread.sleep .

Возможно, вы захотите рассмотреть оба варианта, и если вам нужно выполнить две операции одновременно (создание новых шаров, перемещение шаров) Я бы подумал о том, чтобы использовать новую нить для каждого шарика.

Вы можете прочитать больше об использовании потоков, используя эти статьи, и ваша простая программа на самом деле кажется отличным вариантом использования для изучения их.

 https://www.geeksforgeeks.org/multithreading-in-java/
https://www.tutorialspoint.com/java/java_multithreading.htm
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
 

Комментарии:

1.Потоки работают, JavaFX но, вероятно, являются самым сложным маршрутом. Первый вариант, на который следует обратить JavaFX внимание, — это что-то из Animation API . Второй вариант должен быть таким.