如何在JavaFx中将游戏的UI与gameloop连接起来

如何在JavaFx中将游戏的UI与gameloop连接起来,javafx,Javafx,我是初学者。我正在使用JavaFx制作一个简单的2D游戏。我有基本游戏循环的代码。现在我想做一个完整的游戏,在那里我可以打开一个有新游戏,设置等选项的开始窗口。。。另外,我想添加不同的水平和游戏分数和游戏的信息。。。我该怎么做?我可以制作简单的UI窗口。但是我在使用它开始和结束游戏时遇到了问题。我完全搞砸了。。。现在需要帮助:( 我的代码: import java.util.Arrays; import java.util.Collections; import java.util.List;

我是初学者。我正在使用JavaFx制作一个简单的2D游戏。我有基本游戏循环的代码。现在我想做一个完整的游戏,在那里我可以打开一个有新游戏,设置等选项的开始窗口。。。另外,我想添加不同的水平和游戏分数和游戏的信息。。。我该怎么做?我可以制作简单的UI窗口。但是我在使用它开始和结束游戏时遇到了问题。我完全搞砸了。。。现在需要帮助:(

我的代码:

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.animation.TranslateTransition;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.*;
import javafx.scene.control.Label;
import javafx.scene.input.*;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class ColorRun extends Application {

private static final double KEYBOARD_MOVEMENT_DELTA = 5;
private static final double RECT_WIDTH = 200;
private static final double RECT_HEIGHT = 70;
private static final double RECT_MAX_Y = 800;

private static Rectangle createRectangle(double x) {
Rectangle rect = new Rectangle(x, 0, RECT_WIDTH, RECT_HEIGHT);
rect.setStroke(Color.BLACK);
rect.setArcWidth(10);
rect.setArcHeight(10);
return rect;
}

private final Random random = new Random();

private void randomizeColors(Rectangle[] rects, Circle circle, List<Color> 
colors) {
Collections.shuffle(colors, random);
for (int i = 0; i < rects.length; i++) {
    rects[i].setFill(colors.get(i));
}
circle.setFill(colors.get(random.nextInt(colors.size())));
}

@Override
public void start(Stage primaryStage) {
List<Color> colors = Arrays.asList(Color.RED, Color.GREEN, Color.BLUE, 
Color.YELLOW, Color.GREY);

Circle circle = new Circle(650, 700, 20);
Rectangle[] rectangles = new Rectangle[5];
for (int i = 0; i < rectangles.length; i++) {
    rectangles[i] = createRectangle(RECT_WIDTH * i);
}

Pane root = new Pane();
root.setPrefHeight(RECT_MAX_Y);
for (Rectangle rect : rectangles) {
    root.getChildren().add(rect);
}
root.getChildren().add(circle);

final double frameDuration = 16;
final double iterationDuration = 4000;
final int framesPerIteration = (int) (iterationDuration / frameDuration + 1);
randomizeColors(rectangles, circle, colors);

Timeline timeline = new Timeline();

class FrameHandler implements EventHandler<ActionEvent> {

    KeyCode code;
    private int frame = 1;

    @Override
    public void handle(ActionEvent event) {
        if (frame == 0) {
            randomizeColors(rectangles, circle, colors); // change colors 
when iteration is done
        }

        // move circle, if key is pressed
        if (code != null) {
            switch (code) {
                case RIGHT:
                    circle.setCenterX(circle.getCenterX() + 
KEYBOARD_MOVEMENT_DELTA);
                    break;
                case LEFT:
                    circle.setCenterX(circle.getCenterX() - 
KEYBOARD_MOVEMENT_DELTA);
                    break;
            }
        }

        // move rects & check intersection
        final Paint color = circle.getFill();
        final double cx = circle.getCenterX();
        final double cy = circle.getCenterY();
        final double r2 = circle.getRadius() * circle.getRadius();
        boolean lost = false;
        for (Rectangle rect : rectangles) {
            rect.setY(frame * RECT_MAX_Y / framesPerIteration);
            // check for intersections with rects of wrong color
            if (rect.getFill() != color) {

                double dy = Math.min(Math.abs(rect.getY() - cy),
                        Math.abs(rect.getY() + rect.getHeight() - cy));
                dy = dy * dy;

                if (dy > r2) {
                    continue; // y-distance too great for intersection
                }
                if (cx >= rect.getX() && cx <= rect.getX() + rect.getWidth()) 
{
                    lost = true;
                } else {
                    double dx = Math.min(Math.abs(rect.getX() - cx),
                            Math.abs(rect.getX() + rect.getWidth() - cx));
                    if (dx * dx + dy <= r2) {
                        lost = true;
                    }
                }
            }
        }
        frame = (frame + 1) % framesPerIteration;
        if (lost) {
            timeline.stop();
        }

    }
}

FrameHandler frameHandler = new FrameHandler();

Scene scene = new Scene(root);

// keep track of the state of the arrow keys
scene.setOnKeyPressed(evt -> {
    KeyCode code = evt.getCode();
    switch (code) {
        case RIGHT:
        case LEFT:
            frameHandler.code = code;
            break;
    }
});
scene.setOnKeyReleased(evt -> {
    KeyCode code = evt.getCode();
    if (frameHandler.code == code) {
        frameHandler.code = null;
    }
});

primaryStage.setScene(scene);

timeline.getKeyFrames()
        .add(new KeyFrame(Duration.millis(frameDuration), frameHandler));
timeline.setCycleCount(Timeline.INDEFINITE);

timeline.play();

primaryStage.show();
}


public static void main(String[] args) {
    launch(args);

}
}
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.Random;
导入javafx.animation.AnimationTimer;
导入javafx.animation.KeyFrame;
导入javafx.animation.KeyValue;
导入javafx.animation.Timeline;
导入javafx.animation.TranslateTransition;
导入javafx.application.application;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.Group;
导入javafx.scene.scene;
导入javafx.scene.*;
导入javafx.scene.control.Label;
导入javafx.scene.input.*;
导入javafx.scene.control.Button;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.scene.paint.paint;
导入javafx.scene.shape.Circle;
导入javafx.scene.shape.Rectangle;
导入javafx.stage.stage;
导入javafx.util.Duration;
公共类ColorRun扩展了应用程序{
专用静态最终双键盘_移动_DELTA=5;
专用静态最终双矩形宽度=200;
专用静态最终双矩形高度=70;
专用静态最终双矩形最大Y=800;
专用静态矩形createRectangle(双x){
矩形矩形=新矩形(x,0,矩形宽度,矩形高度);
直接设定行程(颜色为黑色);
矩形设置弧宽(10);
直视下斜视(10);
返回矩形;
}
私有最终随机=新随机();
私有void randomizeColor(矩形[]矩形、圆形、列表
颜色){
集合。洗牌(颜色,随机);
for(int i=0;ir2){
继续;//y距离对于交叉点太大
}
如果(cx>=rect.getX()&&cx{
KeyCode code=evt.getCode();
if(frameHandler.code==代码){
frameHandler.code=null;
}
});
初级阶段。场景(场景);
timeline.getKeyFrames()
.add(新关键帧(Duration.millis(frameDuration),frameHandler));
timeline.setCycleCount(timeline.unfinite);
timeline.play();
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

因此,我测试了该应用程序(对于初学者应用程序来说非常酷),我想我会设置一些按钮来帮助您入门。您应该查看一些关于更高级游戏的教程,我会注意它们的用法(在教程中)设置他们的主屏幕等等,你的问题很难回答,但我不想让你气馁,停止编码。当你遇到堆栈溢出时,试着提出一个确切的问题,说明出了什么问题,除了我不能启动和关闭游戏,试着解决你自己的谷歌代码exa的一些问题看看其他人做了什么,他们是如何解决的,或者教程是如何解决的。也看看谷歌上关于入门游戏应用的一些东西,你很快就会意识到,这可以构造得更好。我不想让这些按钮看起来很好,但只想实现好运和快乐编码的功能

PS我的评论在我添加的内容中

private static final double KEYBOARD_MOVEMENT_DELTA = 5;
private static final double RECT_WIDTH = 200;
private static final double RECT_HEIGHT = 70;
private static final double RECT_MAX_Y = 800;

private static Rectangle createRectangle(double x) {
    Rectangle rect = new Rectangle(x, 0, RECT_WIDTH, RECT_HEIGHT);
    rect.setStroke(Color.BLACK);
    rect.setArcWidth(10);
    rect.setArcHeight(10);
    return rect;
}

private final Random random = new Random();

private void randomizeColors(Rectangle[] rects, Circle circle, List<Color> colors) {
    Collections.shuffle(colors, random);
    for (int i = 0; i < rects.length; i++) {
        rects[i].setFill(colors.get(i));
    }
    circle.setFill(colors.get(random.nextInt(colors.size())));
}

@Override
public void start(Stage primaryStage) {
    List<Color> colors = Arrays.asList(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.GREY);

    Circle circle = new Circle(650, 700, 20);
    Rectangle[] rectangles = new Rectangle[5];
    for (int i = 0; i < rectangles.length; i++) {
        rectangles[i] = createRectangle(RECT_WIDTH * i);
    }

    Pane root = new Pane();
    root.setPrefHeight(RECT_MAX_Y);
    for (Rectangle rect : rectangles) {
        root.getChildren().add(rect);
    }
    root.getChildren().add(circle);

//Here is where I added 2 buttons
    //Added Restart Button
    Button restartButton = new Button("Restart");
    restartButton.setVisible(false); //set to false so you cannot see them when playing
    //Added Quit button
    Button quitButton = new Button("Quit");
    quitButton.setVisible(false);
    restartButton.setLayoutY(30);

    final double frameDuration = 16;
    final double iterationDuration = 4000;
    final int framesPerIteration = (int) (iterationDuration / frameDuration + 1);
    randomizeColors(rectangles, circle, colors);

    Timeline timeline = new Timeline();

    class FrameHandler implements EventHandler<ActionEvent> {
        private KeyCode code;
        private int frame = 1;
        public boolean lost = false;
//Here I created a lost action which will run when you lose
        private void lostAction(){
            timeline.stop();
            restartButton.setVisible(true);
            quitButton.setVisible(true);
        }
        @Override
        public void handle(ActionEvent event) {
            if (frame == 0) {
                randomizeColors(rectangles, circle, colors); // change colors when iteration is done
            }

            // move circle, if key is pressed
            if (code != null) {
                switch (code) {
                    case RIGHT:
                        circle.setCenterX(circle.getCenterX() +
                                KEYBOARD_MOVEMENT_DELTA);
                        break;
                    case LEFT:
                        circle.setCenterX(circle.getCenterX() -
                                KEYBOARD_MOVEMENT_DELTA);
                        break;
                }
            }

            // move rects & check intersection
            final Paint color = circle.getFill();
            final double cx = circle.getCenterX();
            final double cy = circle.getCenterY();
            final double r2 = circle.getRadius() * circle.getRadius();
            for (Rectangle rect : rectangles) {
                rect.setY(frame * RECT_MAX_Y / framesPerIteration);
                // check for intersections with rects of wrong color
                if (rect.getFill() != color) {

                    double dy = Math.min(Math.abs(rect.getY() - cy),
                            Math.abs(rect.getY() + rect.getHeight() - cy));
                    dy = dy * dy;

                    if (dy > r2) {
                        continue; // y-distance too great for intersection
                    }
                    if (cx >= rect.getX() && cx <= rect.getX() + rect.getWidth())
                    {
                        lost = true;
                    } else {
                        double dx = Math.min(Math.abs(rect.getX() - cx),
                                Math.abs(rect.getX() + rect.getWidth() - cx));
                        if (dx * dx + dy <= r2) {
                            lost = true;
                        }
                    }
                }
            }
            frame = (frame + 1) % framesPerIteration;
            if (lost) {
                lostAction();//This was altered to point at lost function
            }
        }
    }

    FrameHandler frameHandler = new FrameHandler();

    Scene scene = new Scene(root);// keep track of the state of the arrow keys
    scene.setOnKeyPressed(evt -> {
        KeyCode code = evt.getCode();
        switch (code) {
            case RIGHT:
            case LEFT:
                frameHandler.code = code;
                break;
        }
    });
    scene.setOnKeyReleased(evt -> {
        KeyCode code = evt.getCode();
        if (frameHandler.code == code) {
            frameHandler.code = null;
        }
    });
//Here is where I added the actions of the buttons
    //Resets variables in order to keep playing
    restartButton.setOnAction(event -> {
        frameHandler.lost = !frameHandler.lost;
        frameHandler.frame=0;
        timeline.play();
        restartButton.setVisible(false);
        quitButton.setVisible(false);
    });
    //This will let you leave without it you will play forever
    quitButton.setOnAction(event -> {
        System.exit(0);
    });
    root.getChildren().addAll(restartButton, quitButton);

    primaryStage.setScene(scene);

    timeline.getKeyFrames().add(new KeyFrame(Duration.millis(frameDuration), frameHandler));
    timeline.setCycleCount(Timeline.INDEFINITE);
    timeline.play();

    primaryStage.show();
}
专用静态最终双键盘\u移动\u增量=5;
专用静态最终双矩形宽度=200;
专用静态最终双矩形高度=70;
专用静态最终双矩形最大Y=800;
专用静态矩形createRectangle(双x){
矩形rect=新矩形(x,0,rect_W