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

时间:2018-06-24 22:16:51

标签: javafx

我是初学者。我正在使用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);

}
}

1 个答案:

答案 0 :(得分:0)

因此,我测试了该应用程序(对于入门应用程序来说非常酷),发现我会设置一些按钮来帮助您入门,您应该查看有关更高级游戏的一些教程,我会注意它们的学习方式(在教程中)设置它们的主屏幕以及其他问题,您的问题可以广泛回答,但我不希望您灰心并且停止编码。当您遇到堆栈溢出问题时,请尝试提出一个出问题的确切问题,但我无法启动并关闭游戏,然后尝试解决您自己的Google的一些问题,以获取代码示例,并查看其他人员做了什么以及如何做他们解决了这个问题或教程是如何做到的。还环顾了Google关于入门游戏应用程序的一些知识,您很快就会意识到它的结构可能会更好,我不希望这些按钮看起来不错,而只是为了让您好运而开心编码

我的评论在我添加的内容之内

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();
}