5
\$\begingroup\$

Download the Program

I have written a Cookie Clicker Game with JavaFX. I have not much experience so I guess that the code looks terrible to a person that is familar with JavaFX. So lets improve that!

Main.java

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.scene.layout.VBox;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import java.util.Timer;
import java.util.TimerTask;

/* this class represents the main application.
 * this application represents a game in which a player can produce cookies
 * with the help of the clicker and some buildings.
 * the clicker produces cookies by a button click.
 * the buildings produce cookies automatically from time to time
 */
public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    /* graphical stuff */

    // container

    private FlowPane root;
    // this box contains general stats and klicker stuff
    private VBox statsAndKlickerBox;
    // this box contains the buildings - also here informations about them and
    // the possibility to make them better
    private VBox buildingsBox;

    // graphic elements like labels and buttons

    /* logical stuff: the player, the clicker and the buildings */

    private Player player;
    private Clicker clicker;

    private Producer bakery;
    private boolean bakeryEnabled;
    private Producer factory;
    private boolean factoryEnabled;
    private Producer cookieSmithy;
    private boolean cookieSmithyEnabled;

    // these are graphical elements that are also needed outside of the start
    // method

    private Label cookiesLabel;
    private Label cookiesEverProducedLabel;

    private Label clickerLabel;
    private Label clickerProductionValueLabel;
    private Button levelUpClickerButton;

    private Label bakeryLabel;
    private Label bakeryProductionValueLabel;
    private Button levelUpBakeryButton;

    private Label factoryLabel;
    private Label factoryProductionValueLabel;
    private Button levelUpFactoryButton;

    private Label cookieSmithyLabel;
    private Label cookieSmithyProductionValueLabel;
    private Button levelUpCookieSmithyButton;

    public Main() {
        player = new Player();
        clicker = new Clicker();
        bakery = new Producer("Bakery", 1, 100);
        bakeryEnabled = false;
        factory = new Producer("Factory", 5, 1000);
        factoryEnabled = false;
        cookieSmithy = new Producer("Cookie Smithy", 10, 10000);
        cookieSmithyEnabled = false;
    }

    // tasks of this method: initialize all graphical elements and add
    // functionality to the interactive elements (that are only buttons here)
    @Override
    public void start(Stage stage) {
        // initialze and configure the basic containers and the information
        // Label

        root = new FlowPane();

        statsAndKlickerBox = new VBox();
        statsAndKlickerBox.setSpacing(5);
        statsAndKlickerBox.setPrefWidth(200);
        statsAndKlickerBox.setPrefHeight(230);

        buildingsBox = new VBox();
        buildingsBox.setSpacing(5);
        buildingsBox.setPrefWidth(200);
        buildingsBox.setPrefHeight(230);

        Label informationLabel = new Label("Arthoria.de - A nice german on" + 
          "line game!");

        // adding the containers and the label 
        root.getChildren().addAll(statsAndKlickerBox, buildingsBox, 
        informationLabel);

        // is used for displaying information, for example when a building has
        // been improved

        // elements for the statsAndKlickerBox

        Label headlineLabel = new Label("Statistics");
        headlineLabel.setStyle("-fx-font-weight: bold;");
        cookiesLabel = new Label("Cookies: " + player.getCookies());
        cookiesEverProducedLabel = new Label("All Cookies: " +
          player.getCookiesEverProduced());
        Label producerProductivityLabel = new Label("Producers Productivity: "  
          + Producer.getAlltogetherProductivity());

        Button produceCookiesButton = new Button("Produce Cookies");
        produceCookiesButton.setOnAction(event -> {
            player.receiveCookies(clicker.getProductionValue());
            actualizeCookieStats();
        });

        clickerLabel = new Label("Clicker Level " + clicker.getLevel());
        clickerLabel.setStyle("-fx-font-weight: bold;");
        clickerProductionValueLabel = new Label("Production Value: " + 
        clicker.getProductionValue());
        levelUpClickerButton = new Button("Improve (Costs " + 
          clicker.getPrice() + ")");
        levelUpClickerButton.setOnAction(event -> {
            boolean hasImproved = clicker.levelUp(player);
            if (hasImproved) {
                actualizeCookieStats();
                actualizeClickerStats();
                informationLabel.setText("Clicker successfully improved");
            } else {
                informationLabel.setText("Not enough Cookies for improving" +
                  " Clicker");
            }
        });

        bakeryLabel = new Label("Bakery Level " + bakery.getLevel());
        bakeryLabel.setStyle("-fx-font-weight: bold;");
        bakeryProductionValueLabel = new Label("Production Value: " + 
        bakery.getProductionValue());
        levelUpBakeryButton = new Button("Improve (Costs " + 
          bakery.getPrice() + ")");
        levelUpBakeryButton.setOnAction(event -> {
            boolean hasImproved = bakery.levelUp(player);
            if (hasImproved) {
                actualizeCookieStats();
                actualizeBakeryStats();
                informationLabel.setText("Bakery successfully improved");
            } else {
                informationLabel.setText("Not enough Cookies for improving" +
                  " Baker");
            }
        });

        factoryLabel = new Label("Factory Level " + factory.getLevel());
        factoryLabel.setStyle("-fx-font-weight: bold;");
        factoryProductionValueLabel = new Label("Production Value: " + 
        factory.getProductionValue());
        levelUpFactoryButton = new Button("Improve (Costs " + 
          factory.getPrice() + ")");
        levelUpFactoryButton.setOnAction(event -> {
            boolean hasImproved = factory.levelUp(player);
            if (hasImproved) {
                actualizeCookieStats();
                actualizeFactoryStats();
                informationLabel.setText("Factory successfully improved");
            } else {
                informationLabel.setText("Not enough Cookies for improving" +
                  " Factory");
            }
        });

        cookieSmithyLabel = new Label("Cookie Smithy Level " + cookieSmithy
          .getLevel());
        cookieSmithyLabel.setStyle("-fx-font-weight: bold;");
        cookieSmithyProductionValueLabel = new Label("Production Value: " + 
        cookieSmithy.getProductionValue());
        levelUpCookieSmithyButton = new Button("Improve (Costs " + 
          cookieSmithy.getPrice() + ")");
        levelUpCookieSmithyButton.setOnAction(event -> {
            boolean hasImproved = cookieSmithy.levelUp(player);
            if (hasImproved) {
                actualizeCookieStats();
                actualizeCookieSmithyStats();
                informationLabel.setText("Cookie Smithy successfully improved");
            } else {
                informationLabel.setText("Not enough Cookies for improving" +
                  " Cookie Smithy");
            }
        });

        // adding all elements to the statsAndKlickerBox

        statsAndKlickerBox.getChildren().add(headlineLabel);
        statsAndKlickerBox.getChildren().add(cookiesLabel);
        statsAndKlickerBox.getChildren().add(cookiesEverProducedLabel);
        statsAndKlickerBox.getChildren().add(producerProductivityLabel);
        statsAndKlickerBox.getChildren().add(clickerLabel);
        statsAndKlickerBox.getChildren().add(produceCookiesButton);
        statsAndKlickerBox.getChildren().add(clickerProductionValueLabel);
        statsAndKlickerBox.getChildren().add(levelUpClickerButton);

        // display window

        stage.setTitle("Cookie Clicker");
        stage.setScene(new Scene(root, 400, 250));
        stage.show();

        Timer producer = new Timer();
        producer.scheduleAtFixedRate(new TimerTask() {
            public void run() {
                Platform.runLater(() -> {
                    checkIfnewBuildingAvailable();
                    player.receiveCookies(bakery.getProductionValue());
                    player.receiveCookies(factory.getProductionValue());
                    player.receiveCookies(cookieSmithy.getProductionValue());
                    actualizeCookieStats();
                    clickerProductionValueLabel.setText("Production Value: " + 
                      clicker.getProductionValue());
                    producerProductivityLabel.setText("Producers Productivity: "
                      + Producer.getAlltogetherProductivity());
                });
            }
        }, 0, 1000);
    }

    private void checkIfnewBuildingAvailable() {
        if (player.getCookiesEverProduced() >= 20 && !bakeryEnabled) {
            buildingsBox.getChildren().add(bakeryLabel);
            buildingsBox.getChildren().add(bakeryProductionValueLabel);
            buildingsBox.getChildren().add(levelUpBakeryButton);
            bakeryEnabled = true;
        }
        if (player.getCookiesEverProduced() >= 1000 && !factoryEnabled) {
            buildingsBox.getChildren().add(factoryLabel);
            buildingsBox.getChildren().add(factoryProductionValueLabel);
            buildingsBox.getChildren().add(levelUpFactoryButton);
            factoryEnabled = true;          
        }
        if (player.getCookiesEverProduced() >= 10000 && !cookieSmithyEnabled) {
            buildingsBox.getChildren().add(cookieSmithyLabel);
            buildingsBox.getChildren().add(cookieSmithyProductionValueLabel);
            buildingsBox.getChildren().add(levelUpCookieSmithyButton);
            cookieSmithyEnabled = true;
        }
    }

    /* the following methods have the task to actualize the informations 
     * displayed in the view
     */

     private void actualizeCookieStats() {
        cookiesLabel.setText("Cookies: " + player.getCookies());
        cookiesEverProducedLabel.setText("All Cookies " + 
          player.getCookiesEverProduced());
     }

     private void actualizeClickerStats() {
        clickerLabel.setText("Clicker Level " + clicker.getLevel());
        clickerProductionValueLabel.setText("Production Value: " + 
        clicker.getProductionValue());
        levelUpClickerButton.setText("Improve (Costs " +  clicker.getPrice() + 
          ")");
     }

     private void actualizeBakeryStats() {
        bakeryLabel.setText("Bakery Level " + bakery.getLevel());
        bakeryProductionValueLabel.setText("Production Value: " + 
        bakery.getProductionValue());
        levelUpBakeryButton.setText("Improve (Costs " + bakery.getPrice() + 
          ")");
     }

    private void actualizeFactoryStats() {
        factoryLabel.setText("Factory Level " + factory.getLevel());
        factoryProductionValueLabel.setText("Production Value: " + 
        factory.getProductionValue());
        levelUpFactoryButton.setText("Improve (Costs " + factory.
          getPrice() + ")");
    }

    private void actualizeCookieSmithyStats() {
        cookieSmithyLabel.setText("Cookie Smithy Level " + cookieSmithy
          .getLevel());
        cookieSmithyProductionValueLabel.setText("Production Value: " + 
        cookieSmithy.getProductionValue());
        levelUpCookieSmithyButton.setText("Improve (Costs " + cookieSmithy.
          getPrice() + ")");
    }
}

Player.java

public class Player {
    private int cookies;
    private int cookiesEverProduced;

    public Player() {
        cookies = 0;
        cookiesEverProduced = 0;
    }

    public int getCookies() {
        return cookies;
    }

    public int getCookiesEverProduced() {
        return cookiesEverProduced;
    }

    public void receiveCookies(int value) {
        cookies += value;
        cookiesEverProduced += value;
    }

    public boolean pay(int value) {
        if (value <= cookies) {
            cookies -= value;
            return true;
        } else {
            return false;
        }
    }
}

Producer.java

public class Producer {
    static protected int alltogetherProductivity;

    protected String name;
    protected int level;
    protected int basicProductionValue;
    protected int basicPrice;

    // this is needed for the compiler (otherwise Clicker cant be compiled, dont
    // aks me why)
    public Producer() {
    }

    public Producer(String name, int basicProductionValue, int basicPrice) {
        this.name = name;
        level = 0;
        this.basicProductionValue = basicProductionValue;
        this.basicPrice = basicPrice;
    }

    public int getLevel() {
        return level;
    }

    static public int getAlltogetherProductivity() {
        return alltogetherProductivity;
    }

    public int getProductionValue() {
        return basicProductionValue * level;
    }

    public boolean levelUp(Player player) {
        if(player.pay(getPrice())) {
            level++;
            alltogetherProductivity += basicProductionValue;
            return true;
        } else {
            return false;
        }
    }

    protected int getPrice() {
        return (int)(0.5 * basicPrice * (level * level + 1) + 0.5 * basicPrice * 
        (level + 1));
    }
}

Clicker.java

public class Clicker extends Producer {
    public Clicker() {
        name = "Klicker";
        level = 1;
        // the value productionValue is not needed
        basicPrice = 500;
    }

    @Override
    public int getProductionValue() {
        return (int)(level + 0.01 * level * alltogetherProductivity);
    }

    @Override
    public int getPrice() {
        return basicPrice;
    }

    // works very different from the super class method
    @Override
    public boolean levelUp(Player player) {
        if(player.pay(basicPrice)) {
            level++;
            increasePrice();
            return true;
        } else {
            return false;
        }
    }

    // is used instead of getPrice
    private void increasePrice() {
        basicPrice *= 2;
    }
}
\$\endgroup\$
  • \$\begingroup\$ the dropbox link is no longer valid :( \$\endgroup\$ – Theoriok Oct 22 '18 at 12:44
4
\$\begingroup\$

I don't have the time to write a complete review but I do have possible (big) change you may want to consider. That is to see if you can use javaFX's Properties to store (and update) your numbers.

For example, taken from here.

Example 3 Using the Fluent API

package bindingdemo;   

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.binding.NumberBinding;   

public class Main {

public static void main(String[] args) {
    IntegerProperty num1 = new SimpleIntegerProperty(1);
    IntegerProperty num2 = new SimpleIntegerProperty(2);
    NumberBinding sum = num1.add(num2);
    System.out.println(sum.getValue());
    num1.set(2);
    System.out.println(sum.getValue());
} }

This example shows that you can "bind" the result of some calculation to the input values. You can than use that binding to calculate the resulting cookies for your player.

This way, you only need to update the cookies of each factory (or other source) and the ammount of cookies available to the player will automatically update to the correct total.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.