如何在Javafx中使用时间线实现游戏循环?
我是初学者。我正在使用Javafx制作一个简单的配色2D游戏,其中一个圆圈将穿过矩形的障碍物。如何在Javafx中使用时间线实现游戏循环?,java,animation,javafx,event-handling,Java,Animation,Javafx,Event Handling,我是初学者。我正在使用Javafx制作一个简单的配色2D游戏,其中一个圆圈将穿过矩形的障碍物。 圆必须穿过具有相同颜色的矩形 通过后,圆的颜色和矩形的颜色顺序将发生变化 我已经完成了以下代码。现在,我不知道如何更改矩形障碍物的颜色顺序以及每个时间轴周期的圆圈颜色 还有,我如何检测圆圈和障碍物的颜色是否匹配。。。我很快就需要帮助 import javafx.animation.AnimationTimer; import javafx.animation.KeyFrame; import java
圆必须穿过具有相同颜色的矩形
通过后,圆的颜色和矩形的颜色顺序将发生变化
我已经完成了以下代码。现在,我不知道如何更改矩形障碍物的颜色顺序以及每个时间轴周期的圆圈颜色
还有,我如何检测圆圈和障碍物的颜色是否匹配。。。我很快就需要帮助
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.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class ColorRun extends Application {
private static final int KEYBOARD_MOVEMENT_DELTA = 20;
private static final Duration TRANSLATE_DURATION = Duration.seconds(0.25);
@Override
public void start(Stage primaryStage) {
for (int i = 0; i < 12; i++) {
Circle circle = new Circle();
circle.setCenterX(650);
circle.setCenterY(500);
circle.setRadius(40);
circle.setFill(Color.RED);
Rectangle rectangle1 = new Rectangle(0, 0, 200, 70);
rectangle1.setFill(Color.RED);
rectangle1.setStroke(Color.BLACK);
rectangle1.setArcWidth(10);
rectangle1.setArcHeight(10);
Rectangle rectangle2 = new Rectangle(200, 0, 200, 70);
rectangle2.setFill(Color.GREEN);
rectangle2.setStroke(Color.BLACK);
rectangle2.setArcWidth(10);
rectangle2.setArcHeight(10);
Rectangle rectangle3 = new Rectangle(400, 0, 200, 70);
rectangle3.setFill(Color.BLUE);
rectangle3.setStroke(Color.BLACK);
rectangle3.setArcWidth(10);
rectangle3.setArcHeight(10);
Rectangle rectangle4 = new Rectangle(600, 0, 200, 70);
rectangle4.setFill(Color.YELLOW);
rectangle4.setStroke(Color.BLACK);
rectangle4.setArcWidth(10);
rectangle4.setArcHeight(10);
Pane root = new Pane();
root.getChildren().addAll(circle, rectangle1, rectangle2, rectangle3, rectangle4);
final Scene scene = new Scene(root, 800, 800, Color.GREY);
primaryStage.setTitle("Color Run");
primaryStage.setScene(scene);
moveCircleOnKeyPress(scene, circle);
Timeline timeline1 = new Timeline();
timeline1.setCycleCount(Timeline.INDEFINITE);
timeline1.setAutoReverse(false);
final KeyValue kv1 = new KeyValue(rectangle1.yProperty(), 800);
final KeyValue kv2 = new KeyValue(rectangle2.yProperty(), 800);
final KeyValue kv3 = new KeyValue(rectangle3.yProperty(), 800);
final KeyValue kv4 = new KeyValue(rectangle4.yProperty(), 800);
final KeyFrame kf = new KeyFrame(Duration.millis(2000), kv1, kv2, kv3, kv4);
timeline1.getKeyFrames().add(kf);
timeline1.play();
primaryStage.show();
}
}
public void moveCircleOnKeyPress(Scene scene, Circle circle) {
scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
switch (event.getCode()) {
case RIGHT:
circle.setCenterX(circle.getCenterX() + KEYBOARD_MOVEMENT_DELTA);
break;
case LEFT:
circle.setCenterX(circle.getCenterX() - KEYBOARD_MOVEMENT_DELTA);
break;
}
}
});
}
public static void main(String[] args) {
launch(args);
}
}
导入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.shape.Circle;
导入javafx.scene.shape.Rectangle;
导入javafx.stage.stage;
导入javafx.util.Duration;
公共类ColorRun扩展了应用程序{
专用静态最终整数键盘_移动_增量=20;
专用静态最终持续时间转换\持续时间=持续时间。秒(0.25);
@凌驾
公共无效开始(阶段primaryStage){
对于(int i=0;i<12;i++){
圆圈=新圆圈();
圆。setCenterX(650);
圆整中心(500);
圆半径(40);
圆形。设置填充(颜色。红色);
矩形矩形1=新矩形(0,0,200,70);
矩形1.设置填充(颜色:红色);
矩形1.调整行程(颜色:黑色);
矩形1.设置弧宽(10);
矩形1.集光(10);
矩形矩形2=新矩形(200,0,200,70);
矩形2.设置填充(颜色为绿色);
矩形2.调整行程(颜色:黑色);
矩形2.设置弧宽(10);
长方形2.集光(10);
矩形矩形3=新矩形(400,0,200,70);
矩形3.设置填充(颜色:蓝色);
矩形3.调整行程(颜色:黑色);
矩形3.设置弧宽(10);
长方形3.集光(10);
矩形矩形4=新矩形(600,0,200,70);
矩形4.设置填充(颜色:黄色);
矩形4.调整行程(颜色:黑色);
矩形4.设置弧宽(10);
长方形4.集光(10);
窗格根=新窗格();
root.getChildren().addAll(圆、矩形1、矩形2、矩形3、矩形4);
最终场景=新场景(根,800,800,颜色.灰色);
primaryStage.setTitle(“彩色运行”);
初级阶段。场景(场景);
移动按键(场景、圆圈);
时间线timeline1=新时间线();
timeline1.setCycleCount(Timeline.Unfinite);
时间线1.设置自动反转(假);
最终KeyValue kv1=新的KeyValue(矩形1.yProperty(),800);
最终KeyValue kv2=新的KeyValue(矩形2.yProperty(),800);
最终KeyValue kv3=新的KeyValue(矩形3.yProperty(),800);
最终KeyValue kv4=新的KeyValue(矩形4.yProperty(),800);
最终关键帧kf=新关键帧(持续时间.millis(2000),kv1,kv2,kv3,kv4);
timeline1.getKeyFrames().add(kf);
时间线1.玩();
primaryStage.show();
}
}
public void moveCircleOnKeyPress(场景、场景、圆圈){
scene.setOnKeyPressed(新的EventHandler(){
@凌驾
公共无效句柄(KeyEvent事件){
开关(event.getCode()){
案例权利:
circle.setCenterX(circle.getCenterX()+键盘移动_DELTA);
打破
案例左:
circle.setCenterX(circle.getCenterX()-键盘\u移动\u增量);
打破
}
}
});
}
公共静态void main(字符串[]args){
发射(args);
}
}
有一个可以接受事件处理程序的构造函数。
要更改颜色,请将事件处理程序添加到(最后一个)关键帧
:
final KeyFrame kf = new KeyFrame(Duration.millis(2000),(evt -> changeColors()), kv1, kv2, kv3, kv4);
并添加处理颜色更改的方法:
private void changeColors() {
//todo handle color change
System.out.println("timeline cycle finished");
}
接近游戏循环。触发一个更频繁地更新场景的
EventHandler
,并使用它检查圆和矩形之间的交点。当矩形到达底部时,将其重置为顶部并更改颜色
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);
Circle circle = new Circle(650, 500, 40);
Rectangle[] rectangles = new Rectangle[4];
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 = 5000;
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();
}
专用静态最终双键盘\u移动\u增量=5;
专用静态最终双矩形宽度=200;
专用静态最终双矩形高度=70;
专用静态最终双矩形最大Y=800;
专用静态矩形createRectangle(双x){
矩形矩形=新矩形(x,0,矩形宽度,矩形高度);
直接设定行程(颜色为黑色);
矩形设置弧宽(10);
直视下斜视(10);
返回矩形;
}
私有最终随机=新随机();
私有void randomizeColor(矩形[]矩形、圆形、列表颜色){
集合。洗牌(颜色,随机);
for(int i=0;i