Как заставить несколько текстовых полей перемещаться в произвольных направлениях с определенным интервалом времени между ними? - PullRequest
0 голосов
/ 08 мая 2018

В настоящее время я делаю игру с типовой скоростью, используя JavaFX, где слова должны падать сверху, и пользователь должен набирать их как можно быстрее, прежде чем упадет снизу. У меня есть базовая настройка игры. Единственное, с чем я борюсь, это как заставить слова падать сверху и идти вниз (в настоящее время они перемещаются снизу вверх). А также я хочу, чтобы несколько слов падали из случайного положения вверху (не в одной и той же точке происхождения) через определенный промежуток времени между ними, скажем, 30 миллисекунд. Код у меня пока такой:

public void showWords() throws InterruptedException
    {
        int missedWords = 0;        // number of words the user failed to type
        while (missedWords != 10)   
        {
            dequedWord = queue.dequeue();           // the word that the Text object will contain
            Text runWord = new Text(dequedWord);

            wordsPane.getChildren().add(runWord);   // the canvas in which the words will travel from top to bottom
            double PaneHeight = wordsPane.getHeight();
            //double PaneWidth = wordsPane.getWidth();
            double runWordWidth = runWord.getLayoutBounds().getWidth();

            KeyValue initKeyValue = new KeyValue(runWord.translateYProperty(), PaneHeight);
            KeyFrame initFrame = new KeyFrame(Duration.ZERO, initKeyValue);

            KeyValue endKeyValue = new KeyValue(runWord.translateYProperty(), -1.0 * runWordWidth);
            KeyFrame endFrame = new KeyFrame(Duration.seconds(12), endKeyValue);

            Timeline timeline = new Timeline(initFrame, endFrame);

            timeline.setCycleCount(1);
            timeline.play();

            // add code to check whether user typed the word in the Text object

            missedWords++;
        }
    }

Я новичок в анимации, поэтому я не знаю много о классах Timeline, KeyValue и KeyFrame. Я пытался читать документацию по API, но мне это сильно не помогло. Любая помощь очень ценится. Спасибо:)

1 Ответ

0 голосов
/ 08 мая 2018

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

Я рекомендую вместо этого использовать AnimationTimer, который содержит метод, вызываемый для каждого кадра, который позволяет обновлять позиции, удалять старые слова и добавлять новые слова в зависимости от времени.

Пример:

@Override
public void start(Stage primaryStage) {
    final Queue<String> words = new LinkedList<>(Arrays.asList(
            "Hello",
            "World",
            "foo",
            "bar"
    ));
    final Pane wordsPane = new Pane();
    wordsPane.setPrefSize(800, 400);
    final long wordDelay = 500_000_000L; // 500 ms
    final long fallDuration = 12_000_000_000L; // 12 s

    AnimationTimer animation = new AnimationTimer() {

        private long lastWordAdd = Long.MIN_VALUE; // never added a word before
        private final Map<Text, Long> nodes = new LinkedHashMap<>();

        private double nextX = 0;

        private void assignXPosition(Text text) {
            text.setTranslateX(nextX);
            nextX += text.getBoundsInLocal().getWidth();
        }

        @Override
        public void handle(long now) {
            // updates & cleanup
            long deletionLimit = now - fallDuration;
            for (Iterator<Map.Entry<Text, Long>> iter = nodes.entrySet().iterator(); iter.hasNext();) {
                Map.Entry<Text, Long> entry = iter.next();
                final Text text = entry.getKey();
                final long startTime = entry.getValue();
                if (startTime < deletionLimit) {
                    // delete old word
                    iter.remove();
                    wordsPane.getChildren().remove(text);
                } else {
                    // update existing word
                    double factor = ((double) (now - startTime)) / fallDuration;
                    Bounds bounds = text.getBoundsInLocal();
                    text.setTranslateY((wordsPane.getHeight() + bounds.getHeight()) * factor - bounds.getMaxY());
                }
            }

            if (words.isEmpty()) {
                if (nodes.isEmpty()) {
                    stop(); // end animation since there are no more words
                }
            } else if (lastWordAdd + wordDelay <= now) {
                lastWordAdd = now;
                // add new word
                Text text = new Text(words.remove());
                wordsPane.getChildren().add(text);
                assignXPosition(text);
                text.setTranslateY(-text.getBoundsInLocal().getMaxY());
                nodes.put(text, now);
            }

        }
    };
    animation.start();

    Scene scene = new Scene(wordsPane);

    primaryStage.setScene(scene);
    primaryStage.show();
}
...