私は現在、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のドキュメントを読んでみましたが、あまり役に立ちませんでした。どんな助けでも大歓迎です。ありがとうございました :)
座標系の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();
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加