diff --git a/app/pom.xml b/app/pom.xml index 962806c..ca89a53 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -6,12 +6,12 @@ 0.1 - org.toop.Main 25 25 UTF-8 + org.toop @@ -25,6 +25,12 @@ 0.1 compile + + + org.openjfx + javafx-controls + 25 + @@ -38,24 +44,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 f2f618e..9d9bbfb 100644 --- a/app/src/main/java/org/toop/Main.java +++ b/app/src/main/java/org/toop/Main.java @@ -1,13 +1,13 @@ package org.toop; -import org.toop.app.gui.LocalServerSelector; +import org.toop.app.App; import org.toop.framework.networking.NetworkingClientManager; import org.toop.framework.networking.NetworkingInitializationException; public class Main { static void main(String[] args) { initSystems(); - javax.swing.SwingUtilities.invokeLater(LocalServerSelector::new); + App.run(args); } private static void initSystems() throws NetworkingInitializationException { 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 0d13a98..0000000 --- a/app/src/main/java/org/toop/app/gui/RemoteGameSelector.java +++ /dev/null @@ -1,105 +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.events.NetworkEvents; -import org.toop.tictactoe.LocalTicTacToe; -import org.toop.framework.networking.NetworkingGameClientHandler; -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) NetworkingGameClientHandler::new, - "127.0.0.1", - 5001 - ).onResponse( - NetworkEvents.StartClientSuccess.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..d4e1b70 --- /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 deleted file mode 100644 index f361d8c..0000000 --- a/app/src/main/java/org/toop/tictactoe/LocalTicTacToe.java +++ /dev/null @@ -1,250 +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; -import org.toop.framework.networking.NetworkingGameClientHandler; - -import java.util.function.Supplier; - -import static java.lang.Thread.sleep; - -/** - * 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 String connectionId = null; - 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); - 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 String createConnection(String ip, int port) { - CompletableFuture connectionIdFuture = new CompletableFuture<>(); - new EventFlow().addPostEvent(NetworkEvents.StartClientRequest.class, - (Supplier) NetworkingGameClientHandler::new, - ip, port, connectionIdFuture).asyncPostEvent(); // TODO: what if server couldn't be started with port. - try { - return connectionIdFuture.get(); - } catch (InterruptedException | ExecutionException e) { - logger.error("Error getting connection ID", e); - } - return null; - } - - 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.ConnectionUuid().equals(this.connectionId)) { - return; - } - - try { - logger.info( - "Received message from {}: {}", this.connectionId, 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.connectionId, 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 deleted file mode 100644 index a8c0027..0000000 --- a/app/src/main/java/org/toop/tictactoe/gui/UIGameBoard.java +++ /dev/null @@ -1,144 +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.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); - } 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); - } else if (state == Game.State.WIN) { - color = new Color(220, 160, 160); - } else if (state == Game.State.DRAW) { - color = new Color(220, 220, 160); - } 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