Infinite recursion of class at initialization

67 Views Asked by At

I've been working on a side project in Java in order to become more familiar with threads. It's a cookie clicker clone that uses different threads for the clicker, the counter, and everything else. Upon trying to run the final build I get an infinite recursion error resulting in stack overflow at one of my class initialization. I've tried moving the class to its own file, but that doesn't seem to change anything. Here's the code:

Game.java

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.Dimension;

public class Game { // main class
    // Integer
    int total = 0;
    int perSec = 0;
    int perClick = 1;
    int upgradeIndex = 0;
    // Boolean
    boolean running = false;
    // JFrame
    JFrame window;
    // JTextField
    JTextField totalDisplay;
    // JButton
    JButton clickArea;
    JButton upgrade1;
    JButton upgrade2;
    JButton upgrade3;
    JButton nextPage;
    JButton prevPage;
    // JPanel
    JPanel clickWindow;
    JPanel upgrades;
    JPanel navigation;
    // Upgrades
        // Click upgrade
    PerClickUpgrade exclamation; // amount 1 cost 10
    PerClickUpgrade at; // amount 10 cost 100
    PerClickUpgrade hashtag; // amount 100 cost 1000
    PerClickUpgrade dollar; // amount 1000 cost 10000
        // Sec upgrade
    PerSecUpgrade percent; // amount 10 cost 1000
    PerSecUpgrade carrot; // amount 100 cost 10000
    PerSecUpgrade and; // amount 1000 cost 100000
        // Click multiplier
    PerClickMultiplier asterisk; // amount 2x cost 1000000
        // Sec multiplier
    PerSecMultiplier tilde; // amount 2x cost 10000000

    Game() {
        window = new JFrame(); // main window
        clickWindow = new JPanel(); // panel for click button
        upgrades = new JPanel(); // panel for upgrades
        upgrade1 = new JButton();
        upgrade2 = new JButton();
        upgrade3 = new JButton();
        navigation = new JPanel(); // navigate upgrade menu
        nextPage = new JButton();
        prevPage = new JButton();
        exclamation = new PerClickUpgrade("!", 1, 10, upgrade1);
        at = new PerClickUpgrade("@", 10, 100, upgrade2);
        hashtag = new PerClickUpgrade("#",100,1000,upgrade3);
        dollar = new PerClickUpgrade("$",1000,10000,upgrade1);
        percent = new PerSecUpgrade("%",10,1000,upgrade2);
        carrot = new PerSecUpgrade("^",100,10000, upgrade3);
        and = new PerSecUpgrade("&", 1000,100000, upgrade1);
        asterisk = new PerClickMultiplier("*",2,1000000, upgrade2);
        tilde = new PerSecMultiplier("~", 2, 10000000, upgrade3);
        window.setSize(new Dimension(800, 600));
        window.setResizable(false);
        window.setLocationRelativeTo(null);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setTitle("ASCII Clicker");
        window.setLayout(new BorderLayout());
        clickWindow.setPreferredSize(new Dimension((800 / 2), 600));
        upgrades.setPreferredSize(new Dimension((800 / 2), 600));
        navigation.setPreferredSize(new Dimension((800 / 2), (600 / 4)));
        clickWindow.setLayout(new BorderLayout());
        navigation.setLayout(new BorderLayout());
        window.add(clickWindow, BorderLayout.WEST);
        window.add(upgrades, BorderLayout.EAST);
        clickWindow.add(totalDisplay, BorderLayout.PAGE_START);
        clickWindow.add(clickArea, BorderLayout.CENTER);
        upgrades.add(upgrade1);
        upgrades.add(upgrade2);
        upgrades.add(upgrade3);
        upgrades.add(navigation);
        navigation.add(nextPage, BorderLayout.EAST);
        navigation.add(prevPage, BorderLayout.WEST);
        window.pack();
        Thread clickDetection = new Thread(new Clicker()); // detects clicks
        Thread counter = new Thread(new Counter()); // counts total
        clickDetection.start();
        counter.start();
        window.setVisible(true);
        exclamation.update(); // sets exclamation, at, and hashtag as displayed upgrades
        at.update();
        hashtag.update();
        upgrade1.addActionListener(e -> {
            switch (upgradeIndex) {
                case 0 -> exclamation.buy();
                case 1 -> dollar.buy();
                case 2 -> and.buy();
            }
        });
        upgrade2.addActionListener(e -> {
            switch (upgradeIndex) {
                case 0 -> at.buy();
                case 1 -> percent.buy();
                case 2 -> asterisk.buy();
            }
        });
        upgrade3.addActionListener(e -> {
            switch (upgradeIndex) {
                case 0 -> hashtag.buy();
                case 1 -> carrot.buy();
                case 2 -> tilde.buy();
            }
        });
        prevPage.addActionListener(e -> {
            if (upgradeIndex != 0) {
                upgradeIndex--;
                switch (upgradeIndex) {
                    case 0 -> {
                        exclamation.update();
                        at.update();
                        hashtag.update();
                    }
                    case 1 -> {
                        dollar.update();
                        percent.update();
                        carrot.update();
                    }
                    case 2 -> {
                        and.update();
                        asterisk.update();
                        tilde.update();
                    }
                }
            }
        });
        nextPage.addActionListener(e -> {
            if (upgradeIndex != 2) {
                upgradeIndex++;
                switch (upgradeIndex) {
                    case 0 -> {
                        exclamation.update();
                        at.update();
                        hashtag.update();
                    }
                    case 1 -> {
                        dollar.update();
                        percent.update();
                        carrot.update();
                    }
                    case 2 -> {
                        and.update();
                        asterisk.update();
                        tilde.update();
                    }
                }
            }
        });
    }

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

class Counter extends Game implements Runnable { // Updates counter

    @Override
    public void run() {
        running = true;
        while (running) {
            total += (perSec / 10);
            totalDisplay.setText(String.valueOf(total));
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Clicker extends Game implements Runnable { // Records clicks

    @Override
    public void run() {
        clickArea.setText("()");
        clickArea.addActionListener(e -> total += perClick);
    }
}

PerClickUpgrade.java


class PerClickUpgrade extends Game {
    private int totalUpgrade = 0;
    private int totalCost;
    private final int upgradeAmount;
    private final int cost;
    private int timesBought = 0;
    private final JButton display;
    private final String symbol;

    PerClickUpgrade(String symbol, int upgradeAmount, int cost, JButton display) {
        this.symbol = symbol;
        this.totalCost = cost;
        this.cost = cost;
        this.upgradeAmount = upgradeAmount;
        this.display = display;
    }

    public void update() {
        this.display.setText(
                this.symbol +
                        "\nOwned: " +
                        this.timesBought +
                        "\nPer Click Increase: " +
                        this.totalUpgrade +
                        "\nCost: " +
                        this.totalCost
        );
    }

    public void buy() {
        if (total >= this.totalCost) {
            this.timesBought++;
            this.totalUpgrade += this.upgradeAmount;
            perClick = this.totalUpgrade;
            total -= this.cost;
            this.totalCost += (this.cost / 2);
            this.update();
        }
    }
}

PerSecUpgrade.java


class PerSecUpgrade extends Game {
    private int totalUpgrade = 0;
    private int totalCost;
    private final int upgradeAmount;
    private final int cost;
    private int timesBought = 0;
    private final JButton display;
    private final String symbol;

    PerSecUpgrade(String symbol, int upgradeAmount, int cost, JButton display) {
        this.symbol = symbol;
        this.totalCost = cost;
        this.cost = cost;
        this.upgradeAmount = upgradeAmount;
        this.display = display;
    }

    void update() {
        this.display.setText(
                this.symbol +
                        "\nOwned: " +
                        this.timesBought +
                        "\nPer Click Increase: " +
                        this.totalUpgrade +
                        "\nCost: " +
                        this.totalCost
        );
    }

    void buy() {
        if (total >= this.totalCost) {
            this.timesBought++;
            this.totalUpgrade += this.upgradeAmount;
            perSec = this.totalUpgrade;
            total -= this.cost;
            this.totalCost += (this.cost / 2);
            this.update();
        }
    }
}

PerSecMultiplier.java


class PerSecMultiplier extends Game {
    private int totalCost;
    private final int upgradeAmount;
    private final int cost;
    private int timesBought = 0;
    private final JButton display;
    private final String symbol;

    PerSecMultiplier(String symbol, int upgradeAmount, int cost, JButton display) {
        this.symbol = symbol;
        this.totalCost = cost;
        this.cost = cost;
        this.upgradeAmount = upgradeAmount;
        this.display = display;
    }

    void update() {
        this.display.setText(
                this.symbol +
                        "\nOwned: " +
                        this.timesBought +
                        "\n" +
                        this.upgradeAmount +
                        "x Per Sec\nCost: " +
                        this.cost
        );
    }

    void buy() {
        if (total >= this.totalCost) {
            this.timesBought++;
            perSec *= this.upgradeAmount;
            total -= this.totalCost;
            this.totalCost += (this.cost / 2);
            this.update();
        }
    }
}

PerClickMultiplier


public class PerClickMultiplier extends Game {
    private final int upgradeAmount;
    private final int cost;
    private final JButton display;
    private final String symbol;
    private int totalCost;
    private int timesBought = 0;

    PerClickMultiplier(String symbol, int upgradeAmount, int cost, JButton display) {
        this.totalCost = cost;
        this.upgradeAmount = upgradeAmount;
        this.cost = cost;
        this.display = display;
        this.symbol = symbol;
    }

    void update() {
        this.display.setText(
                this.symbol +
                        "\nOwned: " +
                        this.timesBought +
                        "\n" +
                        this.upgradeAmount +
                        "x Per Click\nCost: " +
                        this.cost
        );
    }

    void buy() {
        if (total >= this.totalCost) {
            this.timesBought++;
            perClick *= this.upgradeAmount;
            total -= this.totalCost;
            this.totalCost += (this.cost / 2);
            this.update();
        }
    }
}

Any other general criticism is appreciated as well.

0

There are 0 best solutions below