From 38681c5db03e3e170c90ec3ec6795b6331b157df Mon Sep 17 00:00:00 2001
From: ramollia <>
Date: Thu, 27 Nov 2025 15:57:46 +0100
Subject: [PATCH] merge widgets with development
---
.idea/inspectionProfiles/Project_Default.xml | 584 +++++++++++++++++-
app/src/main/java/org/toop/app/Server.java | 12 +-
.../org/toop/app/canvas/Connect4Canvas.java | 2 +-
.../java/org/toop/app/canvas/GameCanvas.java | 22 +-
.../org/toop/app/canvas/ReversiCanvas.java | 95 ++-
.../org/toop/app/canvas/TicTacToeCanvas.java | 2 +-
.../org/toop/app/game/BaseGameThread.java | 14 +-
.../java/org/toop/app/game/Connect4Game.java | 275 ---------
.../org/toop/app/game/Connect4GameThread.java | 188 ++++++
.../java/org/toop/app/game/ReversiGame.java | 327 ----------
.../org/toop/app/game/ReversiGameThread.java | 241 ++++++++
.../java/org/toop/app/game/TicTacToeGame.java | 250 --------
.../toop/app/game/TicTacToeGameThread.java | 61 +-
app/src/main/java/org/toop/app/view/View.java | 400 ------------
.../java/org/toop/app/view/ViewStack.java | 105 ----
.../toop/app/view/displays/SongDisplay.java | 129 ----
.../toop/app/view/views/ChallengeView.java | 127 ----
.../org/toop/app/view/views/CreditsView.java | 110 ----
.../org/toop/app/view/views/ErrorView.java | 45 --
.../org/toop/app/view/views/GameView.java | 184 ------
.../app/view/views/LocalMultiplayerView.java | 171 -----
.../org/toop/app/view/views/LocalView.java | 57 --
.../org/toop/app/view/views/MainView.java | 55 --
.../org/toop/app/view/views/OnlineView.java | 91 ---
.../org/toop/app/view/views/OptionsView.java | 258 --------
.../org/toop/app/view/views/QuitView.java | 40 --
.../app/view/views/SendChallengeView.java | 119 ----
.../org/toop/app/view/views/ServerView.java | 89 ---
.../app/widget/view/LocalMultiplayerView.java | 8 +-
.../main/java/org/toop/local/AppContext.java | 3 +
30 files changed, 1122 insertions(+), 2942 deletions(-)
delete mode 100644 app/src/main/java/org/toop/app/game/Connect4Game.java
create mode 100644 app/src/main/java/org/toop/app/game/Connect4GameThread.java
delete mode 100644 app/src/main/java/org/toop/app/game/ReversiGame.java
create mode 100644 app/src/main/java/org/toop/app/game/ReversiGameThread.java
delete mode 100644 app/src/main/java/org/toop/app/game/TicTacToeGame.java
delete mode 100644 app/src/main/java/org/toop/app/view/View.java
delete mode 100644 app/src/main/java/org/toop/app/view/ViewStack.java
delete mode 100644 app/src/main/java/org/toop/app/view/displays/SongDisplay.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/ChallengeView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/CreditsView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/ErrorView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/GameView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/LocalMultiplayerView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/LocalView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/MainView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/OnlineView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/OptionsView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/QuitView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/SendChallengeView.java
delete mode 100644 app/src/main/java/org/toop/app/view/views/ServerView.java
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 655cfae..1448990 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,9 +1,591 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/Server.java b/app/src/main/java/org/toop/app/Server.java
index 00f91cc..9df2e2d 100644
--- a/app/src/main/java/org/toop/app/Server.java
+++ b/app/src/main/java/org/toop/app/Server.java
@@ -1,8 +1,8 @@
package org.toop.app;
-import org.toop.app.game.Connect4Game;
-import org.toop.app.game.ReversiGame;
-import org.toop.app.game.TicTacToeGame;
+import org.toop.app.game.Connect4GameThread;
+import org.toop.app.game.ReversiGameThread;
+import org.toop.app.game.TicTacToeGameThread;
import org.toop.app.widget.WidgetContainer;
import org.toop.app.widget.popup.ChallengePopup;
import org.toop.app.widget.popup.ErrorPopup;
@@ -131,11 +131,11 @@ public final class Server {
switch (type) {
case TICTACTOE ->
- new TicTacToeGame(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
+ new TicTacToeGameThread(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
case REVERSI ->
- new ReversiGame(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
+ new ReversiGameThread(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
case CONNECT4 ->
- new Connect4Game(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
+ new Connect4GameThread(information, myTurn, this::forfeitGame, this::exitGame, this::sendMessage, onGameOverRunnable);
default -> new ErrorPopup("Unsupported game type.");
}
}
diff --git a/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java b/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java
index c17dafd..913bb62 100644
--- a/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java
+++ b/app/src/main/java/org/toop/app/canvas/Connect4Canvas.java
@@ -6,6 +6,6 @@ import java.util.function.Consumer;
public class Connect4Canvas extends GameCanvas {
public Connect4Canvas(Color color, int width, int height, Consumer onCellClicked) {
- super(color, Color.TRANSPARENT, width, height, 7, 6, 10, true, onCellClicked,null);
+ super(color, Color.TRANSPARENT, width, height, 7, 6, 10, true, onCellClicked);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/canvas/GameCanvas.java b/app/src/main/java/org/toop/app/canvas/GameCanvas.java
index f8f6d70..7342f5b 100644
--- a/app/src/main/java/org/toop/app/canvas/GameCanvas.java
+++ b/app/src/main/java/org/toop/app/canvas/GameCanvas.java
@@ -35,8 +35,9 @@ public abstract class GameCanvas {
protected final boolean edges;
protected final Cell[] cells;
+ protected Cell currentCell;
- protected GameCanvas(Color color, Color backgroundColor, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges, Consumer onCellClicked, Consumer newCellEntered) {
+ protected GameCanvas(Color color, Color backgroundColor, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges, Consumer onCellClicked) {
canvas = new Canvas(width, height);
graphics = canvas.getGraphicsContext2D();
@@ -53,6 +54,7 @@ public abstract class GameCanvas {
this.edges = edges;
cells = new Cell[rowSize * columnSize];
+ currentCell = null;
final float cellWidth = ((float) width - gapSize * rowSize - gapSize) / rowSize;
final float cellHeight = ((float) height - gapSize * columnSize - gapSize) / columnSize;
@@ -82,12 +84,24 @@ public abstract class GameCanvas {
}
});
-
-
-
render();
}
+ public void setOnCellEntered(Consumer onCellEntered) {
+ canvas.setOnMouseMoved(event -> {
+ final int column = (int) ((event.getX() / this.width) * rowSize);
+ final int row = (int) ((event.getY() / this.height) * columnSize);
+
+ final Cell cell = cells[column + row * rowSize];
+
+ if (currentCell != cell && cell.isInside(event.getX(), event.getY())) {
+ event.consume();
+ currentCell = cell;
+ onCellEntered.accept(column + row * rowSize);
+ }
+ });
+ }
+
private void render() {
graphics.setFill(backgroundColor);
graphics.fillRect(0, 0, width, height);
diff --git a/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java b/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java
index c1b24f7..53d0b7d 100644
--- a/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java
+++ b/app/src/main/java/org/toop/app/canvas/ReversiCanvas.java
@@ -7,61 +7,38 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
public final class ReversiCanvas extends GameCanvas {
- private Move[] currentlyHighlightedMoves = null;
- public ReversiCanvas(Color color, int width, int height, Consumer onCellClicked, Consumer newCellEntered) {
- super(color, new Color(0f,0.4f,0.2f,1f), width, height, 8, 8, 5, true, onCellClicked, newCellEntered);
+ private Move[] currentlyHighlightedMoves = null;
+
+ public ReversiCanvas(Color color, int width, int height, Consumer onCellClicked) {
+ super(color, new Color(0f, 0.4f, 0.2f, 1f), width, height, 8, 8, 5, true, onCellClicked);
drawStartingDots();
-
- final AtomicReference| lastHoveredCell = new AtomicReference<>(null);
-
- canvas.setOnMouseMoved(event -> {
- double mouseX = event.getX();
- double mouseY = event.getY();
- int cellId = -1;
-
- Cell hovered = null;
- for (Cell cell : cells) {
- if (cell.isInside(mouseX, mouseY)) {
- hovered = cell;
- cellId = turnCoordsIntoCellId(mouseX, mouseY);
- break;
- }
- }
-
- Cell previous = lastHoveredCell.get();
-
- if (hovered != previous) {
- lastHoveredCell.set(hovered);
- newCellEntered.accept(cellId);
- }
- });
}
- public void setCurrentlyHighlightedMovesNull() {
- currentlyHighlightedMoves = null;
- }
+ public void setCurrentlyHighlightedMovesNull() {
+ currentlyHighlightedMoves = null;
+ }
- public void drawHighlightDots(Move[] moves){
- if (currentlyHighlightedMoves != null){
- for (final Move move : currentlyHighlightedMoves){
- Color color = move.value() == 'W'? Color.BLACK: Color.WHITE;
- drawInnerDot(color, move.position(), true);
- }
- }
- currentlyHighlightedMoves = moves;
- if (moves != null) {
- for (Move move : moves) {
- Color color = move.value() == 'B' ? Color.BLACK : Color.WHITE;
- drawInnerDot(color, move.position(), false);
- }
- }
- }
+ public void drawHighlightDots(Move[] moves) {
+ if (currentlyHighlightedMoves != null) {
+ for (final Move move : currentlyHighlightedMoves) {
+ Color color = move.value() == 'W' ? Color.BLACK : Color.WHITE;
+ drawInnerDot(color, move.position(), true);
+ }
+ }
+ currentlyHighlightedMoves = moves;
+ if (moves != null) {
+ for (Move move : moves) {
+ Color color = move.value() == 'B' ? Color.BLACK : Color.WHITE;
+ drawInnerDot(color, move.position(), false);
+ }
+ }
+ }
- private int turnCoordsIntoCellId(double x, double y) {
- final int column = (int) ((x / this.width) * rowSize);
- final int row = (int) ((y / this.height) * columnSize);
- return column + row * rowSize;
- }
+ private int turnCoordsIntoCellId(double x, double y) {
+ final int column = (int) ((x / this.width) * rowSize);
+ final int row = (int) ((y / this.height) * columnSize);
+ return column + row * rowSize;
+ }
public void drawStartingDots() {
drawDot(Color.BLACK, 28);
@@ -71,16 +48,14 @@ public final class ReversiCanvas extends GameCanvas {
}
public void drawLegalPosition(int cell, char player) {
+ Color innerColor;
- Color innerColor;
- if (player == 'B') {
- innerColor = new Color(0.0f, 0.0f, 0.0f, 0.6f);
- }
- else {
- innerColor = new Color(1.0f, 1.0f, 1.0f, 0.75f);
- }
- drawInnerDot(innerColor, cell,false);
- public void drawLegalPosition(Color color, int cell) {
- drawDot(new Color(color.getRed(), color.getGreen(), color.getBlue(), 0.25), cell);
+ if (player == 'B') {
+ innerColor = new Color(0.0f, 0.0f, 0.0f, 0.6f);
+ } else {
+ innerColor = new Color(1.0f, 1.0f, 1.0f, 0.75f);
+ }
+
+ drawInnerDot(innerColor, cell, false);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java b/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java
index 890eb39..d7ccbc8 100644
--- a/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java
+++ b/app/src/main/java/org/toop/app/canvas/TicTacToeCanvas.java
@@ -6,7 +6,7 @@ import java.util.function.Consumer;
public final class TicTacToeCanvas extends GameCanvas {
public TicTacToeCanvas(Color color, int width, int height, Consumer onCellClicked) {
- super(color, Color.TRANSPARENT, width, height, 3, 3, 30, false, onCellClicked,null);
+ super(color, Color.TRANSPARENT, width, height, 3, 3, 30, false, onCellClicked);
}
public void drawX(Color color, int cell) {
diff --git a/app/src/main/java/org/toop/app/game/BaseGameThread.java b/app/src/main/java/org/toop/app/game/BaseGameThread.java
index f9178da..11b9076 100644
--- a/app/src/main/java/org/toop/app/game/BaseGameThread.java
+++ b/app/src/main/java/org/toop/app/game/BaseGameThread.java
@@ -6,6 +6,7 @@ import org.toop.app.widget.view.GameView;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.networking.events.NetworkEvents;
import org.toop.game.Game;
+import org.toop.game.records.Move;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -18,7 +19,7 @@ public abstract class BaseGameThread {
protected final GameInformation information;
protected final int myTurn;
protected final Runnable onGameOver;
- protected final BlockingQueue moveQueue;
+ protected final BlockingQueue moveQueue;
protected final TGame game;
protected final TAI ai;
@@ -27,6 +28,7 @@ public abstract class BaseGameThread {
protected final TCanvas canvas;
protected final AtomicBoolean isRunning = new AtomicBoolean(true);
+ protected final AtomicBoolean isPaused = new AtomicBoolean(false);
protected BaseGameThread(
GameInformation information,
@@ -76,7 +78,7 @@ public abstract class BaseGameThread {
}
private void onCellClicked(int cell) {
- if (!isRunning.get()) return;
+ if (!isRunning.get() || isPaused.get()) return;
final int currentTurn = getCurrentTurn();
if (!information.players[currentTurn].isHuman) return;
@@ -84,8 +86,9 @@ public abstract class BaseGameThread {
final char value = getSymbolForTurn(currentTurn);
try {
- moveQueue.put(new Game.Move(cell, value));
- } catch (InterruptedException _) {}
+ moveQueue.put(new Move(cell, value));
+ } catch (InterruptedException _) {
+ }
}
protected void gameOver() {
@@ -110,10 +113,13 @@ public abstract class BaseGameThread {
protected abstract void addCanvasToPrimary();
protected abstract int getCurrentTurn();
+
protected abstract char getSymbolForTurn(int turn);
+
protected abstract String getNameForTurn(int turn);
protected abstract void onMoveResponse(NetworkEvents.GameMoveResponse response);
+
protected abstract void onYourTurnResponse(NetworkEvents.YourTurnResponse response);
protected abstract void localGameThread();
diff --git a/app/src/main/java/org/toop/app/game/Connect4Game.java b/app/src/main/java/org/toop/app/game/Connect4Game.java
deleted file mode 100644
index 76bd13e..0000000
--- a/app/src/main/java/org/toop/app/game/Connect4Game.java
+++ /dev/null
@@ -1,275 +0,0 @@
-package org.toop.app.game;
-
-import javafx.geometry.Pos;
-import javafx.scene.paint.Color;
-import org.toop.app.App;
-import org.toop.app.GameInformation;
-import org.toop.app.canvas.Connect4Canvas;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.views.GameView;
-import org.toop.app.view.views.LocalMultiplayerView;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.game.Connect4.Connect4;
-import org.toop.game.Connect4.Connect4AI;
-import org.toop.game.enumerators.GameState;
-import org.toop.game.records.Move;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-public class Connect4Game {
- private final GameInformation information;
-
- private final int myTurn;
- private Runnable onGameOver;
- private final BlockingQueue moveQueue;
-
- private final Connect4 game;
- private final Connect4AI ai;
- private final int columnSize = 7;
- private final int rowSize = 6;
-
- private final GameView view;
- private final Connect4Canvas canvas;
-
- private final AtomicBoolean isRunning;
-
- public Connect4Game(GameInformation information, int myTurn, Runnable onForfeit, Runnable onExit, Consumer onMessage, Runnable onGameOver) {
- this.information = information;
- this.myTurn = myTurn;
- this.onGameOver = onGameOver;
- moveQueue = new LinkedBlockingQueue();
-
-
- game = new Connect4();
- ai = new Connect4AI();
-
- isRunning = new AtomicBoolean(true);
-
- if (onForfeit == null || onExit == null) {
- view = new GameView(null, () -> {
- isRunning.set(false);
- ViewStack.push(new LocalMultiplayerView(information));
- }, null);
- } else {
- view = new GameView(onForfeit, () -> {
- isRunning.set(false);
- onExit.run();
- }, onMessage);
- }
-
- canvas = new Connect4Canvas(Color.GRAY,
- (App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3,
- (cell) -> {
- if (onForfeit == null || onExit == null) {
- if (information.players[game.getCurrentTurn()].isHuman) {
- final char value = game.getCurrentTurn() == 0? 'X' : 'O';
-
- try {
- moveQueue.put(new Move(cell%columnSize, value));
- } catch (InterruptedException _) {}
- }
- } else {
- if (information.players[0].isHuman) {
- final char value = myTurn == 0? 'X' : 'O';
-
- try {
- moveQueue.put(new Move(cell%columnSize, value));
- } catch (InterruptedException _) {}
- }
- }
- });
-
- view.add(Pos.CENTER, canvas.getCanvas());
- ViewStack.push(view);
-
- if (onForfeit == null || onExit == null) {
- new Thread(this::localGameThread).start();
- setGameLabels(information.players[0].isHuman);
- } else {
- new EventFlow()
- .listen(NetworkEvents.GameMoveResponse.class, this::onMoveResponse)
- .listen(NetworkEvents.YourTurnResponse.class, this::onYourTurnResponse)
- .listen(NetworkEvents.ReceivedMessage.class, this::onReceivedMessage);
-
- setGameLabels(myTurn == 0);
- }
- updateCanvas();
- }
-
- public Connect4Game(GameInformation information) {
- this(information, 0, null, null, null, null);
- }
- private void localGameThread() {
- while (isRunning.get()) {
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "RED" : "BLUE";
- final int nextTurn = (currentTurn + 1) % information.type.getPlayerCount();
-
- view.nextPlayer(information.players[currentTurn].isHuman,
- information.players[currentTurn].name,
- currentValue,
- information.players[nextTurn].name);
-
- Move move = null;
-
- if (information.players[currentTurn].isHuman) {
- try {
- final Move wants = moveQueue.take();
- final Move[] legalMoves = game.getLegalMoves();
-
- for (final Move legalMove : legalMoves) {
- if (legalMove.position() == wants.position() &&
- legalMove.value() == wants.value()) {
- move = wants;
- break;
- }
- }
- } catch (InterruptedException _) {}
- } else {
- final long start = System.currentTimeMillis();
-
- move = ai.findBestMove(game, information.players[currentTurn].computerDifficulty);
-
- if (information.players[currentTurn].computerThinkTime > 0) {
- final long elapsedTime = System.currentTimeMillis() - start;
- final long sleepTime = Math.abs(information.players[currentTurn].computerThinkTime * 1000L - elapsedTime);
-
- try {
- Thread.sleep((long)(sleepTime * Math.random()));
- } catch (InterruptedException _) {}
- }
- }
-
- if (move == null) {
- continue;
- }
-
- final GameState state = game.play(move);
- updateCanvas();
-/*
- if (move.value() == 'X') {
- canvas.drawX(Color.INDIANRED, move.position());
- } else if (move.value() == 'O') {
- canvas.drawO(Color.ROYALBLUE, move.position());
- }
-*/
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- view.gameOver(true, information.players[currentTurn].name);
- } else if (state == GameState.DRAW) {
- view.gameOver(false, "");
- }
-
- isRunning.set(false);
- }
- }
- }
-
- private void onMoveResponse(NetworkEvents.GameMoveResponse response) {
- if (!isRunning.get()) {
- return;
- }
-
- char playerChar;
-
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- playerChar = myTurn == 0? 'X' : 'O';
- } else {
- playerChar = myTurn == 0? 'O' : 'X';
- }
-
- final Move move = new Move(Integer.parseInt(response.move()), playerChar);
- final GameState state = game.play(move);
-
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- view.gameOver(true, information.players[0].name);
- gameOver();
- } else {
- view.gameOver(false, information.players[1].name);
- gameOver();
- }
- } else if (state == GameState.DRAW) {
- view.gameOver(false, "");
- gameOver();
- }
- }
-
- if (move.value() == 'X') {
- canvas.drawDot(Color.INDIANRED, move.position());
- } else if (move.value() == 'O') {
- canvas.drawDot(Color.ROYALBLUE, move.position());
- }
-
- updateCanvas();
- setGameLabels(game.getCurrentTurn() == myTurn);
- }
-
- private void gameOver() {
- if (onGameOver == null){
- return;
- }
- isRunning.set(false);
- onGameOver.run();
- }
-
- private void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
-
- if (!isRunning.get()) {
- return;
- }
-
- moveQueue.clear();
-
- int position = -1;
-
- if (information.players[0].isHuman) {
- try {
- position = moveQueue.take().position();
- } catch (InterruptedException _) {}
- } else {
- final Move move = ai.findBestMove(game, information.players[0].computerDifficulty);
-
- assert move != null;
- position = move.position();
- }
-
- new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short)position))
- .postEvent();
- }
-
- private void onReceivedMessage(NetworkEvents.ReceivedMessage msg) {
- if (!isRunning.get()) {
- return;
- }
-
- view.updateChat(msg.message());
- }
-
- private void updateCanvas() {
- canvas.clearAll();
-
- for (int i = 0; i < game.getBoard().length; i++) {
- if (game.getBoard()[i] == 'X') {
- canvas.drawDot(Color.RED, i);
- } else if (game.getBoard()[i] == 'O') {
- canvas.drawDot(Color.BLUE, i);
- }
- }
- }
-
- private void setGameLabels(boolean isMe) {
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "RED" : "BLUE";
-
- view.nextPlayer(isMe,
- information.players[isMe? 0 : 1].name,
- currentValue,
- information.players[isMe? 1 : 0].name);
- }
-}
diff --git a/app/src/main/java/org/toop/app/game/Connect4GameThread.java b/app/src/main/java/org/toop/app/game/Connect4GameThread.java
new file mode 100644
index 0000000..a0d4174
--- /dev/null
+++ b/app/src/main/java/org/toop/app/game/Connect4GameThread.java
@@ -0,0 +1,188 @@
+package org.toop.app.game;
+
+import javafx.geometry.Pos;
+import javafx.scene.paint.Color;
+import org.toop.app.App;
+import org.toop.app.GameInformation;
+import org.toop.app.canvas.Connect4Canvas;
+import org.toop.framework.eventbus.EventFlow;
+import org.toop.framework.networking.events.NetworkEvents;
+import org.toop.game.Connect4.Connect4;
+import org.toop.game.Connect4.Connect4AI;
+import org.toop.game.enumerators.GameState;
+import org.toop.game.records.Move;
+
+import java.util.function.Consumer;
+
+public final class Connect4GameThread extends BaseGameThread {
+ private static final int COLS = 7;
+
+ public Connect4GameThread(
+ GameInformation info,
+ int myTurn,
+ Runnable onForfeit,
+ Runnable onExit,
+ Consumer onMessage,
+ Runnable onGameOver
+ ) {
+ super(
+ info,
+ myTurn,
+ onForfeit,
+ onExit,
+ onMessage,
+ onGameOver,
+ Connect4::new,
+ Connect4AI::new,
+ clickHandler -> new Connect4Canvas(
+ Color.GRAY,
+ (App.getHeight() / 4) * 3,
+ (App.getHeight() / 4) * 3,
+ cell -> clickHandler.accept(cell % COLS)
+ )
+ );
+ }
+
+ public Connect4GameThread(GameInformation info) {
+ this(info, 0, null, null, null, null);
+ }
+
+ @Override
+ protected void addCanvasToPrimary() {
+ primary.add(Pos.CENTER, canvas.getCanvas());
+ }
+
+ @Override
+ protected int getCurrentTurn() {
+ return game.getCurrentTurn();
+ }
+
+ @Override
+ protected char getSymbolForTurn(int turn) {
+ return turn == 0 ? 'X' : 'O';
+ }
+
+ @Override
+ protected String getNameForTurn(int turn) {
+ return turn == 0 ? "RED" : "BLUE";
+ }
+
+ private void drawMove(Move move) {
+ if (move.value() == 'X')
+ canvas.drawDot(Color.RED, move.position());
+ else
+ canvas.drawDot(Color.BLUE, move.position());
+ }
+
+ @Override
+ protected void onMoveResponse(NetworkEvents.GameMoveResponse response) {
+ if (!isRunning.get()) return;
+
+ char symbol =
+ response.player().equalsIgnoreCase(information.players[0].name)
+ ? (myTurn == 0 ? 'X' : 'O')
+ : (myTurn == 0 ? 'O' : 'X');
+
+ final Move move = new Move(Integer.parseInt(response.move()), symbol);
+ final GameState state = game.play(move);
+
+ drawMove(move);
+ updateCanvas();
+
+ if (state != GameState.NORMAL) {
+ if (state == GameState.WIN) {
+ boolean p0 = response.player().equalsIgnoreCase(information.players[0].name);
+ primary.gameOver(p0, information.players[p0 ? 0 : 1].name);
+ gameOver();
+ } else if (state == GameState.DRAW) {
+ primary.gameOver(false, "");
+ gameOver();
+ }
+ }
+
+ setGameLabels(game.getCurrentTurn() == myTurn);
+ }
+
+ @Override
+ protected void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
+ if (!isRunning.get()) return;
+
+ moveQueue.clear();
+ int col = -1;
+
+ if (information.players[0].isHuman) {
+ try {
+ col = moveQueue.take().position();
+ } catch (InterruptedException _) {
+ }
+ } else {
+ final Move move = ai.findBestMove(game, information.players[0].computerDifficulty);
+ assert move != null;
+ col = move.position();
+ }
+
+ new EventFlow()
+ .addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short) col))
+ .postEvent();
+ }
+
+ @Override
+ protected void localGameThread() {
+ while (isRunning.get()) {
+ final int current = game.getCurrentTurn();
+ setGameLabels(current == myTurn);
+
+ Move move = null;
+
+ if (information.players[current].isHuman) {
+ try {
+ final Move wants = moveQueue.take();
+ for (final Move legal : game.getLegalMoves()) {
+ if (legal.position() == wants.position() &&
+ legal.value() == wants.value()) {
+ move = wants;
+ break;
+ }
+ }
+ } catch (InterruptedException _) {
+ }
+ } else {
+ final long start = System.currentTimeMillis();
+ move = ai.findBestMove(game, information.players[current].computerDifficulty);
+
+ if (information.players[current].computerThinkTime > 0) {
+ long elapsed = System.currentTimeMillis() - start;
+ long sleep = information.players[current].computerThinkTime * 1000L - elapsed;
+ try {
+ Thread.sleep((long) (sleep * Math.random()));
+ } catch (InterruptedException _) {
+ }
+ }
+ }
+
+ if (move == null) continue;
+
+ GameState state = game.play(move);
+ drawMove(move);
+ updateCanvas();
+
+ if (state != GameState.NORMAL) {
+ if (state == GameState.WIN)
+ primary.gameOver(information.players[current].isHuman, information.players[current].name);
+ else if (state == GameState.DRAW)
+ primary.gameOver(false, "");
+ isRunning.set(false);
+ }
+ }
+ }
+
+ private void updateCanvas() {
+ canvas.clearAll();
+
+ for (int i = 0; i < game.getBoard().length; i++) {
+ char c = game.getBoard()[i];
+ if (c == 'X') canvas.drawDot(Color.RED, i);
+ else if (c == 'O') canvas.drawDot(Color.BLUE, i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/game/ReversiGame.java b/app/src/main/java/org/toop/app/game/ReversiGame.java
deleted file mode 100644
index a65805e..0000000
--- a/app/src/main/java/org/toop/app/game/ReversiGame.java
+++ /dev/null
@@ -1,327 +0,0 @@
-package org.toop.app.game;
-
-import javafx.animation.SequentialTransition;
-import org.toop.app.App;
-import org.toop.app.GameInformation;
-import org.toop.app.canvas.ReversiCanvas;
-import org.toop.app.widget.WidgetContainer;
-import org.toop.app.widget.view.GameView;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.game.enumerators.GameState;
-import org.toop.game.records.Move;
-import org.toop.game.reversi.Reversi;
-import org.toop.game.reversi.ReversiAI;
-
-import javafx.geometry.Pos;
-import javafx.scene.paint.Color;
-
-import java.awt.*;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-public final class ReversiGame {
- private final GameInformation information;
-
- private final int myTurn;
- private final Runnable onGameOver;
- private final BlockingQueue moveQueue;
- private Runnable onGameOver;
- private final BlockingQueue moveQueue;
-
- private final Reversi game;
- private final ReversiAI ai;
-
- private final GameView primary;
- private final ReversiCanvas canvas;
-
- private final AtomicBoolean isRunning;
- private final AtomicBoolean isPaused;
-
- public ReversiGame(GameInformation information, int myTurn, Runnable onForfeit, Runnable onExit, Consumer onMessage, Runnable onGameOver) {
- this.information = information;
-
- this.myTurn = myTurn;
- this.onGameOver = onGameOver;
- moveQueue = new LinkedBlockingQueue<>();
-
- game = new Reversi();
- ai = new ReversiAI();
-
- isRunning = new AtomicBoolean(true);
- isPaused = new AtomicBoolean(false);
-
- if (onForfeit == null || onExit == null) {
- primary = new GameView(null, () -> {
- isRunning.set(false);
- WidgetContainer.getCurrentView().transitionPrevious();
- }, null);
- } else {
- primary = new GameView(onForfeit, () -> {
- isRunning.set(false);
- onExit.run();
- }, onMessage);
- }
-
- canvas = new ReversiCanvas(Color.BLACK,
- (App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3,
- (cell) -> {
- if (onForfeit == null || onExit == null) {
- if (information.players[game.getCurrentTurn()].isHuman) {
- final char value = game.getCurrentTurn() == 0? 'B' : 'W';
-
- try {
- moveQueue.put(new Move(cell, value));
- } catch (InterruptedException _) {}
- }
- } else {
- if (information.players[0].isHuman) {
- final char value = myTurn == 0? 'B' : 'W';
-
- try {
- moveQueue.put(new Move(cell, value));
- } catch (InterruptedException _) {}
- }
- }
- },this::highlightCells);
-
-
-
- primary.add(Pos.CENTER, canvas.getCanvas());
- WidgetContainer.getCurrentView().transitionNext(primary);
-
- if (onForfeit == null || onExit == null) {
- new Thread(this::localGameThread).start();
- setGameLabels(information.players[0].isHuman);
- } else {
- new EventFlow()
- .listen(NetworkEvents.GameMoveResponse.class, this::onMoveResponse)
- .listen(NetworkEvents.YourTurnResponse.class, this::onYourTurnResponse);
-
- setGameLabels(myTurn == 0);
- }
-
- updateCanvas(false);
- }
-
- public ReversiGame(GameInformation information) {
- this(information, 0, null, null, null,null);
- }
-
- private void localGameThread() {
- while (isRunning.get()) {
- if (isPaused.get()) {
- try {
- Thread.sleep(200);
- } catch (InterruptedException _) {}
-
- continue;
- }
-
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "BLACK" : "WHITE";
- final int nextTurn = (currentTurn + 1) % information.type.getPlayerCount();
-
- primary.nextPlayer(information.players[currentTurn].isHuman,
- information.players[currentTurn].name,
- currentValue,
- information.players[nextTurn].name);
-
- Move move = null;
-
- if (information.players[currentTurn].isHuman) {
- try {
- final Move wants = moveQueue.take();
- final Move[] legalMoves = game.getLegalMoves();
-
- for (final Move legalMove : legalMoves) {
- if (legalMove.position() == wants.position() &&
- legalMove.value() == wants.value()) {
- move = wants;
- break;
- }
- }
- } catch (InterruptedException _) {}
- } else {
- final long start = System.currentTimeMillis();
-
- move = ai.findBestMove(game, information.players[currentTurn].computerDifficulty);
-
- if (information.players[currentTurn].computerThinkTime > 0) {
- final long elapsedTime = System.currentTimeMillis() - start;
- final long sleepTime = information.players[currentTurn].computerThinkTime * 1000L - elapsedTime;
-
- try {
- Thread.sleep((long) (sleepTime * Math.random()));
- } catch (InterruptedException _) {}
- }
- }
-
- if (move == null) {
- continue;
- }
-
- canvas.setCurrentlyHighlightedMovesNull();
- final GameState state = game.play(move);
- updateCanvas(true);
-
- if (state != Game.State.NORMAL) {
- if (state == Game.State.WIN) {
- primary.gameOver(true, information.players[currentTurn].name);
- } else if (state == Game.State.DRAW) {
- primary.gameOver(false, "");
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- view.gameOver(true, information.players[currentTurn].name);
- } else if (state == GameState.DRAW) {
- view.gameOver(false, "");
- }
-
- isRunning.set(false);
- }
- }
- }
-
- private void onMoveResponse(NetworkEvents.GameMoveResponse response) {
- if (!isRunning.get()) {
- return;
- }
-
- char playerChar;
-
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- playerChar = myTurn == 0? 'B' : 'W';
- } else {
- playerChar = myTurn == 0? 'W' : 'B';
- }
-
- final Move move = new Move(Integer.parseInt(response.move()), playerChar);
- final GameState state = game.play(move);
-
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- primary.gameOver(true, information.players[0].name);
- gameOver();
- } else {
- primary.gameOver(false, information.players[1].name);
- gameOver();
- }
- } else if (state == GameState.DRAW) {
- view.gameOver(false, "");
- game.play(move);
- }
- }
-
- updateCanvas(false);
- setGameLabels(game.getCurrentTurn() == myTurn);
- }
-
- private void gameOver() {
- if (onGameOver == null){
- return;
- }
- isRunning.set(false);
- onGameOver.run();
- }
-
- private void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
- if (!isRunning.get()) {
- return;
- }
-
- moveQueue.clear();
-
- int position = -1;
-
- if (information.players[0].isHuman) {
- try {
- position = moveQueue.take().position();
- } catch (InterruptedException _) {}
- } else {
- final Move move = ai.findBestMove(game, information.players[0].computerDifficulty);
-
- assert move != null;
- position = move.position();
- }
-
- new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short) position))
- .postEvent();
- }
-
- private void updateCanvas(boolean animate) {
- // Todo: this is very inefficient. still very fast but if the grid is bigger it might cause issues. improve.
- canvas.clearAll();
-
- for (int i = 0; i < game.getBoard().length; i++) {
- if (game.getBoard()[i] == 'B') {
- canvas.drawDot(Color.BLACK, i);
- } else if (game.getBoard()[i] == 'W') {
- canvas.drawDot(Color.WHITE, i);
- }
- }
-
- final Move[] flipped = game.getMostRecentlyFlippedPieces();
-
- final SequentialTransition animation = new SequentialTransition();
- isPaused.set(true);
-
- final Color fromColor = game.getCurrentPlayer() == 'W'? Color.WHITE : Color.BLACK;
- final Color toColor = game.getCurrentPlayer() == 'W'? Color.BLACK : Color.WHITE;
-
- if (animate && flipped != null) {
- for (final Move flip : flipped) {
- canvas.clear(flip.position());
- canvas.drawDot(fromColor, flip.position());
- animation.getChildren().addFirst(canvas.flipDot(fromColor, toColor, flip.position()));
- }
- }
-
- animation.setOnFinished(_ -> {
- isPaused.set(false);
-
- final Move[] legalMoves = game.getLegalMoves();
-
- for (final Move legalMove : legalMoves) {
- canvas.drawLegalPosition(legalMove.position(), game.getCurrentPlayer());
- for (final Game.Move legalMove : legalMoves) {
- canvas.drawLegalPosition(fromColor, legalMove.position());
- }
- });
-
- animation.play();
- }
-
- private void setGameLabels(boolean isMe) {
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "BLACK" : "WHITE";
-
- primary.nextPlayer(isMe,
- information.players[isMe? 0 : 1].name,
- currentValue,
- information.players[isMe? 1 : 0].name);
- }
-
- private void highlightCells(int cellEntered) {
- Move[] legalMoves = game.getLegalMoves();
- boolean isLegalMove = false;
- for (Move move : legalMoves) {
- if (move.position() == cellEntered){
- isLegalMove = true;
- break;
- }
- }
-
- if (cellEntered >= 0){
- Move[] moves = null;
- if (isLegalMove) {
- moves = game.getFlipsForPotentialMove(
- new Point(cellEntered%game.getColumnSize(),cellEntered/game.getRowSize()),
- game.getCurrentPlayer());
- }
- canvas.drawHighlightDots(moves);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/game/ReversiGameThread.java b/app/src/main/java/org/toop/app/game/ReversiGameThread.java
new file mode 100644
index 0000000..05c1706
--- /dev/null
+++ b/app/src/main/java/org/toop/app/game/ReversiGameThread.java
@@ -0,0 +1,241 @@
+package org.toop.app.game;
+
+import javafx.animation.SequentialTransition;
+import javafx.geometry.Pos;
+import javafx.scene.paint.Color;
+import org.toop.app.App;
+import org.toop.app.GameInformation;
+import org.toop.app.canvas.ReversiCanvas;
+import org.toop.framework.eventbus.EventFlow;
+import org.toop.framework.networking.events.NetworkEvents;
+import org.toop.game.enumerators.GameState;
+import org.toop.game.records.Move;
+import org.toop.game.reversi.Reversi;
+import org.toop.game.reversi.ReversiAI;
+
+import java.awt.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
+public final class ReversiGameThread extends BaseGameThread {
+ public ReversiGameThread(GameInformation info, int myTurn,
+ Runnable onForfeit, Runnable onExit, Consumer onMessage, Runnable onGameOver) {
+ super(info, myTurn, onForfeit, onExit, onMessage, onGameOver,
+ Reversi::new,
+ ReversiAI::new,
+ clickHandler -> new ReversiCanvas(
+ Color.BLACK,
+ (App.getHeight() / 4) * 3,
+ (App.getHeight() / 4) * 3,
+ clickHandler
+ )
+ );
+
+ canvas.setOnCellEntered(this::highlightCells);
+ }
+
+ public ReversiGameThread(GameInformation info) {
+ this(info, 0, null, null, null, null);
+ }
+
+ @Override
+ protected void addCanvasToPrimary() {
+ primary.add(Pos.CENTER, canvas.getCanvas());
+ }
+
+ @Override
+ protected int getCurrentTurn() {
+ return game.getCurrentTurn();
+ }
+
+ @Override
+ protected char getSymbolForTurn(int turn) {
+ return turn == 0 ? 'B' : 'W';
+ }
+
+ @Override
+ protected String getNameForTurn(int turn) {
+ return turn == 0 ? "BLACK" : "WHITE";
+ }
+
+ private void drawMove(Move move) {
+ if (move.value() == 'B') canvas.drawDot(Color.BLACK, move.position());
+ else canvas.drawDot(Color.WHITE, move.position());
+ }
+
+ @Override
+ protected void onMoveResponse(NetworkEvents.GameMoveResponse response) {
+ if (!isRunning.get()) return;
+
+ char playerChar =
+ response.player().equalsIgnoreCase(information.players[0].name)
+ ? (myTurn == 0 ? 'B' : 'W')
+ : (myTurn == 0 ? 'W' : 'B');
+
+ final Move move = new Move(Integer.parseInt(response.move()), playerChar);
+ final GameState state = game.play(move);
+
+ updateCanvas(true);
+
+ if (state != GameState.NORMAL) {
+ if (state == GameState.WIN) {
+ boolean p0 = response.player().equalsIgnoreCase(information.players[0].name);
+ primary.gameOver(p0, information.players[p0 ? 0 : 1].name);
+ gameOver();
+ } else if (state == GameState.DRAW) {
+ primary.gameOver(false, "");
+ gameOver();
+ }
+ }
+
+ setGameLabels(game.getCurrentTurn() == myTurn);
+ }
+
+ @Override
+ protected void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
+ if (!isRunning.get()) return;
+
+ moveQueue.clear();
+ int position = -1;
+
+ if (information.players[0].isHuman) {
+ try {
+ position = moveQueue.take().position();
+ } catch (InterruptedException _) {
+ }
+ } else {
+ final Move move = ai.findBestMove(game, information.players[0].computerDifficulty);
+ assert move != null;
+ position = move.position();
+ }
+
+ new EventFlow()
+ .addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short) position))
+ .postEvent();
+ }
+
+ @Override
+ protected void localGameThread() {
+ while (isRunning.get()) {
+ if (isPaused.get()) {
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException _) {}
+
+ continue;
+ }
+
+ final int currentTurn = game.getCurrentTurn();
+ setGameLabels(currentTurn == myTurn);
+
+ Move move = null;
+
+ if (information.players[currentTurn].isHuman) {
+ try {
+ final Move wants = moveQueue.take();
+ final Move[] legalMoves = game.getLegalMoves();
+
+ for (final Move legalMove : legalMoves) {
+ if (legalMove.position() == wants.position() &&
+ legalMove.value() == wants.value()) {
+ move = wants;
+ break;
+ }
+ }
+ } catch (InterruptedException _) {
+ }
+
+ } else {
+ long start = System.currentTimeMillis();
+ move = ai.findBestMove(game, information.players[currentTurn].computerDifficulty);
+
+ if (information.players[currentTurn].computerThinkTime > 0) {
+ long elapsed = System.currentTimeMillis() - start;
+ long sleep = information.players[currentTurn].computerThinkTime * 1000L - elapsed;
+
+ try {
+ Thread.sleep((long) (sleep * Math.random()));
+ } catch (InterruptedException _) {
+ }
+ }
+ }
+
+ if (move == null) continue;
+
+ GameState state = game.play(move);
+ updateCanvas(true);
+
+ if (state != GameState.NORMAL) {
+ if (state == GameState.WIN) {
+ primary.gameOver(information.players[currentTurn].isHuman,
+ information.players[currentTurn].name);
+ } else if (state == GameState.DRAW) {
+ primary.gameOver(false, "");
+ }
+
+ isRunning.set(false);
+ }
+ }
+ }
+
+ private void updateCanvas(boolean animate) {
+ canvas.clearAll();
+
+ for (int i = 0; i < game.getBoard().length; i++) {
+ char c = game.getBoard()[i];
+ if (c == 'B') canvas.drawDot(Color.BLACK, i);
+ else if (c == 'W') canvas.drawDot(Color.WHITE, i);
+ }
+
+ final Move[] flipped = game.getMostRecentlyFlippedPieces();
+
+ final SequentialTransition anim = new SequentialTransition();
+ isPaused.set(true);
+
+ final Color from = game.getCurrentPlayer() == 'W' ? Color.WHITE : Color.BLACK;
+ final Color to = game.getCurrentPlayer() == 'W' ? Color.BLACK : Color.WHITE;
+
+ if (animate && flipped != null) {
+ for (final Move flip : flipped) {
+ canvas.clear(flip.position());
+ canvas.drawDot(from, flip.position());
+ anim.getChildren().addFirst(canvas.flipDot(from, to, flip.position()));
+ }
+ }
+
+ anim.setOnFinished(_ -> {
+ isPaused.set(false);
+
+ for (final Move m : game.getLegalMoves()) {
+ canvas.drawLegalPosition(m.position(), game.getCurrentPlayer());
+ }
+ });
+
+ anim.play();
+ }
+
+ private void highlightCells(int cell) {
+ Move[] legal = game.getLegalMoves();
+ boolean isLegal = false;
+
+ for (Move m : legal) {
+ if (m.position() == cell) {
+ isLegal = true;
+ break;
+ }
+ }
+
+ if (cell >= 0) {
+ Move[] flips = null;
+
+ if (isLegal) {
+ flips = game.getFlipsForPotentialMove(
+ new Point(cell % game.getColumnSize(), cell / game.getRowSize()),
+ game.getCurrentPlayer()
+ );
+ }
+
+ canvas.drawHighlightDots(flips);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/game/TicTacToeGame.java b/app/src/main/java/org/toop/app/game/TicTacToeGame.java
deleted file mode 100644
index 84fc237..0000000
--- a/app/src/main/java/org/toop/app/game/TicTacToeGame.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package org.toop.app.game;
-
-import org.toop.app.App;
-import org.toop.app.GameInformation;
-import org.toop.app.canvas.TicTacToeCanvas;
-import org.toop.app.widget.WidgetContainer;
-import org.toop.app.widget.view.GameView;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.game.enumerators.GameState;
-import org.toop.game.records.Move;
-import org.toop.game.tictactoe.TicTacToe;
-import org.toop.game.tictactoe.TicTacToeAI;
-
-import javafx.geometry.Pos;
-import javafx.scene.paint.Color;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-public final class TicTacToeGame {
- private final GameInformation information;
-
- private final int myTurn;
- private Runnable onGameOver;
- private final BlockingQueue moveQueue;
-
- private final TicTacToe game;
- private final TicTacToeAI ai;
-
- private final GameView primary;
- private final TicTacToeCanvas canvas;
-
- private final AtomicBoolean isRunning;
-
- public TicTacToeGame(GameInformation information, int myTurn, Runnable onForfeit, Runnable onExit, Consumer onMessage, Runnable onGameOver) {
- this.information = information;
-
- this.myTurn = myTurn;
- this.onGameOver = onGameOver;
- moveQueue = new LinkedBlockingQueue();
-
- game = new TicTacToe();
- ai = new TicTacToeAI();
-
- isRunning = new AtomicBoolean(true);
-
- if (onForfeit == null || onExit == null) {
- primary = new GameView(null, () -> {
- isRunning.set(false);
- WidgetContainer.getCurrentView().transitionPrevious();
- }, null);
- } else {
- primary = new GameView(onForfeit, () -> {
- isRunning.set(false);
- onExit.run();
- }, onMessage);
- }
-
- canvas = new TicTacToeCanvas(Color.GRAY,
- (App.getHeight() / 4) * 3, (App.getHeight() / 4) * 3,
- (cell) -> {
- if (onForfeit == null || onExit == null) {
- if (information.players[game.getCurrentTurn()].isHuman) {
- final char value = game.getCurrentTurn() == 0? 'X' : 'O';
-
- try {
- moveQueue.put(new Move(cell, value));
- } catch (InterruptedException _) {}
- }
- } else {
- if (information.players[0].isHuman) {
- final char value = myTurn == 0? 'X' : 'O';
-
- try {
- moveQueue.put(new Move(cell, value));
- } catch (InterruptedException _) {}
- }
- }
- });
-
- primary.add(Pos.CENTER, canvas.getCanvas());
- WidgetContainer.getCurrentView().transitionNext(primary);
-
- if (onForfeit == null || onExit == null) {
- new Thread(this::localGameThread).start();
- } else {
- new EventFlow()
- .listen(NetworkEvents.GameMoveResponse.class, this::onMoveResponse)
- .listen(NetworkEvents.YourTurnResponse.class, this::onYourTurnResponse);
-
- setGameLabels(myTurn == 0);
- }
- }
-
- public TicTacToeGame(GameInformation information) {
- this(information, 0, null, null, null, null);
- }
-
- private void localGameThread() {
- while (isRunning.get()) {
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "X" : "O";
- final int nextTurn = (currentTurn + 1) % information.type.getPlayerCount();
-
- primary.nextPlayer(information.players[currentTurn].isHuman,
- information.players[currentTurn].name,
- currentValue,
- information.players[nextTurn].name);
-
- Move move = null;
-
- if (information.players[currentTurn].isHuman) {
- try {
- final Move wants = moveQueue.take();
- final Move[] legalMoves = game.getLegalMoves();
-
- for (final Move legalMove : legalMoves) {
- if (legalMove.position() == wants.position() &&
- legalMove.value() == wants.value()) {
- move = wants;
- break;
- }
- }
- } catch (InterruptedException _) {}
- } else {
- final long start = System.currentTimeMillis();
-
- move = ai.findBestMove(game, information.players[currentTurn].computerDifficulty);
-
- if (information.players[currentTurn].computerThinkTime > 0) {
- final long elapsedTime = System.currentTimeMillis() - start;
- final long sleepTime = information.players[currentTurn].computerThinkTime * 1000L - elapsedTime;
-
- try {
- Thread.sleep((long)(sleepTime * Math.random()));
- } catch (InterruptedException _) {}
- }
- }
-
- if (move == null) {
- continue;
- }
-
- final GameState state = game.play(move);
-
- if (move.value() == 'X') {
- canvas.drawX(Color.INDIANRED, move.position());
- } else if (move.value() == 'O') {
- canvas.drawO(Color.ROYALBLUE, move.position());
- }
-
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- primary.gameOver(true, information.players[currentTurn].name);
- } else if (state == GameState.DRAW) {
- primary.gameOver(false, "");
- }
-
- isRunning.set(false);
- }
- }
- }
-
- private void onMoveResponse(NetworkEvents.GameMoveResponse response) {
- if (!isRunning.get()) {
- return;
- }
-
- char playerChar;
-
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- playerChar = myTurn == 0? 'X' : 'O';
- } else {
- playerChar = myTurn == 0? 'O' : 'X';
- }
-
- final Move move = new Move(Integer.parseInt(response.move()), playerChar);
- final GameState state = game.play(move);
-
- if (state != GameState.NORMAL) {
- if (state == GameState.WIN) {
- if (response.player().equalsIgnoreCase(information.players[0].name)) {
- primary.gameOver(true, information.players[0].name);
- gameOver();
- } else {
- primary.gameOver(false, information.players[1].name);
- gameOver();
- }
- } else if (state == GameState.DRAW) {
- if(game.getLegalMoves().length == 0) { //only return draw in online multiplayer if the game is actually over.
- primary.gameOver(false, "");
- gameOver();
- }
- }
- }
-
- if (move.value() == 'X') {
- canvas.drawX(Color.RED, move.position());
- } else if (move.value() == 'O') {
- canvas.drawO(Color.BLUE, move.position());
- }
-
- setGameLabels(game.getCurrentTurn() == myTurn);
- }
-
- private void gameOver() {
- if (onGameOver == null){
- return;
- }
- isRunning.set(false);
- onGameOver.run();
- }
-
- private void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
- if (!isRunning.get()) {
- return;
- }
-
- moveQueue.clear();
-
- int position = -1;
-
- if (information.players[0].isHuman) {
- try {
- position = moveQueue.take().position();
- } catch (InterruptedException _) {}
- } else {
- final Move move;
- move = ai.findBestMove(game, information.players[0].computerDifficulty);
- assert move != null;
- position = move.position();
- }
-
- new EventFlow().addPostEvent(new NetworkEvents.SendMove(response.clientId(), (short)position))
- .postEvent();
- }
-
- private void setGameLabels(boolean isMe) {
- final int currentTurn = game.getCurrentTurn();
- final String currentValue = currentTurn == 0? "X" : "O";
-
- primary.nextPlayer(isMe,
- information.players[isMe? 0 : 1].name,
- currentValue,
- information.players[isMe? 1 : 0].name);
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/game/TicTacToeGameThread.java b/app/src/main/java/org/toop/app/game/TicTacToeGameThread.java
index a71bf07..cf0db79 100644
--- a/app/src/main/java/org/toop/app/game/TicTacToeGameThread.java
+++ b/app/src/main/java/org/toop/app/game/TicTacToeGameThread.java
@@ -1,19 +1,19 @@
package org.toop.app.game;
+import javafx.geometry.Pos;
+import javafx.scene.paint.Color;
import org.toop.app.App;
import org.toop.app.GameInformation;
import org.toop.app.canvas.TicTacToeCanvas;
import org.toop.framework.eventbus.EventFlow;
import org.toop.framework.networking.events.NetworkEvents;
-import org.toop.game.Game;
+import org.toop.game.enumerators.GameState;
+import org.toop.game.records.Move;
import org.toop.game.tictactoe.TicTacToe;
import org.toop.game.tictactoe.TicTacToeAI;
import java.util.function.Consumer;
-import javafx.geometry.Pos;
-import javafx.scene.paint.Color;
-
public final class TicTacToeGameThread extends BaseGameThread {
public TicTacToeGameThread(GameInformation info, int myTurn, Runnable onForfeit, Runnable onExit, Consumer onMessage, Runnable onGameOver) {
super(info, myTurn, onForfeit, onExit, onMessage, onGameOver,
@@ -47,7 +47,7 @@ public final class TicTacToeGameThread extends BaseGameThread nodeMap;
-
- protected View(boolean mainView, String cssClass) {
- this.mainView = mainView;
-
- view = new StackPane();
- view.getStyleClass().add(cssClass);
-
- nodeMap = new HashMap();
- }
-
- public void add(Pos position, Node node) {
- assert node != null;
-
- StackPane.setAlignment(node, position);
- view.getChildren().add(node);
- }
-
- protected Region hspacer() {
- final Region hspacer = new Region();
- hspacer.getStyleClass().add("hspacer");
-
- return hspacer;
- }
-
- protected Region vspacer() {
- final Region vspacer = new Region();
- vspacer.getStyleClass().add("vspacer");
-
- return vspacer;
- }
-
- protected ScrollPane fit(String identifier, String cssClass, Node node) {
- assert node != null;
-
- final ScrollPane fit = new ScrollPane(node);
- fit.getStyleClass().add(cssClass);
-
- fit.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
- fit.setFitToWidth(true);
- fit.setFitToHeight(true);
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, fit);
- }
-
- return fit;
- }
-
- protected ScrollPane fit(String identifier, Node node) {
- return fit(identifier, "fit", node);
- }
-
- protected ScrollPane fit(Node node) {
- return fit("", node);
- }
-
- protected HBox hbox(String identifier, String cssClass, Node... nodes) {
- assert !nodeMap.containsKey(identifier);
-
- final HBox hbox = new HBox();
- hbox.getStyleClass().add(cssClass);
- hbox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
-
- for (final Node node : nodes) {
- if (node != null) {
- hbox.getChildren().add(node);
- }
- }
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, hbox);
- }
-
- return hbox;
- }
-
- protected HBox hbox(String identifier, Node... nodes) {
- return hbox(identifier, "container", nodes);
- }
-
- protected HBox hbox(Node... nodes) {
- return hbox("", nodes);
- }
-
- protected HBox hboxFill(String identifier, String cssClass, Node... nodes) {
- final HBox hbox = hbox(identifier, cssClass, nodes);
-
- for (final Node node : hbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxHeight(Double.MAX_VALUE);
- }
- }
-
- return hbox;
- }
-
- protected HBox hboxFill(String identifier, Node... nodes) {
- final HBox hbox = hbox(identifier, nodes);
-
- for (final Node node : hbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxHeight(Double.MAX_VALUE);
- }
- }
-
- return hbox;
- }
-
- protected HBox hboxFill(Node... nodes) {
- final HBox hbox = hbox(nodes);
-
- for (final Node node : hbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxHeight(Double.MAX_VALUE);
- }
- }
-
- return hbox;
- }
-
- protected VBox vbox(String identifier, String cssClass, Node... nodes) {
- assert !nodeMap.containsKey(identifier);
-
- final VBox vbox = new VBox();
- vbox.getStyleClass().add(cssClass);
- vbox.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
-
- for (final Node node : nodes) {
- if (node != null) {
- vbox.getChildren().add(node);
- }
- }
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, vbox);
- }
-
- return vbox;
- }
-
- protected VBox vbox(String identifier, Node... nodes) {
- return vbox(identifier, "container", nodes);
- }
-
- protected VBox vbox(Node... nodes) {
- return vbox("", nodes);
- }
-
- protected VBox vboxFill(String identifier, String cssClass, Node... nodes) {
- final VBox vbox = vbox(identifier, cssClass, nodes);
-
- for (final Node node : vbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxWidth(Double.MAX_VALUE);
- }
- }
-
- return vbox;
- }
-
- protected VBox vboxFill(String identifier, Node... nodes) {
- final VBox vbox = vbox(identifier, nodes);
-
- for (final Node node : vbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxWidth(Double.MAX_VALUE);
- }
- }
-
- return vbox;
- }
-
- protected VBox vboxFill(Node... nodes) {
- final VBox vbox = vbox(nodes);
-
- for (final Node node : vbox.getChildren()) {
- if (node instanceof Region) {
- ((Region)node).setMaxWidth(Double.MAX_VALUE);
- }
- }
-
- return vbox;
- }
-
- protected Separator separator(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final Separator separator = new Separator();
- separator.getStyleClass().add(cssClass);
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, separator);
- }
-
- return separator;
- }
-
- protected Separator separator(String identifier) {
- return separator(identifier, "separator");
- }
-
- protected Separator separator() {
- return separator("");
- }
-
- protected Text header(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final Text header = new Text();
- header.getStyleClass().add(cssClass);
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, header);
- }
-
- return header;
- }
-
- protected Text header(String identifier) {
- return header(identifier, "header");
- }
-
- protected Text header() {
- return header("");
- }
-
- protected Text text(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final Text text = new Text();
- text.getStyleClass().add(cssClass);
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, text);
- }
-
- return text;
- }
-
- protected Text text(String identifier) {
- return text(identifier, "text");
- }
-
- protected Text text() {
- return text("");
- }
-
- protected Button button(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final Button button = new Button();
- button.getStyleClass().add(cssClass);
-
- button.setOnMouseClicked(_ -> {
- new EventFlow().addPostEvent(new AudioEvents.ClickButton()).asyncPostEvent();
- });
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, button);
- }
-
- return button;
- }
-
- protected Button button(String identifier) {
- return button(identifier, "button");
- }
-
- protected Button button() {
- return button("");
- }
-
- protected Slider slider(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final Slider slider = new Slider();
- slider.getStyleClass().add(cssClass);
-
- slider.setMinorTickCount(0);
- slider.setMajorTickUnit(1);
- slider.setBlockIncrement(1);
-
- slider.setSnapToTicks(true);
- slider.setShowTickLabels(true);
-
- slider.setOnMouseClicked(_ -> {
- new EventFlow().addPostEvent(new AudioEvents.ClickButton()).asyncPostEvent();
- });
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, slider);
- }
-
- return slider;
- }
-
- protected Slider slider(String identifier) {
- return slider(identifier, "slider");
- }
-
- protected Slider slider() {
- return slider("");
- }
-
- protected TextField input(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final TextField input = new TextField();
- input.getStyleClass().add(cssClass);
-
- input.setOnMouseClicked(_ -> {
- new EventFlow().addPostEvent(new AudioEvents.ClickButton()).asyncPostEvent();
- });
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, input);
- }
-
- return input;
- }
-
- protected TextField input(String identifier) {
- return input(identifier, "input");
- }
-
- protected TextField input() {
- return input("");
- }
-
- protected ComboBox combobox(String identifier, String cssClass) {
- assert !nodeMap.containsKey(identifier);
-
- final ComboBox combobox = new ComboBox();
- combobox.getStyleClass().add(cssClass);
-
- combobox.setOnMouseClicked(_ -> {
- new EventFlow().addPostEvent(new AudioEvents.ClickButton()).asyncPostEvent();
- });
-
- if (!identifier.isEmpty()) {
- nodeMap.put(identifier, combobox);
- }
-
- return combobox;
- }
-
- protected ComboBox combobox(String identifier) {
- return combobox(identifier, "combo-box");
- }
-
- protected ComboBox combobox() {
- return combobox("");
- }
-
- @SuppressWarnings("unchecked")
- protected T get(String identifier) {
- assert nodeMap.containsKey(identifier);
- return (T) nodeMap.get(identifier);
- }
-
- protected void clear() {
- view.getChildren().clear();
- nodeMap.clear();
- }
-
- public boolean isMainView() { return mainView; }
- public Region getView() { return view; }
-
- public abstract void setup();
- public void cleanup() {
- clear();
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/ViewStack.java b/app/src/main/java/org/toop/app/view/ViewStack.java
deleted file mode 100644
index 20d0ff3..0000000
--- a/app/src/main/java/org/toop/app/view/ViewStack.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.toop.app.view;
-
-import javafx.application.Platform;
-import javafx.scene.Scene;
-import javafx.scene.layout.StackPane;
-
-import java.util.Stack;
-
-public final class ViewStack {
- private static boolean setup = false;
-
- private static StackPane root;
-
- private static View active;
- private static Stack stack;
-
- public static void setup(Scene scene) {
- assert scene != null;
-
- if (setup) {
- return;
- }
-
- root = new StackPane();
-
- active = null;
- stack = new Stack();
-
- scene.setRoot(root);
-
- setup = true;
- }
-
- public static void cleanup() {
- assert setup;
-
- final var count = stack.size();
-
- for (int i = 0; i < count; i++) {
- pop();
- }
-
- if (active != null) {
- active.cleanup();
- }
-
- setup = false;
- }
-
- public static void reload() {
- assert setup;
-
- for (final var view : stack) {
- view.cleanup();
- }
-
- if (active != null) {
- active.cleanup();
- active.setup();
- }
-
- for (final var view : stack) {
- view.setup();
- }
- }
-
- public static void push(View view) {
- assert setup;
- assert view != null;
-
- if (view.isMainView()) {
- Platform.runLater(() -> {
- if (active != null) {
- root.getChildren().removeFirst();
- active.cleanup();
- }
-
- root.getChildren().addFirst(view.getView());
- view.setup();
-
- active = view;
- });
- } else {
- Platform.runLater(() -> {
- stack.push(view);
- root.getChildren().addLast(view.getView());
- view.setup();
- });
- }
- }
-
- public static void pop() {
- assert setup;
-
- if (stack.isEmpty()) {
- return;
- }
-
- Platform.runLater(() -> {
- final var last = stack.pop();
- root.getChildren().removeLast();
- last.cleanup();
- });
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/displays/SongDisplay.java b/app/src/main/java/org/toop/app/view/displays/SongDisplay.java
deleted file mode 100644
index f21e2aa..0000000
--- a/app/src/main/java/org/toop/app/view/displays/SongDisplay.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package org.toop.app.view.displays;
-
-import javafx.application.Platform;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.ProgressBar;
-import javafx.scene.layout.HBox;
-import javafx.scene.layout.VBox;
-import javafx.scene.paint.Color;
-import org.toop.app.widget.Widget;
-import org.toop.framework.audio.AudioEventListener;
-import org.toop.framework.audio.events.AudioEvents;
-import org.toop.framework.eventbus.EventFlow;
-import javafx.geometry.Pos;
-import javafx.scene.text.Text;
-import org.toop.framework.eventbus.GlobalEventBus;
-
-public class SongDisplay extends VBox implements Widget {
-
- private final Text songTitle;
- private final ProgressBar progressBar;
- private final Text progressText;
- private boolean paused = false;
-
- public SongDisplay() {
- new EventFlow()
- .listen(this::updateTheSong);
-
- setAlignment(Pos.CENTER);
- getStyleClass().add("song-display");
-
- songTitle = new Text("song playing");
- songTitle.getStyleClass().add("song-title");
-
- progressBar = new ProgressBar(0);
- progressBar.getStyleClass().add("progress-bar");
-
- progressText = new Text("0:00/0:00");
- progressText.getStyleClass().add("progress-text");
-
- Button skipButton = new Button(">>");
- Button pauseButton = new Button("⏸");
- Button previousButton = new Button("<<");
-
- skipButton.getStyleClass().setAll("skip-button");
- pauseButton.getStyleClass().setAll("pause-button");
- previousButton.getStyleClass().setAll("previous-button");
-
- skipButton.setOnAction( event -> {
- GlobalEventBus.post(new AudioEvents.SkipMusic());
- paused = false;
- pauseButton.setText(getPlayString(paused));
- });
-
- pauseButton.setOnAction(event -> {
- GlobalEventBus.post(new AudioEvents.PauseMusic());
- paused = !paused;
- pauseButton.setText(getPlayString(paused));
- });
-
- previousButton.setOnAction( event -> {
- GlobalEventBus.post(new AudioEvents.PreviousMusic());
- paused = false;
- pauseButton.setText(getPlayString(paused));
- });
-
- HBox control = new HBox(10, previousButton, pauseButton, skipButton);
- control.setAlignment(Pos.CENTER);
- control.getStyleClass().add("controls");
-
- getChildren().addAll(songTitle, progressBar, progressText, control);
- }
-
- private void updateTheSong(AudioEvents.PlayingMusic event) {
- Platform.runLater(() -> {
- String text = event.name();
- text = text.substring(0, text.length() - 4);
- songTitle.setText(text);
- double currentPos = event.currentPosition();
- double duration = event.duration();
- if (currentPos / duration > 0.05) {
- double progress = currentPos / duration;
- progressBar.setProgress(progress);
- }
- else if (currentPos / duration < 0.05) {
- progressBar.setProgress(0.05);
- }
- progressText.setText(getTimeString(event.currentPosition(), event.duration()));
- });
- }
-
- private String getTimeString(long position, long duration) {
- long positionMinutes = position / 60;
- long durationMinutes = duration / 60;
- long positionSeconds = position % 60;
- long durationSeconds = duration % 60;
- String positionSecondsStr = String.valueOf(positionSeconds);
- String durationSecondsStr = String.valueOf(durationSeconds);
-
- if (positionSeconds < 10) {
- positionSecondsStr = "0" + positionSeconds;
- }
- if (durationSeconds < 10) {
- durationSecondsStr = "0" + durationSeconds;
- }
-
- String time = positionMinutes + ":" + positionSecondsStr + " / " + durationMinutes + ":" + durationSecondsStr;
- return time;
- }
-
- private String getPlayString(boolean paused) {
- if (paused) {
- return "▶";
- }
- else {
- return "⏸";
- }
- }
-
- @Override
- public Node getNode() {
- return this;
- }
-}
-
-
-
-
-
diff --git a/app/src/main/java/org/toop/app/view/views/ChallengeView.java b/app/src/main/java/org/toop/app/view/views/ChallengeView.java
deleted file mode 100644
index 36184f6..0000000
--- a/app/src/main/java/org/toop/app/view/views/ChallengeView.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.GameInformation;
-import org.toop.app.Server;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.Slider;
-import javafx.scene.text.Text;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public final class ChallengeView extends View {
- private final GameInformation.Player playerInformation;
-
- private final String challenger;
- private final String game;
-
- private final Consumer onAccept;
-
- public ChallengeView(String challenger, String game, Consumer onAccept) {
- super(false, "bg-popup");
-
- playerInformation = new GameInformation.Player();
-
- this.challenger = challenger;
- this.game = game;
-
- this.onAccept = onAccept;
- }
-
- @Override
- public void setup() {
- final Text challengeText = text();
- challengeText.setText(AppContext.getString("you-were-challenged-by"));
-
- final Text challengerHeader = header();
- challengerHeader.setText(challenger);
-
- final Text gameText = text();
- gameText.setText(AppContext.getString("to-a-game-of") + " " + game);
-
- final Button acceptButton = button();
- acceptButton.setText(AppContext.getString("accept"));
- acceptButton.setOnAction(_ -> {
- onAccept.accept(playerInformation);
- });
-
- final Button denyButton = button();
- denyButton.setText(AppContext.getString("deny"));
- denyButton.setOnAction(_ -> {
- ViewStack.pop();
- });
-
- final List nodes = new ArrayList<>();
-
- if (playerInformation.isHuman) {
- final Button playerToggle = button();
- playerToggle.setText(AppContext.getString("player"));
- playerToggle.setOnAction(_ -> {
- playerInformation.isHuman = false;
- cleanup();
- setup();
- });
-
- nodes.add(vbox(playerToggle));
- } else {
- final Button computerToggle = button();
- computerToggle.setText(AppContext.getString("computer"));
- computerToggle.setOnAction(_ -> {
- playerInformation.isHuman = true;
- cleanup();
- setup();
- });
-
- nodes.add(vbox(computerToggle));
-
- final Text computerDifficultyText = text();
- computerDifficultyText.setText(AppContext.getString("computer-difficulty"));
-
- final Slider computerDifficultySlider = slider();
- computerDifficultySlider.setMin(0);
- computerDifficultySlider.setMax(Server.gameToType(game).getMaxDepth());
- computerDifficultySlider.setValue(playerInformation.computerDifficulty);
- computerDifficultySlider.valueProperty().addListener((_, _, newValue) -> {
- playerInformation.computerDifficulty = newValue.intValue();
- });
-
- nodes.add(vbox(computerDifficultyText, computerDifficultySlider));
- }
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.CENTER,
- fit(hboxFill(
- vboxFill(
- challengeText,
- challengerHeader,
- gameText,
- separator(),
-
- hboxFill(
- acceptButton,
- denyButton
- )
- ),
-
- vboxFill(
- nodes.toArray(new Node[0])
- )
- ))
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/CreditsView.java b/app/src/main/java/org/toop/app/view/views/CreditsView.java
deleted file mode 100644
index 3f02ef8..0000000
--- a/app/src/main/java/org/toop/app/view/views/CreditsView.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.App;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.animation.KeyFrame;
-import javafx.animation.KeyValue;
-import javafx.animation.Timeline;
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.ScrollPane;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.Text;
-import javafx.util.Duration;
-
-public final class CreditsView extends View {
- public CreditsView() {
- super(false, "bg-primary");
- }
-
- @Override
- public void setup() {
- final Text scrumMasterHeader = header();
- scrumMasterHeader.setText(AppContext.getString("scrum-master") + ": Stef");
-
- final Text productOwnerHeader = header();
- productOwnerHeader.setText(AppContext.getString("product-owner") + ": Omar");
-
- final Text mergeCommanderHeader = header();
- mergeCommanderHeader.setText(AppContext.getString("merge-commander") + ": Bas");
-
- final Text localizationHeader = header();
- localizationHeader.setText(AppContext.getString("localization") + ": Ticho");
-
- final Text aiHeader = header();
- aiHeader.setText(AppContext.getString("ai") + ": Michiel");
-
- final Text developersHeader = header();
- developersHeader.setText(AppContext.getString("developers") + ": Michiel, Bas, Stef, Omar, Ticho");
-
- final Text moralSupportHeader = header();
- moralSupportHeader.setText(AppContext.getString("moral-support") + ": Wesley");
-
- final Text openglHeader = header();
- openglHeader.setText(AppContext.getString("opengl") + ": Omar");
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.CENTER,
- fit("credits-fit", vboxFill("credits-container", "credits-container",
- vbox("credits-spacer-top", ""),
-
- scrumMasterHeader,
- productOwnerHeader,
- mergeCommanderHeader,
- localizationHeader,
- aiHeader,
- developersHeader,
- moralSupportHeader,
- openglHeader,
-
- vbox("credits-spacer-bottom", "")
- ))
- );
-
- final Button backButton = button();
- backButton.setText(AppContext.getString("back"));
- backButton.setOnAction(_ -> { ViewStack.pop(); });
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- backButton
- )
- );
-
- playCredits(100, 20);
- }
-
- private void playCredits(int lineHeight, int length) {
- final ScrollPane creditsFit = get("credits-fit");
- creditsFit.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
- creditsFit.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
-
- final VBox creditsContainer = get("credits-container");
- creditsContainer.setSpacing(lineHeight);
-
- final VBox creditsSpacerTop = get("credits-spacer-top");
- creditsSpacerTop.setMinHeight(App.getHeight() - lineHeight);
-
- final VBox creditsSpacerBottom = get("credits-spacer-bottom");
- creditsSpacerBottom.setMinHeight(App.getHeight() - lineHeight);
-
- final Timeline timeline = new Timeline(
- new KeyFrame(Duration.seconds(0), new KeyValue(creditsFit.vvalueProperty(), 0.0)),
- new KeyFrame(Duration.seconds(length), new KeyValue(creditsFit.vvalueProperty(), 1.0))
- );
-
- timeline.setCycleCount(Timeline.INDEFINITE);
- timeline.play();
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/ErrorView.java b/app/src/main/java/org/toop/app/view/views/ErrorView.java
deleted file mode 100644
index 5dc85fa..0000000
--- a/app/src/main/java/org/toop/app/view/views/ErrorView.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.text.Text;
-
-public final class ErrorView extends View {
- private final String error;
-
- public ErrorView(String error) {
- super(false, "bg-popup");
- this.error = error;
- }
-
- @Override
- public void setup() {
- final Text errorHeader = header();
- errorHeader.setText(AppContext.getString("error"));
-
- final Text errorText = text();
- errorText.setText(error);
-
- final Button okButton = button();
- okButton.setText(AppContext.getString("ok"));
- okButton.setOnAction(_ -> { ViewStack.pop(); });
-
- add(Pos.CENTER,
- vboxFill(
- errorHeader,
- separator(),
-
- vspacer(),
- errorText,
- vspacer(),
-
- separator(),
- okButton
- )
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/GameView.java b/app/src/main/java/org/toop/app/view/views/GameView.java
deleted file mode 100644
index df69240..0000000
--- a/app/src/main/java/org/toop/app/view/views/GameView.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package org.toop.app.view.views;
-
-import javafx.application.Platform;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.ListView;
-import javafx.scene.control.TextField;
-import javafx.scene.text.Text;
-
-import java.util.function.Consumer;
-
-public final class GameView extends View {
- private static class GameOverView extends View {
- private final boolean iWon;
- private final String winner;
-
- public GameOverView(boolean iWon, String winner) {
- super(false, "bg-popup");
-
- this.iWon = iWon;
- this.winner = winner;
- }
-
- @Override
- public void setup() {
- final Text gameOverHeader = header();
- gameOverHeader.setText(AppContext.getString("game-over"));
-
- final Button okButton = button();
- okButton.setText(AppContext.getString("ok"));
- okButton.setOnAction(_ -> { ViewStack.pop(); });
-
- Text gameOverText = text();
-
- if (winner.isEmpty()) {
- gameOverText.setText(AppContext.getString("the-game-ended-in-a-draw"));
- } else {
- if (iWon) {
- gameOverText.setText(AppContext.getString("you-win") + " " + winner);
- } else {
- gameOverText.setText(AppContext.getString("you-lost-against") + " " + winner);
- }
- }
-
- add(Pos.CENTER,
- fit(vboxFill(
- gameOverHeader,
- separator(),
-
- vspacer(),
- gameOverText,
- vspacer(),
-
- separator(),
- okButton
- ))
- );
- }
- }
-
- private final Button forfeitButton;
- private final Button exitButton;
-
- private final Text currentPlayerHeader;
- private final Text currentMoveHeader;
-
- private final Text nextPlayerHeader;
-
- private final ListView chatListView;
- private final TextField chatInput;
-
- public GameView(Runnable onForfeit, Runnable onExit, Consumer onMessage) {
- assert onExit != null;
-
- super(true, "bg-primary");
-
- if (onForfeit != null) {
- forfeitButton = button();
- forfeitButton.setText(AppContext.getString("forfeit"));
- forfeitButton.setOnAction(_ -> onForfeit.run());
- } else {
- forfeitButton = null;
- }
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- if (onMessage != null) {
- chatListView = new ListView();
-
- chatInput = input();
- chatInput.setOnAction(_ -> {
- onMessage.accept(chatInput.getText());
- chatInput.setText("");
- });
- } else {
- chatListView = null;
- chatInput = null;
- }
-
- exitButton = button();
- exitButton.setText(AppContext.getString("exit"));
- exitButton.setOnAction(_ -> onExit.run());
-
- currentPlayerHeader = header("", "current-player");
- currentMoveHeader = header();
-
- nextPlayerHeader = header();
- }
-
- @Override
- public void setup() {
- add(Pos.TOP_RIGHT,
- fit(vboxFill(
- currentPlayerHeader,
-
- hboxFill(
- separator(),
- currentMoveHeader,
- separator()
- ),
-
- nextPlayerHeader
- ))
- );
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- forfeitButton,
- exitButton
- )
- );
-
- if (chatListView != null) {
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- chatListView,
- chatInput
- )
- ));
- }
- }
-
- public void nextPlayer(boolean isMe, String currentPlayer, String currentMove, String nextPlayer) {
- Platform.runLater(() -> {
- currentPlayerHeader.setText(currentPlayer);
- currentMoveHeader.setText(currentMove);
-
- nextPlayerHeader.setText(nextPlayer);
-
- if (isMe) {
- currentPlayerHeader.getStyleClass().add("my-turn");
- } else {
- currentPlayerHeader.getStyleClass().remove("my-turn");
- }
- });
-
- }
-
- public void updateChat(String message) {
- if (chatListView == null) {
- return;
- }
-
- final Text messageText = text();
- messageText.setText(message);
-
- chatListView.getItems().add(messageText);
- }
-
- public void gameOver(boolean iWon, String winner) {
- ViewStack.push(new GameOverView(iWon, winner));
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/LocalMultiplayerView.java b/app/src/main/java/org/toop/app/view/views/LocalMultiplayerView.java
deleted file mode 100644
index c44d784..0000000
--- a/app/src/main/java/org/toop/app/view/views/LocalMultiplayerView.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.GameInformation;
-import org.toop.app.game.Connect4Game;
-import org.toop.app.game.ReversiGame;
-import org.toop.app.game.TicTacToeGameThread;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.Slider;
-import javafx.scene.control.TextField;
-import javafx.scene.layout.VBox;
-import javafx.scene.text.Text;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public final class LocalMultiplayerView extends View {
- private final GameInformation information;
-
- public LocalMultiplayerView(GameInformation information) {
- super(true, "bg-primary");
- this.information = information;
- }
-
- public LocalMultiplayerView(GameInformation.Type type) {
- this(new GameInformation(type));
- }
-
- @Override
- public void setup() {
- final Button playButton = button();
- playButton.setText(AppContext.getString("play"));
- playButton.setOnAction(_ -> {
- for (final GameInformation.Player player : information.players) {
- if (player.name.isEmpty()) {
- ViewStack.push(new ErrorView(AppContext.getString("please-enter-your-name")));
- return;
- }
- }
-
- switch (information.type) {
- case TICTACTOE: new TicTacToeGameThread(information); break;
- case REVERSI: new ReversiGame(information); break;
- case CONNECT4: new Connect4Game(information); break;
- // case BATTLESHIP: new BattleshipGame(information); break;
- }
- });
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.CENTER,
- fit(vboxFill(
- hbox(
- setupPlayers()
- ),
-
- separator(),
- playButton
- ))
- );
-
- final Button backButton = button();
- backButton.setText(AppContext.getString("back"));
- backButton.setOnAction(_ -> { ViewStack.push(new MainView()); });
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- backButton
- )
- );
- }
-
- private VBox[] setupPlayers() {
- final VBox[] playerBoxes = new VBox[information.type.getPlayerCount()];
-
- for (int i = 0; i < playerBoxes.length; i++) {
- final int index = i;
-
- List nodes = new ArrayList<>();
-
- final Text playerHeader = header();
- playerHeader.setText(AppContext.getString("player") + " #" + (i + 1));
-
- nodes.add(playerHeader);
- nodes.add(separator());
-
- final Text nameText = text();
- nameText.setText(AppContext.getString("name"));
-
- if (information.players[i].isHuman) {
- final Button playerToggle = button();
- playerToggle.setText(AppContext.getString("player"));
- playerToggle.setOnAction(_ -> {
- information.players[index].isHuman = false;
- cleanup();
- setup();
- });
-
- nodes.add(vboxFill(playerToggle));
-
- final TextField playerNameInput = input();
- playerNameInput.setPromptText(AppContext.getString("enter-your-name"));
- playerNameInput.setText(information.players[i].name);
- playerNameInput.textProperty().addListener((_, _, newValue) -> {
- information.players[index].name = newValue;
- });
-
- nodes.add(vboxFill(nameText, playerNameInput));
- } else {
- final Button computerToggle = button();
- computerToggle.setText(AppContext.getString("computer"));
- computerToggle.setOnAction(_ -> {
- information.players[index].isHuman = true;
- cleanup();
- setup();
- });
-
- nodes.add(vboxFill(computerToggle));
-
- information.players[i].name = "Pism Bot V" + i;
-
- final Text computerNameText = text();
- computerNameText.setText(information.players[index].name);
-
- nodes.add(vboxFill(nameText, computerNameText));
-
- final Text computerDifficultyText = text();
- computerDifficultyText.setText(AppContext.getString("computer-difficulty"));
-
- final Slider computerDifficultySlider = slider();
- computerDifficultySlider.setMin(0);
- computerDifficultySlider.setMax(information.type.getMaxDepth());
- computerDifficultySlider.setValue(information.players[i].computerDifficulty);
- computerDifficultySlider.valueProperty().addListener((_, _, newValue) -> {
- information.players[index].computerDifficulty = newValue.intValue();
- });
-
- nodes.add(vboxFill(computerDifficultyText, computerDifficultySlider));
-
- final Text computerThinkTimeText = text();
- computerThinkTimeText.setText(AppContext.getString("computer-think-time"));
-
- final Slider computerThinkTimeSlider = slider();
- computerThinkTimeSlider.setMin(0);
- computerThinkTimeSlider.setMax(5);
- computerThinkTimeSlider.setValue(information.players[i].computerThinkTime);
- computerThinkTimeSlider.valueProperty().addListener((_, _, newValue) -> {
- information.players[index].computerThinkTime = newValue.intValue();
- });
-
- nodes.add(vboxFill(computerThinkTimeText, computerThinkTimeSlider));
- }
-
- playerBoxes[i] = vboxFill(nodes.toArray(new Node[0]));
- }
-
- return playerBoxes;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/LocalView.java b/app/src/main/java/org/toop/app/view/views/LocalView.java
deleted file mode 100644
index c4a1c4b..0000000
--- a/app/src/main/java/org/toop/app/view/views/LocalView.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.GameInformation;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-
-public final class LocalView extends View {
- public LocalView() {
- super(true, "bg-primary");
- }
-
- @Override
- public void setup() {
- final Button ticTacToeButton = button();
- ticTacToeButton.setText(AppContext.getString("tic-tac-toe"));
- ticTacToeButton.setOnAction(_ -> { ViewStack.push(new LocalMultiplayerView(GameInformation.Type.TICTACTOE)); });
-
- final Button reversiButton = button();
- reversiButton.setText(AppContext.getString("reversi"));
- reversiButton.setOnAction(_ -> { ViewStack.push(new LocalMultiplayerView(GameInformation.Type.REVERSI)); });
-
- final Button connect4Button = button();
- connect4Button.setText(AppContext.getString("connect4"));
- connect4Button.setOnAction(_ -> { ViewStack.push(new LocalMultiplayerView(GameInformation.Type.CONNECT4)); });
-
- add(Pos.CENTER,
- fit(vboxFill(
- ticTacToeButton,
- reversiButton,
- connect4Button
- ))
- );
-
- final Button backButton = button();
- backButton.setText(AppContext.getString("back"));
- backButton.setOnAction(_ -> { ViewStack.push(new MainView()); });
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- backButton
- )
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/MainView.java b/app/src/main/java/org/toop/app/view/views/MainView.java
deleted file mode 100644
index 10fa0fc..0000000
--- a/app/src/main/java/org/toop/app/view/views/MainView.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.App;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.local.AppContext;
-import org.toop.app.view.displays.SongDisplay;
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-
-public final class MainView extends View {
- public MainView() {
- super(true, "bg-primary");
- }
-
- @Override
- public void setup() {
- final Button localButton = button();
- localButton.setText(AppContext.getString("local"));
- localButton.setOnAction(_ -> { ViewStack.push(new LocalView()); });
-
- final Button onlineButton = button();
- onlineButton.setText(AppContext.getString("online"));
- onlineButton.setOnAction(_ -> { ViewStack.push(new OnlineView()); });
-
- final Button creditsButton = button();
- creditsButton.setText(AppContext.getString("credits"));
- creditsButton.setOnAction(_ -> { ViewStack.push(new CreditsView()); });
-
- final Button optionsButton = button();
- optionsButton.setText(AppContext.getString("options"));
- optionsButton.setOnAction(_ -> { ViewStack.push(new OptionsView()); });
-
- final Button quitButton = button();
- quitButton.setText(AppContext.getString("quit"));
- quitButton.setOnAction(_ -> { App.startQuit(); });
-
- final SongDisplay songdisplay = new SongDisplay();
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.CENTER,
- fit(vboxFill(
- localButton,
- onlineButton,
- creditsButton,
- optionsButton,
- quitButton
- ))
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/OnlineView.java b/app/src/main/java/org/toop/app/view/views/OnlineView.java
deleted file mode 100644
index 3d7750d..0000000
--- a/app/src/main/java/org/toop/app/view/views/OnlineView.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.Server;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.TextField;
-import javafx.scene.text.Text;
-
-public class OnlineView extends View {
- public OnlineView() {
- super(true, "bg-primary");
- }
-
- @Override
- public void setup() {
- final Text serverInformationHeader = header();
- serverInformationHeader.setText(AppContext.getString("server-information"));
-
- final Text serverIPText = text();
- serverIPText.setText(AppContext.getString("ip-address"));
-
- final TextField serverIPInput = input();
- serverIPInput.setPromptText(AppContext.getString("enter-the-server-ip"));
-
- final Text serverPortText = text();
- serverPortText.setText(AppContext.getString("port"));
-
- final TextField serverPortInput = input();
- serverPortInput.setPromptText(AppContext.getString("enter-the-server-port"));
-
- final Text playerNameText = text();
- playerNameText.setText(AppContext.getString("player-name"));
-
- final TextField playerNameInput = input();
- playerNameInput.setPromptText(AppContext.getString("enter-your-name"));
-
- final Button connectButton = button();
- connectButton.setText(AppContext.getString("connect"));
- connectButton.setOnAction(_ -> {
- new Server(serverIPInput.getText(), serverPortInput.getText(), playerNameInput.getText());
- });
-
- final SongDisplay songdisplay = new SongDisplay();
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.CENTER,
- fit(vboxFill(
- serverInformationHeader,
- separator(),
-
- vboxFill(
- serverIPText,
- serverIPInput
- ),
-
- vboxFill(
- serverPortText,
- serverPortInput
- ),
-
- vboxFill(
- playerNameText,
- playerNameInput
- ),
-
- vboxFill(
- connectButton
- )
- ))
- );
-
- final Button backButton = button();
- backButton.setText(AppContext.getString("back"));
- backButton.setOnAction(_ -> { ViewStack.push(new MainView()); });
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- backButton
- )
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/OptionsView.java b/app/src/main/java/org/toop/app/view/views/OptionsView.java
deleted file mode 100644
index 08cdfa0..0000000
--- a/app/src/main/java/org/toop/app/view/views/OptionsView.java
+++ /dev/null
@@ -1,258 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.App;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.framework.audio.VolumeControl;
-import org.toop.framework.audio.events.AudioEvents;
-import org.toop.framework.eventbus.EventFlow;
-import org.toop.local.AppContext;
-import org.toop.local.AppSettings;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.Slider;
-import javafx.scene.text.Text;
-import javafx.util.StringConverter;
-
-import java.util.Locale;
-
-public final class OptionsView extends View {
- public OptionsView() {
- super(false, "bg-secondary");
- }
-
- @Override
- public void setup() {
- final Text generalHeader = header();
- generalHeader.setText(AppContext.getString("general"));
-
- final Text volumeHeader = header();
- volumeHeader.setText(AppContext.getString("volume"));
-
- final Text styleHeader = header();
- styleHeader.setText(AppContext.getString("style"));
-
- add(Pos.CENTER,
- fit(hboxFill(
- vboxFill(
- generalHeader,
- separator(),
-
- vboxFill(
- text("language-text"),
- combobox("language-combobox")
- ),
-
- vboxFill(
- button("fullscreen-button")
- )
- ),
-
- vboxFill(
- volumeHeader,
- separator(),
-
- vboxFill(
- text("master-volume-text"),
- slider("master-volume-slider")
- ),
-
- vboxFill(
- text("effects-volume-text"),
- slider("effects-volume-slider")
- ),
-
- vboxFill(
- text("music-volume-text"),
- slider("music-volume-slider")
- )
- ),
-
- vboxFill(
- styleHeader,
- separator(),
-
- vboxFill(
- text("theme-text"),
- combobox("theme-combobox")
- ),
-
- vboxFill(
- text("layout-text"),
- combobox("layout-combobox")
- )
- )
- ))
- );
-
- setupLanguageOption();
- setupMasterVolumeOption();
- setupEffectsVolumeOption();
- setupMusicVolumeOption();
- setupThemeOption();
- setupLayoutOption();
- setupFullscreenOption();
-
- final Button backButton = button();
- backButton.setText(AppContext.getString("back"));
- backButton.setOnAction(_ -> { ViewStack.pop(); });
-
- final SongDisplay songdisplay = new SongDisplay();
-
-
- add(Pos.BOTTOM_RIGHT,
- fit(vboxFill(
- songdisplay
- )));
-
- add(Pos.BOTTOM_LEFT,
- vboxFill(
- backButton
- )
- );
- }
-
- private void setupLanguageOption() {
- final Text languageText = get("language-text");
- languageText.setText(AppContext.getString("language"));
-
- final ComboBox languageCombobox = get("language-combobox");
- languageCombobox.getItems().addAll(AppContext.getLocalization().getAvailableLocales());
- languageCombobox.setValue(AppContext.getLocale());
-
- languageCombobox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setLocale(newValue.toString());
- AppContext.setLocale(newValue);
- });
-
- languageCombobox.setConverter(new StringConverter<>() {
- @Override
- public String toString(Locale locale) {
- return AppContext.getString(locale.getDisplayName().toLowerCase());
- }
-
- @Override
- public Locale fromString(String s) {
- return null;
- }
- });
- }
-
- private void setupMasterVolumeOption() {
- final Text masterVolumeText = get("master-volume-text");
- masterVolumeText.setText(AppContext.getString("master-volume"));
-
- final Slider masterVolumeSlider = get("master-volume-slider");
- masterVolumeSlider.setMin(0);
- masterVolumeSlider.setMax(100);
- masterVolumeSlider.setValue(AppSettings.getSettings().getVolume());
-
- masterVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setVolume(newValue.intValue());
- new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.MASTERVOLUME)).asyncPostEvent();
- });
- }
-
- private void setupEffectsVolumeOption() {
- final Text effectsVolumeText = get("effects-volume-text");
- effectsVolumeText.setText(AppContext.getString("effects-volume"));
-
- final Slider effectsVolumeSlider = get("effects-volume-slider");
- effectsVolumeSlider.setMin(0);
- effectsVolumeSlider.setMax(100);
- effectsVolumeSlider.setValue(AppSettings.getSettings().getFxVolume());
-
- effectsVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setFxVolume(newValue.intValue());
- new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.FX)).asyncPostEvent();
- });
- }
-
- private void setupMusicVolumeOption() {
- final Text musicVolumeText = get("music-volume-text");
- musicVolumeText.setText(AppContext.getString("music-volume"));
-
- final Slider musicVolumeSlider = get("music-volume-slider");
- musicVolumeSlider.setMin(0);
- musicVolumeSlider.setMax(100);
- musicVolumeSlider.setValue(AppSettings.getSettings().getMusicVolume());
-
- musicVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setMusicVolume(newValue.intValue());
- new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.MUSIC)).asyncPostEvent();
- });
- }
-
- private void setupThemeOption() {
- final Text themeText = get("theme-text");
- themeText.setText(AppContext.getString("theme"));
-
- final ComboBox themeCombobox = get("theme-combobox");
- themeCombobox.getItems().addAll("dark", "light", "high-contrast");
- themeCombobox.setValue(AppSettings.getSettings().getTheme());
-
- themeCombobox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setTheme(newValue);
- App.setStyle(newValue, AppSettings.getSettings().getLayoutSize());
- });
-
- themeCombobox.setConverter(new StringConverter<>() {
- @Override
- public String toString(String theme) {
- return AppContext.getString(theme);
- }
-
- @Override
- public String fromString(String s) {
- return null;
- }
- });
- }
-
- private void setupLayoutOption() {
- final Text layoutText = get("layout-text");
- layoutText.setText(AppContext.getString("layout-size"));
-
- final ComboBox layoutCombobox = get("layout-combobox");
- layoutCombobox.getItems().addAll("small", "medium", "large");
- layoutCombobox.setValue(AppSettings.getSettings().getLayoutSize());
-
- layoutCombobox.getSelectionModel().selectedItemProperty().addListener((_, _, newValue) -> {
- AppSettings.getSettings().setLayoutSize(newValue);
- App.setStyle(AppSettings.getSettings().getTheme(), newValue);
- });
-
- layoutCombobox.setConverter(new StringConverter<>() {
- @Override
- public String toString(String layout) {
- return AppContext.getString(layout);
- }
-
- @Override
- public String fromString(String s) {
- return null;
- }
- });
- }
-
- private void setupFullscreenOption() {
- final Button fullscreenButton = get("fullscreen-button");
-
- if (AppSettings.getSettings().getFullscreen()) {
- fullscreenButton.setText(AppContext.getString("windowed"));
- fullscreenButton.setOnAction(_ -> {
- AppSettings.getSettings().setFullscreen(false);
- App.setFullscreen(false);
- });
- } else {
- fullscreenButton.setText(AppContext.getString("fullscreen"));
- fullscreenButton.setOnAction(_ -> {
- AppSettings.getSettings().setFullscreen(true);
- App.setFullscreen(true);
- });
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/QuitView.java b/app/src/main/java/org/toop/app/view/views/QuitView.java
deleted file mode 100644
index c2f37eb..0000000
--- a/app/src/main/java/org/toop/app/view/views/QuitView.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.App;
-import org.toop.app.view.View;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.text.Text;
-
-public final class QuitView extends View {
- public QuitView() {
- super(false, "bg-popup");
- }
-
- @Override
- public void setup() {
- final Text sureHeader = header();
- sureHeader.setText(AppContext.getString("are-you-sure"));
-
- final Button yesButton = button();
- yesButton.setText(AppContext.getString("yes"));
- yesButton.setOnAction(_ -> { App.quit(); });
-
- final Button noButton = button();
- noButton.setText(AppContext.getString("no"));
- noButton.setOnAction(_ -> { App.stopQuit(); });
-
- add(Pos.CENTER,
- fit(vbox(
- sureHeader,
-
- hbox(
- yesButton,
- noButton
- )
- ))
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/SendChallengeView.java b/app/src/main/java/org/toop/app/view/views/SendChallengeView.java
deleted file mode 100644
index d72560c..0000000
--- a/app/src/main/java/org/toop/app/view/views/SendChallengeView.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.GameInformation;
-import org.toop.app.Server;
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.local.AppContext;
-
-import javafx.geometry.Pos;
-import javafx.scene.Node;
-import javafx.scene.control.Button;
-import javafx.scene.control.ComboBox;
-import javafx.scene.control.Slider;
-import javafx.scene.text.Text;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.BiConsumer;
-
-public final class SendChallengeView extends View {
- private final Server server;
- private final String opponent;
- private final BiConsumer onSend;
-
- private final GameInformation.Player playerInformation;
-
- public SendChallengeView(Server server, String opponent, BiConsumer onSend) {
- super(false, "bg-popup");
-
- this.server = server;
- this.opponent = opponent;
- this.onSend = onSend;
-
- playerInformation = new GameInformation.Player();
- }
-
- @Override
- public void setup() {
- final Text challengeText = text();
- challengeText.setText(AppContext.getString("challenge"));
-
- final Text opponentHeader = header();
- opponentHeader.setText(opponent);
-
- final Text gameText = text();
- gameText.setText(AppContext.getString("to-a-game-of"));
-
- final ComboBox gamesCombobox = combobox();
- gamesCombobox.getItems().addAll(server.getGameList());
- gamesCombobox.setValue(gamesCombobox.getItems().getFirst());
-
- final Button sendButton = button();
- sendButton.setText(AppContext.getString("send"));
- sendButton.setOnAction(_ -> { onSend.accept(playerInformation, gamesCombobox.getValue()); });
-
- final Button cancelButton = button();
- cancelButton.setText(AppContext.getString("cancel"));
- cancelButton.setOnAction(_ -> {
- ViewStack.pop(); });
-
- final List nodes = new ArrayList<>();
-
- if (playerInformation.isHuman) {
- final Button playerToggle = button();
- playerToggle.setText(AppContext.getString("player"));
- playerToggle.setOnAction(_ -> {
- playerInformation.isHuman = false;
- cleanup();
- setup();
- });
-
- nodes.add(vbox(playerToggle));
- } else {
- final Button computerToggle = button();
- computerToggle.setText(AppContext.getString("computer"));
- computerToggle.setOnAction(_ -> {
- playerInformation.isHuman = true;
- cleanup();
- setup();
- });
-
- nodes.add(vbox(computerToggle));
-
- final Text computerDifficultyText = text();
- computerDifficultyText.setText(AppContext.getString("computer-difficulty"));
-
- final Slider computerDifficultySlider = slider();
- computerDifficultySlider.setMin(0);
- computerDifficultySlider.setMax(Server.gameToType(gamesCombobox.getValue()).getMaxDepth());
- computerDifficultySlider.setValue(playerInformation.computerDifficulty);
- computerDifficultySlider.valueProperty().addListener((_, _, newValue) -> {
- playerInformation.computerDifficulty = newValue.intValue();
- });
-
- nodes.add(vbox(computerDifficultyText, computerDifficultySlider));
- }
-
- add(Pos.CENTER,
- fit(hboxFill(
- vboxFill(
- challengeText,
- opponentHeader,
- gameText,
- gamesCombobox,
- separator(),
-
- hboxFill(
- sendButton,
- cancelButton
- )
- ),
-
- vboxFill(
- nodes.toArray(new Node[0])
- )
- ))
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/org/toop/app/view/views/ServerView.java b/app/src/main/java/org/toop/app/view/views/ServerView.java
deleted file mode 100644
index c819c14..0000000
--- a/app/src/main/java/org/toop/app/view/views/ServerView.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package org.toop.app.view.views;
-
-import org.toop.app.view.View;
-import org.toop.app.view.ViewStack;
-import org.toop.app.view.displays.SongDisplay;
-import org.toop.local.AppContext;
-
-import javafx.application.Platform;
-import javafx.geometry.Pos;
-import javafx.scene.control.Button;
-import javafx.scene.control.ListView;
-import javafx.scene.text.Text;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-public final class ServerView extends View {
- private final String user;
- private final Consumer onPlayerClicked;
- private final Runnable onDisconnect;
-
- private ListView |