diff --git a/app/pom.xml b/app/pom.xml
index e6a8434..17ed5af 100644
--- a/app/pom.xml
+++ b/app/pom.xml
@@ -12,6 +12,7 @@
UTF-8
+
com.diffplug.spotless
@@ -31,6 +32,12 @@
0.1
compile
+
+
+ org.openjfx
+ javafx-controls
+ 25
+
@@ -44,24 +51,6 @@
25
25
UTF-8
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/java/org/toop/Main.java b/app/src/main/java/org/toop/Main.java
index ed6a662..0f92ca8 100644
--- a/app/src/main/java/org/toop/Main.java
+++ b/app/src/main/java/org/toop/Main.java
@@ -1,54 +1,21 @@
package org.toop;
-import org.toop.app.gui.LocalServerSelector;
+import org.toop.app.App;
import org.toop.framework.asset.AssetLoader;
import org.toop.framework.asset.AssetManager;
-import org.toop.framework.asset.events.AssetEvents;
-import org.toop.framework.asset.resources.TextAsset;
import org.toop.framework.audio.SoundManager;
-import org.toop.framework.audio.events.AudioEvents;
-import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.networking.NetworkingClientManager;
import org.toop.framework.networking.NetworkingInitializationException;
-import java.nio.file.NotDirectoryException;
-
public class Main {
- static void main(String[] args) {
+ static void main(String[] args) {
+ initSystems();
+ App.run(args);
+ }
- javax.swing.SwingUtilities.invokeLater(LocalServerSelector::new);
-
- new EventFlow().listen(Main::loadingHandler);
-
- AssetManager.loadAssets(new AssetLoader("app/src/main/resources/assets"));
- var text = AssetManager.getAllOfType(TextAsset.class).getFirst().getResource();
- var jpg = AssetManager.getByName("background.jpg");
-
- System.out.println(jpg.getResource().getFile());
-
- text.load();
-
- IO.println(text.getContent());
-
- new Thread(NetworkingClientManager::new).start();
- new Thread(SoundManager::new).start();
-
- new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", true)).asyncPostEvent();
-// new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", false)).asyncPostEvent();
-// Thread.sleep(200);
-// new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", false)).asyncPostEvent();
-// new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", false)).asyncPostEvent();
-// Thread.sleep(200);
-// new EventFlow().addPostEvent(new AudioEvents.PlayAudio("mainmenu.wav", false)).asyncPostEvent();
-// new EventFlow().addPostEvent(new AudioEvents.PlayAudio("sadtrombone.wav", false)).asyncPostEvent();
- }
-
- private static void loadingHandler(AssetEvents.LoadingProgressUpdate update) {
- int loaded = update.hasLoadedAmount();
- int total = update.isLoadingAmount();
- double percent = (total == 0) ? 100.0 : (loaded * 100.0 / total);
- }
-
- private static void initSystems() throws NetworkingInitializationException, NotDirectoryException {
- }
+ private static void initSystems() throws NetworkingInitializationException {
+ AssetManager.loadAssets(new AssetLoader("app/src/main/resources/assets"));
+ new Thread(NetworkingClientManager::new).start();
+ new Thread(SoundManager::new).start();
+ }
}
diff --git a/app/src/main/java/org/toop/app/App.java b/app/src/main/java/org/toop/app/App.java
new file mode 100644
index 0000000..da9a955
--- /dev/null
+++ b/app/src/main/java/org/toop/app/App.java
@@ -0,0 +1,62 @@
+package org.toop.app;
+
+import org.toop.app.menu.MainMenu;
+import org.toop.app.menu.Menu;
+import org.toop.app.menu.QuitMenu;
+
+import javafx.application.Application;
+import javafx.scene.layout.StackPane;
+import javafx.scene.Scene;
+import javafx.stage.Stage;
+
+public class App extends Application {
+ private static Stage stage;
+ private static Scene scene;
+ private static StackPane root;
+
+ public static void run(String[] args) {
+ launch(args);
+ }
+
+ @Override
+ public void start(Stage stage) throws Exception {
+ final StackPane root = new StackPane(new MainMenu().getPane());
+ final Scene scene = new Scene(root);
+
+ stage.setTitle("pism");
+ stage.setMinWidth(1080);
+ stage.setMinHeight(720);
+
+ stage.setOnCloseRequest(event -> {
+ event.consume();
+ push(new QuitMenu());
+ });
+
+ stage.setScene(scene);
+ stage.setResizable(false);
+
+ stage.show();
+
+ App.stage = stage;
+ App.scene = scene;
+ App.root = root;
+ }
+
+ public static void activate(Menu menu) {
+ scene.setRoot(menu.getPane());
+ }
+
+ public static void push(Menu menu) {
+ root.getChildren().add(menu.getPane());
+ }
+
+ public static void pop() {
+ root.getChildren().removeLast();
+ }
+
+ public static void quit() {
+ stage.close();
+ }
+
+ public static StackPane getRoot() { return root; }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/gui/BackgroundPanel.java b/app/src/main/java/org/toop/app/gui/BackgroundPanel.java
deleted file mode 100644
index bd5c6d2..0000000
--- a/app/src/main/java/org/toop/app/gui/BackgroundPanel.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.toop.app.gui;
-
-import java.awt.*;
-import javax.swing.*;
-
-public class BackgroundPanel extends JPanel {
- private Image backgroundImage;
-
- public void setBackgroundImage(Image image) {
- this.backgroundImage = image;
- repaint();
- }
-
- @Override
- protected void paintComponent(Graphics g) {
- super.paintComponent(g);
- if (backgroundImage != null) {
- g.drawImage(backgroundImage, 0, 0, getWidth(), getHeight(), this);
- }
- }
-}
diff --git a/app/src/main/java/org/toop/app/gui/LocalGameSelector.form b/app/src/main/java/org/toop/app/gui/LocalGameSelector.form
deleted file mode 100644
index 0816519..0000000
--- a/app/src/main/java/org/toop/app/gui/LocalGameSelector.form
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
diff --git a/app/src/main/java/org/toop/app/gui/LocalGameSelector.java b/app/src/main/java/org/toop/app/gui/LocalGameSelector.java
deleted file mode 100644
index cf4a44b..0000000
--- a/app/src/main/java/org/toop/app/gui/LocalGameSelector.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.toop.app.gui;
-
-import java.awt.*;
-import javax.swing.*;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.toop.tictactoe.LocalTicTacToe;
-import org.toop.tictactoe.gui.UIGameBoard;
-
-public class LocalGameSelector extends JFrame {
- private static final Logger logger = LogManager.getLogger(LocalGameSelector.class);
-
- private JPanel panel1;
- private JComboBox gameSelectionComboBox;
- private JButton startGame;
- private JComboBox playerTypeSelectionBox;
- private JButton deleteSave;
-
- private JPanel cards; // CardLayout panel
- private CardLayout cardLayout;
-
- private UIGameBoard tttBoard;
-
- public LocalGameSelector() {
- setTitle("Local Game Selector");
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- setSize(1920, 1080);
- setLocationRelativeTo(null);
-
- // Setup CardLayout
- cardLayout = new CardLayout();
- cards = new JPanel(cardLayout);
- setContentPane(cards);
-
- // --- Main menu panel ---
- panel1 = new JPanel();
- panel1.setLayout(new FlowLayout());
- gameSelectionComboBox = new JComboBox<>();
- gameSelectionComboBox.addItem("Tic Tac Toe");
- gameSelectionComboBox.addItem("Reversi");
-
- playerTypeSelectionBox = new JComboBox<>();
- playerTypeSelectionBox.addItem("Player vs Player");
- playerTypeSelectionBox.addItem("Player vs AI");
- playerTypeSelectionBox.addItem("AI vs Player");
-
- panel1.add(gameSelectionComboBox);
- panel1.add(playerTypeSelectionBox);
-
- startGame = new JButton("Start Game");
- panel1.add(startGame);
-
- deleteSave = new JButton("Delete Save");
- panel1.add(deleteSave);
- deleteSave.setEnabled(false);
- deleteSave.addActionListener(
- e -> {
- tttBoard = null;
- deleteSave.setEnabled(false);
- });
-
- cards.add(panel1, "MainMenu");
-
- // Start button action
- startGame.addActionListener(e -> startGameClicked());
-
- setVisible(true);
- }
-
- private void startGameClicked() {
- String playerTypes = (String) playerTypeSelectionBox.getSelectedItem();
- String selectedGame = (String) gameSelectionComboBox.getSelectedItem();
-
- LocalTicTacToe lttt = null;
-
- if (playerTypes.equals("Player vs Player")) {
- logger.info("Player vs Player");
- lttt = LocalTicTacToe.createLocal(new boolean[] {false, false});
- } else {
- if (playerTypes.equals("Player vs AI")) {
- logger.info("Player vs AI");
- lttt = LocalTicTacToe.createLocal(new boolean[] {false, true});
- } else {
- logger.info("AI vs Player");
- lttt = LocalTicTacToe.createLocal(new boolean[] {true, false});
- }
- }
-
- if ("Tic Tac Toe".equalsIgnoreCase(selectedGame)) {
- if (tttBoard == null) {
- tttBoard = new UIGameBoard(lttt, this);
- cards.add(tttBoard.getTTTPanel(), "TicTacToe");
- }
- cardLayout.show(cards, "TicTacToe");
- }
- lttt.startThreads();
- }
-
- public void showMainMenu() {
- cardLayout.show(cards, "MainMenu");
- gameSelectionComboBox.setSelectedIndex(0);
- playerTypeSelectionBox.setSelectedIndex(0);
- if (tttBoard != null) {
- deleteSave.setEnabled(true);
- }
- }
-}
diff --git a/app/src/main/java/org/toop/app/gui/LocalServerSelector.form b/app/src/main/java/org/toop/app/gui/LocalServerSelector.form
deleted file mode 100644
index 68623a2..0000000
--- a/app/src/main/java/org/toop/app/gui/LocalServerSelector.form
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
diff --git a/app/src/main/java/org/toop/app/gui/LocalServerSelector.java b/app/src/main/java/org/toop/app/gui/LocalServerSelector.java
deleted file mode 100644
index 50eb60b..0000000
--- a/app/src/main/java/org/toop/app/gui/LocalServerSelector.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.toop.app.gui;
-
-import javax.swing.*;
-
-public class LocalServerSelector {
- private JPanel panel1;
- private JButton serverButton;
- private JButton localButton;
- private final JFrame frame;
-
- public LocalServerSelector() {
- frame = new JFrame("Server Selector");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setContentPane(panel1);
- frame.setSize(1920, 1080);
- frame.setLocationRelativeTo(null); // Sets to center
- frame.setVisible(true);
-
- serverButton.addActionListener(e -> onServerClicked());
- localButton.addActionListener(e -> onLocalClicked());
- }
-
- private void onServerClicked() {
- frame.dispose();
- new RemoteGameSelector();
- }
-
- private void onLocalClicked() {
- frame.dispose();
- new LocalGameSelector();
- }
-}
diff --git a/app/src/main/java/org/toop/app/gui/RemoteGameSelector.form b/app/src/main/java/org/toop/app/gui/RemoteGameSelector.form
deleted file mode 100644
index df43ead..0000000
--- a/app/src/main/java/org/toop/app/gui/RemoteGameSelector.form
+++ /dev/null
@@ -1,147 +0,0 @@
-
-
diff --git a/app/src/main/java/org/toop/app/gui/RemoteGameSelector.java b/app/src/main/java/org/toop/app/gui/RemoteGameSelector.java
deleted file mode 100644
index 3e09acc..0000000
--- a/app/src/main/java/org/toop/app/gui/RemoteGameSelector.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package org.toop.app.gui;
-
-import java.awt.event.ActionEvent;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Supplier;
-import javax.swing.*;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.framework.networking.NetworkingGameClientHandler;
-import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.tictactoe.LocalTicTacToe;
-import org.toop.tictactoe.gui.UIGameBoard;
-
-public class RemoteGameSelector {
- private static final Logger logger = LogManager.getLogger(RemoteGameSelector.class);
-
- private JPanel mainMenu;
- private JTextField nameTextField;
- private JTextField name2TextField;
- private JTextField ipTextField;
- private JTextField portTextField;
- private JButton connectButton;
- private JComboBox gameSelectorBox;
- private JPanel cards;
- private JPanel gameSelector;
- private JFrame frame;
- private JLabel fillAllFields;
-
- private LocalTicTacToe localTicTacToe;
-
- public RemoteGameSelector() {
- gameSelectorBox.addItem("Tic Tac Toe");
- gameSelectorBox.addItem("Reversi");
- // todo get supported games from server and add to gameSelectorBox
- frame = new JFrame("Game Selector");
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setSize(1920, 1080);
- frame.setResizable(true);
-
- init();
- frame.add(mainMenu);
- frame.setVisible(true);
- // GlobalEventBus.subscribeAndRegister() Todo add game panel to frame when connection
- // succeeds
-
- }
-
- private void init() {
- connectButton.addActionListener(
- (ActionEvent e) -> {
- if (!nameTextField.getText().isEmpty()
- && !name2TextField.getText().isEmpty()
- && !ipTextField.getText().isEmpty()
- && !portTextField.getText().isEmpty()) {
-
- AtomicReference clientId = new AtomicReference<>();
- new EventFlow()
- .addPostEvent(
- NetworkEvents.StartClient.class,
- (Supplier)
- new NetworkingGameClientHandler(clientId.get()),
- "127.0.0.1",
- 5001)
- .onResponse(
- NetworkEvents.StartClientResponse.class,
- (response) -> {
- clientId.set(response.clientId());
- })
- .asyncPostEvent();
-
- // GlobalEventBus.subscribeAndRegister(
- // NetworkEvents.ReceivedMessage.class,
- // event -> {
- // if
- // (event.message().equalsIgnoreCase("ok")) {
- // logger.info("received ok from
- // server.");
- // } else if
- // (event.message().toLowerCase().startsWith("gameid")) {
- // String gameId =
- // event.message()
- // .toLowerCase()
- // .replace("gameid
- // ", "");
- // GlobalEventBus.post(
- // new
- // NetworkEvents.SendCommand(
- // "start_game " +
- // gameId));
- // } else {
- // logger.info("{}",
- // event.message());
- // }
- // });
- frame.remove(mainMenu);
- UIGameBoard ttt = new UIGameBoard(localTicTacToe, this);
- localTicTacToe.startThreads();
- frame.add(ttt.getTTTPanel()); // TODO: Fix later
- frame.revalidate();
- frame.repaint();
- } else {
- fillAllFields.setVisible(true);
- }
- });
- }
-
- public void showMainMenu() {
- frame.removeAll();
- frame.add(mainMenu);
- frame.revalidate();
- frame.repaint();
- }
-}
diff --git a/app/src/main/java/org/toop/app/menu/CreditsMenu.java b/app/src/main/java/org/toop/app/menu/CreditsMenu.java
new file mode 100644
index 0000000..96c77cd
--- /dev/null
+++ b/app/src/main/java/org/toop/app/menu/CreditsMenu.java
@@ -0,0 +1,6 @@
+package org.toop.app.menu;
+
+public final class CreditsMenu extends Menu {
+ public CreditsMenu() {
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/menu/MainMenu.java b/app/src/main/java/org/toop/app/menu/MainMenu.java
new file mode 100644
index 0000000..19d8040
--- /dev/null
+++ b/app/src/main/java/org/toop/app/menu/MainMenu.java
@@ -0,0 +1,31 @@
+package org.toop.app.menu;
+
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.image.ImageView;
+import javafx.scene.layout.*;
+
+public final class MainMenu extends Menu {
+ public MainMenu() {
+ final ImageView background = new ImageView();
+
+ final Button tictactoe = createButton("Tic Tac Toe", () -> {});
+ final Button reversi = createButton("Reversi", () -> {});
+ final Button sudoku = createButton("Sudoku", () -> {});
+ final Button battleship = createButton("Battleship", () -> {});
+ final Button other = createButton("Other", () -> {});
+
+ final VBox gamesBox = new VBox(tictactoe, reversi, sudoku, background, other);
+ gamesBox.setAlignment(Pos.TOP_CENTER);
+
+ final Button credits = createButton("Credits", () -> {});
+ final Button options = createButton("Options", () -> {});
+ final Button quit = createButton("Quit", () -> {});
+
+ final VBox creditsBox = new VBox(10, credits, options, quit);
+ creditsBox.setAlignment(Pos.BOTTOM_CENTER);
+
+ //pane = new StackPane(background, grid);
+ pane.getStylesheets().add(getClass().getResource("/style/main.css").toExternalForm());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/menu/Menu.java b/app/src/main/java/org/toop/app/menu/Menu.java
new file mode 100644
index 0000000..fc0627f
--- /dev/null
+++ b/app/src/main/java/org/toop/app/menu/Menu.java
@@ -0,0 +1,27 @@
+package org.toop.app.menu;
+
+import org.toop.app.App;
+
+import javafx.animation.FadeTransition;
+import javafx.scene.control.Button;
+import javafx.scene.layout.Pane;
+import javafx.util.Duration;
+
+public abstract class Menu {
+ protected Pane pane;
+ public Pane getPane() { return pane; }
+
+ public void fadeBackgroundImage(String imagePath, float from, float to, float milliseconds) {
+ final FadeTransition fade = new FadeTransition(Duration.millis(milliseconds), App.getRoot());
+ fade.setFromValue(from);
+ fade.setToValue(to);
+ fade.play();
+ }
+
+ public Button createButton(String text, Runnable runnable) {
+ final Button button = new Button(text);
+ button.setOnAction(_ -> runnable.run());
+ button.getStyleClass().add("button");
+ return button;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/menu/OptionsMenu.java b/app/src/main/java/org/toop/app/menu/OptionsMenu.java
new file mode 100644
index 0000000..541bb73
--- /dev/null
+++ b/app/src/main/java/org/toop/app/menu/OptionsMenu.java
@@ -0,0 +1,6 @@
+package org.toop.app.menu;
+
+public final class OptionsMenu extends Menu {
+ public OptionsMenu() {
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/menu/QuitMenu.java b/app/src/main/java/org/toop/app/menu/QuitMenu.java
new file mode 100644
index 0000000..fe359da
--- /dev/null
+++ b/app/src/main/java/org/toop/app/menu/QuitMenu.java
@@ -0,0 +1,48 @@
+package org.toop.app.menu;
+
+import javafx.geometry.Pos;
+import javafx.scene.control.Button;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Region;
+import javafx.scene.layout.StackPane;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Text;
+import org.toop.app.App;
+
+public final class QuitMenu extends Menu {
+ public QuitMenu() {
+ final Region background = new Region();
+ background.getStyleClass().add("quit-background");
+ background.setPrefSize(Double.MAX_VALUE, Double.MAX_VALUE);
+
+ final Text sure = new Text("Are you sure?");
+ sure.getStyleClass().add("quit-text");
+
+ final Button yes = new Button("Yes");
+ yes.getStyleClass().add("quit-button");
+ yes.setOnAction(_ -> {
+ App.quit();
+ });
+
+ final Button no = new Button("No");
+ no.getStyleClass().add("quit-button");
+ no.setOnAction(_ -> {
+ App.pop();
+ });
+
+ final HBox buttons = new HBox(10, yes, no);
+ buttons.setAlignment(Pos.CENTER);
+
+ VBox box = new VBox(43, sure, buttons);
+ box.setAlignment(Pos.CENTER);
+ box.getStyleClass().add("quit-box");
+ box.setMaxWidth(350);
+ box.setMaxHeight(200);
+
+ StackPane modalContainer = new StackPane(background, box);
+ StackPane.setAlignment(box, Pos.CENTER);
+
+ pane = modalContainer;
+ pane.getStylesheets().add(getClass().getResource("/style/quit.css").toExternalForm());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/events/WindowEvents.java b/app/src/main/java/org/toop/events/WindowEvents.java
deleted file mode 100644
index 59c22ff..0000000
--- a/app/src/main/java/org/toop/events/WindowEvents.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.toop.events;
-
-import org.toop.framework.eventbus.events.EventWithoutSnowflake;
-import org.toop.framework.eventbus.events.EventsBase;
-
-public class WindowEvents extends EventsBase {
- /** Triggers when a cell is clicked in one of the game boards. */
- public record CellClicked(int cell) implements EventWithoutSnowflake {}
-
- /** Triggers when the window wants to quit. */
- public record OnQuitRequested() implements EventWithoutSnowflake {}
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/tictactoe/LocalTicTacToe.java b/app/src/main/java/org/toop/tictactoe/LocalTicTacToe.java
index 3503334..e69de29 100644
--- a/app/src/main/java/org/toop/tictactoe/LocalTicTacToe.java
+++ b/app/src/main/java/org/toop/tictactoe/LocalTicTacToe.java
@@ -1,233 +0,0 @@
-package org.toop.tictactoe;
-
-import java.util.concurrent.*;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.game.Game;
-import org.toop.game.tictactoe.TicTacToe;
-import org.toop.game.tictactoe.TicTacToeAI;
-import org.toop.tictactoe.gui.UIGameBoard;
-
-/**
- * A representation of a local tic-tac-toe game. Calls are made to a server for information about
- * current game state. MOST OF THIS CODE IS TRASH, THROW IT OUT OF THE WINDOW AFTER DEMO.
- */
-// Todo: refactor
-public class LocalTicTacToe { // TODO: Implement runnable
- private static final Logger logger = LogManager.getLogger(LocalTicTacToe.class);
-
- private final ExecutorService executor = Executors.newFixedThreadPool(3);
- private final BlockingQueue receivedQueue = new LinkedBlockingQueue<>();
- private final BlockingQueue moveQueuePlayerA = new LinkedBlockingQueue<>();
- private final BlockingQueue moveQueuePlayerB = new LinkedBlockingQueue<>();
-
- private Object receivedMessageListener = null;
-
- private boolean isLocal;
- private String gameId;
- private long clientId = -1;
- private String serverId = null;
-
- private boolean[] isAiPlayer = new boolean[2];
- private TicTacToeAI ai = new TicTacToeAI();
- private TicTacToe ticTacToe;
- private UIGameBoard ui;
-
- /** Is either 0 or 1. */
- private int playersTurn = 0;
-
- /**
- * @return The current players turn.
- */
- public int getCurrentPlayersTurn() {
- return this.playersTurn;
- }
-
- // LocalTicTacToe(String gameId, String connectionId, String serverId) {
- // this.gameId = gameId;
- // this.connectionId = connectionId;
- // this.serverId = serverId;
- // this.receivedMessageListener =
- // GlobalEventBus.subscribe(Events.ServerEvents.ReceivedMessage.class,
- // this::receiveMessageAction);
- // GlobalEventBus.register(this.receivedMessageListener);
- //
- //
- // this.executor.submit(this::gameThread);
- // } TODO: If remote server
-
- /**
- * Starts a connection with a remote server.
- *
- * @param ip The IP of the server to connect to.
- * @param port The port of the server to connect to.
- */
- private LocalTicTacToe(String ip, int port) {
- // this.receivedMessageListener =
- // GlobalEventBus.subscribe(this::receiveMessageAction);
- // GlobalEventBus.subscribe(this.receivedMessageListener);
- // this.connectionId = this.createConnection(ip, port); TODO: Refactor this
- this.createGame("X", "O");
- this.isLocal = false;
- // this.executor.submit(this::remoteGameThread);
- }
-
- private LocalTicTacToe(boolean[] aiFlags) {
- this.isAiPlayer = aiFlags; // store who is AI
- this.isLocal = true;
- // this.executor.submit(this::localGameThread);
- }
-
- public void startThreads() {
- if (isLocal) {
- this.executor.submit(this::localGameThread);
- } else {
- this.executor.submit(this::remoteGameThread);
- }
- }
-
- public static LocalTicTacToe createLocal(boolean[] aiPlayers) {
- return new LocalTicTacToe(aiPlayers);
- }
-
- public static LocalTicTacToe createRemote(String ip, int port) {
- return new LocalTicTacToe(ip, port);
- }
-
- private void createGame(String nameA, String nameB) {
- nameA = nameA.trim().replace(" ", "-");
- nameB = nameB.trim().replace(" ", "-");
- this.sendCommand("create_game", nameA, nameB);
- }
-
- private void startGame() {
- if (this.gameId == null) {
- return;
- }
- this.sendCommand("start_game", this.gameId);
- }
-
- private void localGameThread() {
- boolean running = true;
- this.ticTacToe = new TicTacToe("X", "O");
- while (running) {
- try {
- Game.State state;
- if (!isAiPlayer[0]) {
- state = this.ticTacToe.play(this.moveQueuePlayerA.take());
- } else {
- Game.Move bestMove = ai.findBestMove(this.ticTacToe, 9);
- assert bestMove != null;
-
- state = this.ticTacToe.play(bestMove);
- ui.setCell(bestMove.position(), "X");
- }
- if (state == Game.State.WIN || state == Game.State.DRAW) {
- ui.setState(state, "X");
- running = false;
- }
- this.setNextPlayersTurn();
- if (!isAiPlayer[1]) {
- state = this.ticTacToe.play(this.moveQueuePlayerB.take());
- } else {
- Game.Move bestMove = ai.findBestMove(this.ticTacToe, 9);
- assert bestMove != null;
- state = this.ticTacToe.play(bestMove);
- ui.setCell(bestMove.position(), "O");
- }
- if (state == Game.State.WIN || state == Game.State.DRAW) {
- ui.setState(state, "O");
- running = false;
- }
- this.setNextPlayersTurn();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- private void remoteGameThread() {
- // TODO: If server start this.
- }
-
- public void setNextPlayersTurn() {
- if (this.playersTurn == 0) {
- this.playersTurn += 1;
- } else {
- this.playersTurn -= 1;
- }
- }
-
- public char[] getCurrentBoard() {
- // return ticTacToe.getGrid();
- return new char[2];
- }
-
- /** End the current game. */
- public void endGame() {
- sendCommand("gameid", "end_game"); // TODO: Command is a bit wrong.
- }
-
- /**
- * @param moveIndex The index of the move to make.
- */
- public void move(int moveIndex) {
- this.executor.submit(
- () -> {
- try {
- if (this.playersTurn == 0 && !isAiPlayer[0]) {
- this.moveQueuePlayerA.put(new Game.Move(moveIndex, 'X'));
- logger.info(
- "Adding player's {}, move: {} to queue A",
- this.playersTurn,
- moveIndex);
- } else if (this.playersTurn == 1 && !isAiPlayer[1]) {
- this.moveQueuePlayerB.put(new Game.Move(moveIndex, 'O'));
- logger.info(
- "Adding player's {}, move: {} to queue B",
- this.playersTurn,
- moveIndex);
- }
- } catch (InterruptedException e) {
- logger.error(
- "Could not add player: {}'s, move {}",
- this.playersTurn,
- moveIndex); // TODO: Error handling instead of crash.
- }
- });
- }
-
- private void endTheGame() {
- this.sendCommand("end_game", this.gameId);
- // this.endListeners();
- }
-
- private void receiveMessageAction(NetworkEvents.ReceivedMessage receivedMessage) {
- if (receivedMessage.clientId() != this.clientId) {
- return;
- }
-
- try {
- logger.info("Received message from {}: {}", this.clientId, receivedMessage.message());
- this.receivedQueue.put(receivedMessage.message());
- } catch (InterruptedException e) {
- logger.error("Error waiting for received Message", e);
- }
- }
-
- private void sendCommand(String... args) {
- new EventFlow()
- .addPostEvent(NetworkEvents.SendCommand.class, this.clientId, args)
- .asyncPostEvent();
- }
-
- // private void endListeners() {
- // GlobalEventBus.unregister(this.receivedMessageListener);
- // } TODO
-
- public void setUIReference(UIGameBoard uiGameBoard) {
- this.ui = uiGameBoard;
- }
-}
diff --git a/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.form b/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.form
deleted file mode 100644
index b69fad4..0000000
--- a/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.form
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
diff --git a/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.java b/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.java
index 0c54a6b..e69de29 100644
--- a/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.java
+++ b/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.java
@@ -1,158 +0,0 @@
-package org.toop.tictactoe.gui;
-
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.Locale;
-import javax.swing.*;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.toop.app.gui.LocalGameSelector;
-import org.toop.app.gui.RemoteGameSelector;
-import org.toop.framework.audio.events.AudioEvents;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.game.Game;
-import org.toop.tictactoe.LocalTicTacToe;
-
-public class UIGameBoard {
- private static final int TICTACTOE_SIZE = 3;
-
- private static final Logger logger = LogManager.getLogger(LocalGameSelector.class);
-
- private JPanel tttPanel; // Root panel for this game
- private JButton backToMainMenuButton;
- private JButton[] cells;
- private String currentPlayer = "X";
- private int currentPlayerIndex = 0;
-
- private Object parentSelector;
- private boolean parentLocal;
- private LocalTicTacToe localTicTacToe;
-
- private boolean gameOver = false;
-
- public UIGameBoard(LocalTicTacToe lttt, Object parent) {
- if (!(parent == null)) {
- if (parent instanceof LocalGameSelector) {
- parentLocal = true;
- } else if (parent instanceof RemoteGameSelector) {
- parentLocal = false;
- }
- }
- this.parentSelector = parent;
- this.localTicTacToe = lttt;
- lttt.setUIReference(this);
-
- // Root panel
- tttPanel = new JPanel(new BorderLayout());
-
- // Back button
- backToMainMenuButton = new JButton("Back to Main Menu");
-
- tttPanel.add(backToMainMenuButton, BorderLayout.SOUTH);
- backToMainMenuButton.addActionListener(
- _ -> {
- // TODO reset game and connections
- // Game now gets reset in local
- if (parentLocal) {
- ((LocalGameSelector) parent).showMainMenu();
- } else {
- ((RemoteGameSelector) parent).showMainMenu();
- }
- });
-
- // Game grid
- JPanel gameGrid = createGridPanel(TICTACTOE_SIZE, TICTACTOE_SIZE);
- tttPanel.add(gameGrid, BorderLayout.CENTER);
-
- // localTicTacToe.setMoveListener((playerIndex, moveIndex, symbol) -> {
- // SwingUtilities.invokeLater(() -> {
- // cells[moveIndex].setText(String.valueOf(symbol));
- // });
- // });
-
- }
-
- private JPanel createGridPanel(int sizeX, int sizeY) {
- JPanel panel = new JPanel(new GridLayout(sizeX, sizeY));
- cells = new JButton[sizeX * sizeY];
-
- for (int i = 0; i < sizeX * sizeY; i++) {
- cells[i] = new JButton(" ");
- cells[i].setFont(new Font("Arial", Font.BOLD, 400 / sizeX));
- panel.add(cells[i]);
- cells[i].setFocusable(false);
-
- final int index = i;
- cells[i].addActionListener(
- (ActionEvent _) -> {
- if (!gameOver) {
- if (cells[index].getText().equals(" ")) {
- int cp = this.localTicTacToe.getCurrentPlayersTurn();
- if (cp == 0) {
- this.currentPlayer = "X";
- currentPlayerIndex = 0;
- } else if (cp == 1) {
- this.currentPlayer = "O";
- currentPlayerIndex = 1;
- }
- this.localTicTacToe.move(index);
- cells[index].setText(currentPlayer);
- new EventFlow().addPostEvent(
- new AudioEvents.PlayAudio("hitsound0", false)
- ).asyncPostEvent();
- } else {
- logger.info(
- "Player "
- + currentPlayerIndex
- + " attempted invalid move at: "
- + cells[index].getText());
- }
- } else {
- logger.info(
- "Player "
- + currentPlayerIndex
- + " attempted to move after the game has ended.");
- }
- });
- }
-
- return panel;
- }
-
- public void setCell(int index, String move) {
- System.out.println(cells[index].getText());
- cells[index].setText(move);
- }
-
- public void setState(Game.State state, String playerMove) {
- Color color;
- if (state == Game.State.WIN && playerMove.equals(currentPlayer)) {
- color = new Color(160, 220, 160);
- new EventFlow().addPostEvent(
- new AudioEvents.PlayAudio("winsound", false)
- ).asyncPostEvent();
- } else if (state == Game.State.WIN) {
- color = new Color(220, 160, 160);
- new EventFlow().addPostEvent(
- new AudioEvents.PlayAudio("sadtrombone", false)
- ).asyncPostEvent();
- } else if (state == Game.State.DRAW) {
- color = new Color(220, 220, 160);
- new EventFlow().addPostEvent(
- new AudioEvents.PlayAudio("dramatic", false)
- ).asyncPostEvent();
- } else {
- color = new Color(220, 220, 220);
- }
- for (JButton cell : cells) {
- cell.setBackground(color);
- }
- if (state == Game.State.DRAW || state == Game.State.WIN) {
- gameOver = true;
- }
- }
-
- public JPanel getTTTPanel() {
- return tttPanel;
- }
-}
diff --git a/app/src/main/resources/image/game/battleship.png b/app/src/main/resources/image/game/battleship.png
new file mode 100644
index 0000000..813893f
Binary files /dev/null and b/app/src/main/resources/image/game/battleship.png differ
diff --git a/app/src/main/resources/image/game/other.png b/app/src/main/resources/image/game/other.png
new file mode 100644
index 0000000..6bd4167
Binary files /dev/null and b/app/src/main/resources/image/game/other.png differ
diff --git a/app/src/main/resources/image/game/reversi.png b/app/src/main/resources/image/game/reversi.png
new file mode 100644
index 0000000..bd9252f
Binary files /dev/null and b/app/src/main/resources/image/game/reversi.png differ
diff --git a/app/src/main/resources/image/game/sudoku.png b/app/src/main/resources/image/game/sudoku.png
new file mode 100644
index 0000000..ec88234
Binary files /dev/null and b/app/src/main/resources/image/game/sudoku.png differ
diff --git a/app/src/main/resources/image/game/tictactoe.png b/app/src/main/resources/image/game/tictactoe.png
new file mode 100644
index 0000000..2a81e05
Binary files /dev/null and b/app/src/main/resources/image/game/tictactoe.png differ
diff --git a/app/src/main/resources/style/main.css b/app/src/main/resources/style/main.css
new file mode 100644
index 0000000..99e8087
--- /dev/null
+++ b/app/src/main/resources/style/main.css
@@ -0,0 +1,33 @@
+.main-button {
+ -fx-background-color: transparent;
+ -fx-background-image: url("card-default.jpg"); /* fallback image */
+ -fx-background-size: cover;
+ -fx-background-position: center;
+ -fx-pref-width: 250px;
+ -fx-pref-height: 180px;
+ -fx-border-radius: 15;
+ -fx-background-radius: 15;
+ -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 15, 0.4, 0, 4);
+ -fx-cursor: hand;
+ -fx-padding: 0;
+}
+
+.card-label {
+ -fx-background-color: rgba(0, 0, 0, 0.5);
+ -fx-font-size: 20px;
+ -fx-font-weight: bold;
+ -fx-text-fill: white;
+ -fx-padding: 10px;
+ -fx-alignment: top-center;
+ -fx-background-radius: 15 15 0 0;
+ -fx-opacity: 0;
+ -fx-transition: all 0.3s ease;
+}
+
+.main-button:hover {
+ -fx-effect: dropshadow(gaussian, #00ffff, 15, 0.5, 0, 0);
+}
+
+.main-button:hover .card-label {
+ -fx-opacity: 1;
+}
\ No newline at end of file
diff --git a/app/src/main/resources/style/quit.css b/app/src/main/resources/style/quit.css
new file mode 100644
index 0000000..59c72a3
--- /dev/null
+++ b/app/src/main/resources/style/quit.css
@@ -0,0 +1,33 @@
+.quit-background {
+ -fx-background-color: rgba(0, 0, 0, 0.6);
+}
+
+.quit-box {
+ -fx-background-color: rgba(30, 30, 30, 0.95);
+ -fx-background-radius: 15;
+ -fx-padding: 30;
+ -fx-effect: dropshadow(gaussian, black, 20, 0.6, 0, 4);
+}
+
+.quit-text {
+ -fx-fill: white;
+ -fx-font-size: 28px;
+ -fx-font-weight: 600;
+ -fx-font-family: "Segoe UI", sans-serif;
+}
+
+.quit-button {
+ -fx-font-size: 16px;
+ -fx-text-fill: white;
+ -fx-background-color: transparent;
+ -fx-border-color: white;
+ -fx-border-radius: 5;
+ -fx-padding: 8 20;
+ -fx-cursor: hand;
+}
+
+.quit-button:hover {
+ -fx-text-fill: #00ffff;
+ -fx-border-color: #00ffff;
+ -fx-effect: dropshadow(gaussian, #00ffff, 8, 0.5, 0, 0);
+}
\ No newline at end of file
diff --git a/app/src/main/resources/style/style.css b/app/src/main/resources/style/style.css
new file mode 100644
index 0000000..c09d516
--- /dev/null
+++ b/app/src/main/resources/style/style.css
@@ -0,0 +1,20 @@
+.root {
+ -fx-background-color: #2d2d2d;
+
+ -fx-font-size: 28px;
+ -fx-font-weight: 600;
+ -fx-font-family: "Segoe UI", sans-serif;
+}
+
+.button {
+ -fx-background-color: transparent;
+ -fx-text-fill: white;
+ -fx-border-color: transparent;
+ -fx-padding: 10 20;
+ -fx-cursor: hand;
+ -fx-effect: null;
+}
+
+.button:hover {
+ -fx-effect: dropshadow(gaussian, #00ffff, 10, 0.3, 0, 0);
+}
\ No newline at end of file