JavaFX动画 - 细节Re。如何实施

时间:2015-05-03 17:19:41

标签: java animation javafx

我有一些代码可以自我避免随机游走:

package event_handling;

import java.util.ArrayList;
import java.util.Random;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class SelfAvoidingRandomWalk extends Application {

int latticeSize;
int scale;
double initialX, initialY;
double currentX, currentY;
ArrayList<Line> lines;
ArrayList<String> moveDirections;
String chosenDirection;
Pane pane;

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

@Override
public void start(Stage primaryStage) throws Exception {

    Random random = new Random();
    pane = new Pane();
    Button start = new Button("Start");

    latticeSize = 16;
    scale = 30;

    initialX = latticeSize * scale / 2;
    initialY = latticeSize * scale / 2;

    currentX = initialX;
    currentY = initialY;

    lines = new ArrayList<>();
    moveDirections = new ArrayList<>();

    chosenDirection = "";

    Line[] horizontalGridLines = new Line[latticeSize + 1];
    Line[] verticalGridLines = new Line[latticeSize + 1];

    //Draw gridlines
    for (int a = 0; a < latticeSize + 1; a++) {
        Line l = new Line(0, a * scale, latticeSize * scale, a * scale);
        l.setStroke(Color.LIGHTGRAY);
        horizontalGridLines[a] = l;
    }

    for (int a = 0; a < latticeSize + 1; a++) {
        Line l =  new Line(a * scale, 0, a * scale, latticeSize * scale);
        l.setStroke(Color.LIGHTGRAY);
        verticalGridLines[a] = l;
    }

    pane.getChildren().addAll(horizontalGridLines);
    pane.getChildren().addAll(verticalGridLines);

    BorderPane bPane = new BorderPane();

    bPane.setCenter(pane);
    bPane.setBottom(start);

    BorderPane.setAlignment(start, Pos.CENTER);

    start.setOnMouseClicked(e -> {

        pane.getChildren().removeAll(lines);
        lines.clear();
        initialX = latticeSize * scale / 2;
        initialY = latticeSize * scale / 2;

        currentX = initialX;
        currentY = initialY;

        while (noNodeTouchesBorders() && validMoveExists()) {

            //Check which directions are empty
            buildValidMovesList();

            //Choose from the available directions
            chosenDirection = moveDirections.get(random.nextInt(moveDirections.size()));

            //Make the move
            makeMove();

            //Reset list of possible moves
            moveDirections = new ArrayList<>();

        }

        System.out.println("Finished walk.");

        if (noNodeTouchesBorders()) {
            System.out.println("Dead end.");
        } else {
            System.out.println("Reached exit.");
        }
    });

    Scene scene = new Scene(bPane, latticeSize * scale, latticeSize * scale + 30);

    primaryStage.setTitle("Self-avoiding Random Walk");
    primaryStage.setScene(scene);
    primaryStage.show();

}

private boolean noNodeTouchesBorders() {

    if (currentX == 0 || currentY == 0 || currentX == latticeSize * scale || currentY == latticeSize * scale) {
        return false;
    }

    return true;

}

private boolean validMoveExists() {

    //We have coordinates, and need to check if there are existing lines in the relevant ArrayList with the same endpoint/startpoint.

    boolean blocksUp = false;
    boolean blocksDown = false;
    boolean blocksLeft = false;
    boolean blocksRight = false;

    //For each line,
    for (Line l : lines) {

        //Check if this line blocks in some direction
        if (blocksUp(l)) {
            blocksUp = true;
        }

        if (blocksDown(l)) {
            blocksDown = true;
        }

        if (blocksLeft(l)) {
            blocksLeft = true;
        }

        if (blocksRight(l)) {
            blocksRight = true;
        }

    }

    if (blocksUp && blocksDown && blocksLeft && blocksRight) {
        return false;
    }

    return true;

}

private boolean blocksUp(Line l) {

    if ((l.getStartX() == currentX && l.getStartY() == currentY - scale) || (l.getEndX() == currentX && l.getEndY() == currentY - scale)) {
        return true;
    }

    return false;

}

private boolean blocksDown(Line l) {

    if ((l.getStartX() == currentX && l.getStartY() == currentY + scale) || (l.getEndX() == currentX && l.getEndY() == currentY + scale)) {
        return true;
    }

    return false;

}

private boolean blocksLeft(Line l) {

    if ((l.getStartX() == currentX - scale && l.getStartY() == currentY) || (l.getEndX() == currentX - scale && l.getEndY() == currentY)) {
        return true;
    }

    return false;

}

private boolean blocksRight(Line l) {

    if ((l.getStartX() == currentX + scale && l.getStartY() == currentY) || (l.getEndX() == currentX + scale && l.getEndY() == currentY)) {
        return true;
    }

    return false;

}

private void buildValidMovesList() {

    moveDirections.add("Up");
    moveDirections.add("Down");
    moveDirections.add("Left");
    moveDirections.add("Right");

    for (Line l : lines) {
        if (blocksUp(l)) {
            moveDirections.remove("Up");
        }

        if (blocksDown(l)) {
            moveDirections.remove("Down");
        }

        if (blocksLeft(l)) {
            moveDirections.remove("Left");
        }

        if (blocksRight(l)) {
            moveDirections.remove("Right");
        }
    }

}

private void makeMove() {

    switch (chosenDirection) {
        case "Up" :     moveUp();       break;
        case "Down" :   moveDown();     break;
        case "Left" :   moveLeft();     break;
        case "Right" :  moveRight();    break;
    }

}

private void moveUp() {

    //Create new line
    Line l = new Line(currentX, currentY, currentX, currentY - scale);

    //Add a new line to the lines ArrayList
    lines.add(l);

    //Add the new line to the pane
    pane.getChildren().add(l);

    //Set new currentY
    currentY = currentY - scale;

    System.out.println("Went up.");

}

private void moveDown() {

    //Create new line
    Line l = new Line(currentX, currentY, currentX, currentY + scale);

    //Add a new line to the lines ArrayList
    lines.add(l);

    //Add the new line to the pane
    pane.getChildren().add(l);

    //Set new currentY
    currentY = currentY + scale;

    System.out.println("Went down.");

}

private void moveLeft() {

    //Create new line
    Line l = new Line(currentX, currentY, currentX - scale, currentY);

    //Add a new line to the lines ArrayList
    lines.add(l);

    //Add the new line to the pane
    pane.getChildren().add(l);

    //Set new currentX
    currentX = currentX - scale;

    System.out.println("Went left.");

}

private void moveRight() {

    //Create new line
    Line l = new Line(currentX, currentY, currentX + scale, currentY);

    //Add a new line to the lines ArrayList
    lines.add(l);

    //Add the new line to the pane
    pane.getChildren().add(l);

    //Set new currentX
    currentX = currentX + scale;

    System.out.println("Went right.");

}

}

目前,每次单击“开始”按钮时,都会进行一次模拟。一个完整的程序运行,可以这么说。

我的任务是为该程序制作动画。所以我想在自己的框架中显示每条画线。

我不确定该怎么做。我试过并搞砸了代码。我知道我应该使用KeyFrames和事件处理程序......不知何故。 (之前我做过简单的动画,但代码并不复杂。没有必要踩踏,或者我正在使用现有的转换。)

我认为我的代码有点弱,因为逻辑与UI一起。实现动画时不确定这是否重要。

你能指导我如何解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

您可以将while循环包含在AnimationTimer内,如下所示:

SELECT