Angel Garcia
Angel Garcia

Reputation: 1577

JavaFX program not starting when I use a while loop

Ok, so I'm trying to make a text-based game with a GUI using JavaFX. Everything was working out fine before I put in the actual game loop. Although once I put coded in the game loop, the program wouldn't start. It would run without errors or exceptions, but the window simply wouldn't pop up. When I close the window, all the command line in IntelliJ says is "Process finished with exit code 130" which apparently means that the program was closed because the user press Ctrl+C. which isn't the case because the window isn't even popping up, so it's impossible for any user to click Ctrl+C to terminate the program. So my question is what can I do be able to run my program with a game loop (while loop) without the window refusing to pop up. Here's is my Code:

package sample;
/**
 * Created by Angel on 7/26/16.
 */

import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;

public class Game {

    // Inventory is a class that i made,
    // but im sure it has nothing to do with my problem
    private Inventory inv = new Inventory();
    private String levels;

    private Scene scene;
    private Label topText;
    private Button btn1;
    private Button btn2;
    private Button btn3;
    private boolean gameOn;

    public void gameStart(){

        // Setting the GUI

        // Setting up the window
        VBox window = new VBox(210);

        // setting up the top text holder.
        HBox textHolder = new HBox();
        textHolder.setAlignment(Pos.CENTER);

        // setting up the label
        topText = new Label();
        topText.setText("You in a dark room, what do you do?");

        // setting up the button holder
        HBox buttonHolder = new HBox(50);
        buttonHolder.setAlignment(Pos.CENTER);

        // setting up the buttons
        btn1 = new Button();
        btn1.setPrefWidth(260);
        btn1.setPrefHeight(30);
        btn1.getStyleClass().add("gameButtons");
        btn1.setText("1");

        btn2 = new Button();
        btn2.setPrefWidth(260);
        btn2.setPrefHeight(30);
        btn2.getStyleClass().add("gameButtons");
        btn2.setText("2");

        btn3 = new Button();
        btn3.setPrefWidth(260);
        btn3.setPrefHeight(30);
        btn3.getStyleClass().add("gameButtons");
        btn3.setText("3");


        // finalizing the gui, by putting it all together
        textHolder.getChildren().add(topText);
        buttonHolder.getChildren().addAll(btn1, btn2, btn3);
        window.getChildren().addAll(textHolder, buttonHolder);

        // setting up the scene
        scene = new Scene(window, 800, 600);

        //adding the css script
        // adding css script
        scene.getStylesheets().add(this.getClass().getResource("game.css").toExternalForm());

        // the game loop.

        levels = "Storyline";
        gameOn = true;
        while(gameOn) {
            switch (levels) {
                case "Storyline":
                    btn1.setText("search around");
                    btn2.setText("turn the light on");
                    btn3.setText("stand in fear");

                    btn2.setOnAction(e -> levels = "level1");
                    break;
                case "level1":
                    topText.setText("You turned the light on");
                    break;
            }
        }

    }

    public Scene getScene(){
        return scene;
    }

}

Upvotes: 0

Views: 1201

Answers (1)

fabian
fabian

Reputation: 82461

This shouldn't be a game loop. The button click triggers an event. It should be handled there. It's unnecessary to update button texts ect again and again, which is what you're currently doing.

By executing a loop there, you block the application thread, which is the thread that is responsible for redrawing and handling user interaction, making it impossible to do it's task.

Refractor your code to work event based, i.e.

User interaction (button click) triggers ui update (a change of the state and a single update of the UI).

E.g. something like this:

public class Game {

    ...

    public void gameStart(){

        ...

        // setting up the scene
        scene = new Scene(window, 800, 600);

        // adding css
        scene.getStylesheets().add(this.getClass().getResource("game.css").toExternalForm());

        setLevel("Storyline");
    }

    public void setLevel(String newLevel) {
         // TODO: integrate gameOn value
         if (newLevel != null && !newLevel.equals(levels)) {
              levels = newLevel;
              switch (levels) {
                case "Storyline":
                    btn1.setText("search around");
                    btn2.setText("turn the light on");
                    btn3.setText("stand in fear");

                    // user interaction triggers setting the level
                    btn2.setOnAction(e -> setLevel("level1"));
                    break;
                case "level1":
                    topText.setText("You turned the light on");
                    break;
            }
         }
    }

    ...

}

Additional recommendation: Don't represent the level as String, represent it as instance implementing a interface:

public interface Level {
     // do updates for level start on game
     void updateGameLevelStart(Game game);

     // cleanup code e.g. unregistering event handlers...
     void updateGameLevelEnd(Game game);
}

this would allow you to change the type of levels to Level and simplify the updates:

public void setLevel(Level newLevel) {
     if (!Objects.equals(levels, newLevel)) {
         if (levels != null) {
              // cleanup old level
              levels.updateGameLevelEnd(this);
         }
         levels = newLevel;
         if (newLevel != null) {
              // start new level
              newLevel.updateGameLevelStart(this);
         }
     }
}

This would of course require you to make the relevant parts of the ui accessible to the Level implementations.

Upvotes: 1

Related Questions