Ошибка NullPoiterExceprion в JavaFX

Задания такое что нужно написать типа гонку и вот у меня проблема с потоками я непонимаю как и где должен прописать их ведь писал везде и все одна ошибка NullPointerException, если вы знаете как можна это реализовать буду вам очень благодарен. Подробнее: У нас должно быть машинки которие в потоке и их должно быть несколько они рухаються по многопоточности кожная по своему потоку

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Racing");
        primaryStage.setScene(new Scene(root, 1000, 800));
        primaryStage.show();
    }


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

Contoller

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;

import javafx.scene.control.Alert;

public class Controller extends Thread {

    @Override
    public void run(){
        System.out.println("Thread started");
        CreateCar();
    }

    public void Move() {
        //TODO
    }

    public void CreateCar(){
        try {
            int n = Integer.parseInt(NoDField.getText());
            System.out.println(n);
            Move();

        } catch (NumberFormatException e) {
            Alert alert = new Alert(Alert.AlertType.ERROR);

            alert.setTitle("Error");
            alert.setHeaderText(null);
            alert.setContentText("Number entered incorrectly");

            alert.showAndWait();
        }
    }

    @FXML
    private ImageView Car;
    @FXML
    private TextField NoDField;

    @FXML
    void ClearFielld(MouseEvent event) {
        NoDField.setText("");
    }

    @FXML
    void Start(ActionEvent event) {
        CreateCar();
    }

    @FXML
    void initialize() {
      Thread obj = new Thread();
      obj.start();
    }
}

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Line?>
<?import javafx.scene.text.Font?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <children>
      <AnchorPane prefHeight="46.0" prefWidth="1000.0" style="-fx-background-color: #A9A9A9;" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Button layoutX="14.0" layoutY="5.0" mnemonicParsing="false" onAction="#Start" prefHeight="20.0" prefWidth="80.0" text="Start" />
            <TextField fx:id="NoDField" layoutX="102.0" layoutY="5.0" onMouseClicked="#ClearFielld" prefHeight="25.0" prefWidth="114.0" text="Number of drivers" />
         </children>
      </AnchorPane>
      <AnchorPane layoutY="156.0" prefHeight="722.0" prefWidth="1000.0" style="-fx-background-color: #FFFFFF;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0">
         <children>
            <ImageView fx:id="Car" fitHeight="100.0" fitWidth="140.0" layoutX="24.0" layoutY="125.0" pickOnBounds="true" preserveRatio="true">
               <image>
                  <Image url="@../Machine.png" />
               </image>
            </ImageView>
            <Label layoutX="904.0" layoutY="351.0" prefHeight="61.0" prefWidth="103.0" rotate="90.0" text="FINISH">
               <font>
                  <Font name="Calibri" size="38.0" />
               </font>
            </Label>
            <Line endX="669.0" endY="271.0" layoutX="253.0" layoutY="496.0" startX="669.0" startY="-496.0" />
         </children>
      </AnchorPane>
   </children>
</AnchorPane>


Ответы (1 шт):

Автор решения: Asad Ganiev

Игру лучше реализовать AnimationTimer'ом.

Простенький пример:

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Box;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class BasicGraphicsDemo3 extends Application implements EventHandler<KeyEvent> {

    final int WIDTH = 600;
    final int HEIGHT = 400;

    double ballRadius = 40;
    double ballX = 100;
    double ballY = 200;
    double xSpeed = 4;

    public static void main(String[] args) {

        launch(args);
    }

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

        stage.setTitle("Basic JavaFX demo");

        Group root = new Group();
        Scene scene = new Scene(root, WIDTH, HEIGHT);

        // Bouncing Ball
        Circle circle = new Circle();
        circle.setCenterX(ballX);
        circle.setCenterY(ballY);
        circle.setRadius(ballRadius);
        circle.setFill(Color.BLUE);
        root.getChildren().add(circle);

        // need to attach KeyEvent caller to a Node of some sort.
        // How about an invisible Box?
        final Box keyboardNode = new Box();
        keyboardNode.setFocusTraversable(true);
        keyboardNode.requestFocus();
        keyboardNode.setOnKeyPressed(this);

        root.getChildren().add(keyboardNode);

        stage.setScene(scene);
        stage.show();

        AnimationTimer animator = new AnimationTimer() {

            @Override
            public void handle(long arg0) {

                // UPDATE
                ballX += xSpeed;

                if (ballX + ballRadius >= WIDTH) {
                    ballX = WIDTH - ballRadius;
                    xSpeed *= -1;
                } else if (ballX - ballRadius < 0) {
                    ballX = 0 + ballRadius;
                    xSpeed *= -1;
                }

                // RENDER
                circle.setCenterX(ballX);
            }
        };

        animator.start();
    }

    @Override
    public void handle(KeyEvent arg0) {

        if (arg0.getCode() == KeyCode.SPACE) {
            xSpeed *= -1;
        }
    }
}

В вышеуказанном примере мячик меняет направление при нажатие на пробел.

Пример кода взят отсюда

→ Ссылка