mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 10:54:51 +00:00
add: reversi game
This commit is contained in:
@@ -14,8 +14,8 @@ public class GameInformation {
|
||||
|
||||
public static int maxDepth(Type type) {
|
||||
return switch (type) {
|
||||
case TICTACTOE -> 5;
|
||||
case REVERSI -> 0; // Todo
|
||||
case TICTACTOE -> 5; // Todo. 5 seems to always draw or win. could increase to 9 but that might affect performance
|
||||
case REVERSI -> 10; // Todo. 10 is a guess. might be too slow or too bad.
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class GameInformation {
|
||||
public static class Player {
|
||||
public String name = "";
|
||||
public boolean isHuman = true;
|
||||
public int computerDifficulty = 0;
|
||||
public int computerDifficulty = 1;
|
||||
public int computerThinkTime = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.toop.app;
|
||||
|
||||
import org.toop.app.game.ReversiGame;
|
||||
import org.toop.app.game.TicTacToeGame;
|
||||
import org.toop.app.view.ViewStack;
|
||||
import org.toop.app.view.views.ChallengeView;
|
||||
import org.toop.app.view.views.ErrorView;
|
||||
import org.toop.app.view.views.OnlineView;
|
||||
import org.toop.app.view.views.SendChallengeView;
|
||||
import org.toop.app.view.views.ServerView;
|
||||
import org.toop.framework.eventbus.EventFlow;
|
||||
@@ -11,6 +13,7 @@ import org.toop.framework.networking.events.NetworkEvents;
|
||||
import org.toop.local.AppContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@@ -93,6 +96,10 @@ public final class Server {
|
||||
}
|
||||
|
||||
private void sendChallenge(String opponent) {
|
||||
if (!isPolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewStack.push(new SendChallengeView(this, opponent, (playerInformation, gameType) -> {
|
||||
new EventFlow().addPostEvent(new NetworkEvents.SendChallenge(clientId, opponent, gameType))
|
||||
.listen(NetworkEvents.GameMatchResponse.class, e -> {
|
||||
@@ -108,13 +115,20 @@ public final class Server {
|
||||
information.players[0].name = user;
|
||||
information.players[1].name = opponent;
|
||||
|
||||
new TicTacToeGame(information, myTurn, this::forfeitGame, this::exitGame);
|
||||
switch (type) {
|
||||
case TICTACTOE: new TicTacToeGame(information, myTurn, this::forfeitGame, this::exitGame); break;
|
||||
case REVERSI: new ReversiGame(information, myTurn, this::forfeitGame, this::exitGame); break;
|
||||
}
|
||||
}
|
||||
}).postEvent();
|
||||
}));
|
||||
}
|
||||
|
||||
private void handleReceivedChallenge(NetworkEvents.ChallengeResponse response) {
|
||||
if (!isPolling) {
|
||||
return;
|
||||
}
|
||||
|
||||
String challengerName = response.challengerName();
|
||||
challengerName = challengerName.substring(challengerName.indexOf("\"") + 1);
|
||||
challengerName = challengerName.substring(0, challengerName.indexOf("\""));
|
||||
@@ -145,11 +159,8 @@ public final class Server {
|
||||
information.players[1].name = e.opponent();
|
||||
|
||||
switch (type) {
|
||||
case TICTACTOE:
|
||||
new TicTacToeGame(information, myTurn, this::forfeitGame, this::exitGame);
|
||||
break;
|
||||
case REVERSI:
|
||||
break;
|
||||
case TICTACTOE: new TicTacToeGame(information, myTurn, this::forfeitGame, this::exitGame); break;
|
||||
case REVERSI: new ReversiGame(information, myTurn, this::forfeitGame, this::exitGame); break;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -157,11 +168,12 @@ public final class Server {
|
||||
}
|
||||
|
||||
private void disconnect() {
|
||||
// Todo
|
||||
new EventFlow().addPostEvent(new NetworkEvents.CloseClient(clientId)).postEvent();
|
||||
ViewStack.push(new OnlineView());
|
||||
}
|
||||
|
||||
private void forfeitGame() {
|
||||
// Todo
|
||||
new EventFlow().addPostEvent(new NetworkEvents.SendForfeit(clientId)).postEvent();
|
||||
}
|
||||
|
||||
private void exitGame() {
|
||||
@@ -182,6 +194,12 @@ public final class Server {
|
||||
public List<String> getGamesList() {
|
||||
final List<String> list = new ArrayList<String>();
|
||||
list.add("tic-tac-toe"); // Todo: get games list from server and check if the game is supported
|
||||
list.add("reversi");
|
||||
|
||||
new EventFlow().addPostEvent(new NetworkEvents.SendGetGamelist(clientId))
|
||||
.listen(NetworkEvents.GamelistResponse.class, e -> {
|
||||
System.out.println(Arrays.toString(e.gamelist()));
|
||||
}).postEvent();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,10 @@ import java.util.function.Consumer;
|
||||
|
||||
public abstract class GameCanvas {
|
||||
protected record Cell(float x, float y, float width, float height) {
|
||||
public boolean isInside(double x, double y) {
|
||||
return x >= this.x && x <= this.x + width &&
|
||||
y >= this.y && y <= this.y + height;
|
||||
}
|
||||
}
|
||||
|
||||
protected final Canvas canvas;
|
||||
@@ -19,18 +23,15 @@ public abstract class GameCanvas {
|
||||
protected final int width;
|
||||
protected final int height;
|
||||
|
||||
protected final int rows;
|
||||
protected final int columns;
|
||||
protected final int rowSize;
|
||||
protected final int columnSize;
|
||||
|
||||
protected final int gapSize;
|
||||
protected final boolean edges;
|
||||
|
||||
protected final Cell[] cells;
|
||||
|
||||
protected GameCanvas(Color color, int width, int height, int rows, int columns, int gapSize, boolean edges, Consumer<Integer> onCellClicked) {
|
||||
width += gapSize * 2;
|
||||
height += gapSize * 2;
|
||||
|
||||
protected GameCanvas(Color color, int width, int height, int rowSize, int columnSize, int gapSize, boolean edges, Consumer<Integer> onCellClicked) {
|
||||
canvas = new Canvas(width, height);
|
||||
graphics = canvas.getGraphicsContext2D();
|
||||
|
||||
@@ -39,23 +40,23 @@ public abstract class GameCanvas {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.rows = rows;
|
||||
this.columns = columns;
|
||||
this.rowSize = rowSize;
|
||||
this.columnSize = columnSize;
|
||||
|
||||
this.gapSize = gapSize;
|
||||
this.edges = edges;
|
||||
|
||||
cells = new Cell[rows * columns];
|
||||
cells = new Cell[rowSize * columnSize];
|
||||
|
||||
final float cellWidth = ((float) width - gapSize * rows) / rows;
|
||||
final float cellHeight = ((float) height - gapSize * columns) / columns;
|
||||
final float cellWidth = ((float)width - gapSize * rowSize - gapSize) / rowSize;
|
||||
final float cellHeight = ((float)height - gapSize * columnSize - gapSize) / columnSize;
|
||||
|
||||
for (int y = 0; y < columns; y++) {
|
||||
final float startY = gapSize + y * cellHeight + y * gapSize;
|
||||
for (int y = 0; y < columnSize; y++) {
|
||||
final float startY = y * cellHeight + y * gapSize + gapSize;
|
||||
|
||||
for (int x = 0; x < rows; x++) {
|
||||
final float startX = gapSize + x * cellWidth + x * gapSize;
|
||||
cells[y * rows + x] = new Cell(startX, startY, cellWidth, cellHeight);
|
||||
for (int x = 0; x < rowSize; x++) {
|
||||
final float startX = x * cellWidth + x * gapSize + gapSize;
|
||||
cells[x + y * rowSize] = new Cell(startX, startY, cellWidth, cellHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +65,15 @@ public abstract class GameCanvas {
|
||||
return;
|
||||
}
|
||||
|
||||
final int column = (int)((event.getX() / this.width) * rows);
|
||||
final int row = (int)((event.getY() / this.height) * columns);
|
||||
final int column = (int)((event.getX() / this.width) * rowSize);
|
||||
final int row = (int)((event.getY() / this.height) * columnSize);
|
||||
|
||||
event.consume();
|
||||
onCellClicked.accept(column + row * rows);
|
||||
final Cell cell = cells[column + row * rowSize];
|
||||
|
||||
if (cell.isInside(event.getX(), event.getY())) {
|
||||
event.consume();
|
||||
onCellClicked.accept(column + row * rowSize);
|
||||
}
|
||||
});
|
||||
|
||||
render();
|
||||
@@ -81,20 +86,22 @@ public abstract class GameCanvas {
|
||||
public void render() {
|
||||
graphics.setFill(color);
|
||||
|
||||
for (int x = 1; x < rows; x++) {
|
||||
graphics.fillRect(cells[x].x() - gapSize, 0, gapSize, height + gapSize);
|
||||
for (int x = 0; x < rowSize - 1; x++) {
|
||||
final float start = cells[x].x + cells[x].width;
|
||||
graphics.fillRect(start, gapSize, gapSize, height - gapSize * 2);
|
||||
}
|
||||
|
||||
for (int y = 1; y < columns; y++) {
|
||||
graphics.fillRect(0, cells[y * rows].y() - gapSize, width + gapSize, gapSize);
|
||||
for (int y = 0; y < columnSize - 1; y++) {
|
||||
final float start = cells[y * rowSize].y + cells[y * rowSize].height;
|
||||
graphics.fillRect(gapSize, start, width - gapSize * 2, gapSize);
|
||||
}
|
||||
|
||||
if (edges) {
|
||||
graphics.fillRect(0, 0, gapSize, height + gapSize);
|
||||
graphics.fillRect(0, 0, width + gapSize, gapSize);
|
||||
graphics.fillRect(0, 0, width, gapSize);
|
||||
graphics.fillRect(0, 0, gapSize, height);
|
||||
|
||||
graphics.fillRect(width + gapSize, 0, gapSize, height + gapSize * 2);
|
||||
graphics.fillRect(0, height + gapSize, width + gapSize * 2, gapSize);
|
||||
graphics.fillRect(width - gapSize, 0, gapSize, height);
|
||||
graphics.fillRect(0, height - gapSize, width, gapSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package org.toop.app.canvas;
|
||||
|
||||
import javafx.scene.layout.Background;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.toop.game.Game;
|
||||
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -12,15 +9,26 @@ public class ReversiCanvas extends GameCanvas{
|
||||
super(color, width, height, 8, 8, 10, true, onCellClicked);
|
||||
drawStartingDots();
|
||||
}
|
||||
public void drawStartingDots(){
|
||||
drawDot(Color.BLACK,28);
|
||||
drawDot(Color.WHITE,36);
|
||||
drawDot(Color.BLACK,35);
|
||||
drawDot(Color.WHITE,27);
|
||||
}
|
||||
public void drawLegalMoves(Game.Move[] moves){
|
||||
for(Game.Move move : moves){
|
||||
drawDot(new Color(1f,0,0,0.25f),move.position());
|
||||
}
|
||||
|
||||
public void drawDot(Color color, int cell) {
|
||||
final float x = cells[cell].x() + gapSize;
|
||||
final float y = cells[cell].y() + gapSize;
|
||||
|
||||
final float width = cells[cell].width() - gapSize * 2;
|
||||
final float height = cells[cell].height() - gapSize * 2;
|
||||
|
||||
graphics.setFill(color);
|
||||
graphics.fillOval(x, y, width, height);
|
||||
}
|
||||
|
||||
public void drawStartingDots() {
|
||||
drawDot(Color.BLACK, 28);
|
||||
drawDot(Color.WHITE, 36);
|
||||
drawDot(Color.BLACK, 35);
|
||||
drawDot(Color.WHITE, 27);
|
||||
}
|
||||
|
||||
public void drawLegalPosition(int cell) {
|
||||
drawDot(new Color(1.0f, 0.0f, 0.0f, 0.5f), cell);
|
||||
}
|
||||
}
|
||||
|
||||
233
app/src/main/java/org/toop/app/game/ReversiGame.java
Normal file
233
app/src/main/java/org/toop/app/game/ReversiGame.java
Normal file
@@ -0,0 +1,233 @@
|
||||
package org.toop.app.game;
|
||||
|
||||
import org.toop.app.App;
|
||||
import org.toop.app.GameInformation;
|
||||
import org.toop.app.canvas.ReversiCanvas;
|
||||
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.Game;
|
||||
import org.toop.game.reversi.Reversi;
|
||||
import org.toop.game.reversi.ReversiAI;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public final class ReversiGame {
|
||||
private final GameInformation information;
|
||||
|
||||
private final int myTurn;
|
||||
private final BlockingQueue<Game.Move> moveQueue;
|
||||
|
||||
private final Reversi game;
|
||||
private final ReversiAI ai;
|
||||
|
||||
private final GameView view;
|
||||
private final ReversiCanvas canvas;
|
||||
|
||||
public ReversiGame(GameInformation information, int myTurn, Runnable onForfeit, Runnable onExit) {
|
||||
this.information = information;
|
||||
|
||||
this.myTurn = myTurn;
|
||||
moveQueue = new LinkedBlockingQueue<Game.Move>();
|
||||
|
||||
game = new Reversi();
|
||||
ai = new ReversiAI();
|
||||
|
||||
if (onForfeit == null || onExit == null) {
|
||||
view = new GameView(null, () -> {
|
||||
ViewStack.push(new LocalMultiplayerView(information));
|
||||
});
|
||||
} else {
|
||||
view = new GameView(onForfeit, onExit);
|
||||
}
|
||||
|
||||
canvas = new ReversiCanvas(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? 'B' : 'W';
|
||||
|
||||
try {
|
||||
moveQueue.put(new Game.Move(cell, value));
|
||||
} catch (InterruptedException _) {}
|
||||
}
|
||||
} else {
|
||||
if (information.players[0].isHuman) {
|
||||
final char value = myTurn == 0? 'B' : 'W';
|
||||
|
||||
try {
|
||||
moveQueue.put(new Game.Move(cell, value));
|
||||
} catch (InterruptedException _) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
view.add(Pos.CENTER, canvas.getCanvas());
|
||||
ViewStack.push(view);
|
||||
|
||||
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)
|
||||
.listen(NetworkEvents.ReceivedMessage.class, this::onReceivedMessage);
|
||||
|
||||
setGameLabels(myTurn == 0);
|
||||
}
|
||||
|
||||
updateCanvas();
|
||||
}
|
||||
|
||||
private void localGameThread() {
|
||||
boolean isRunning = true;
|
||||
|
||||
while (isRunning) {
|
||||
final int currentTurn = game.getCurrentTurn();
|
||||
final char currentValue = currentTurn == 0? 'B' : 'W';
|
||||
final int nextTurn = (currentTurn + 1) % GameInformation.Type.playerCount(information.type);
|
||||
|
||||
view.nextPlayer(information.players[currentTurn].isHuman,
|
||||
information.players[currentTurn].name,
|
||||
String.valueOf(currentValue),
|
||||
information.players[nextTurn].name);
|
||||
|
||||
Game.Move move = null;
|
||||
|
||||
if (information.players[currentTurn].isHuman) {
|
||||
try {
|
||||
final Game.Move wants = moveQueue.take();
|
||||
final Game.Move[] legalMoves = game.getLegalMoves();
|
||||
|
||||
for (final Game.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 Game.State state = game.play(move);
|
||||
updateCanvas();
|
||||
|
||||
if (state != Game.State.NORMAL) {
|
||||
if (state == Game.State.WIN) {
|
||||
view.gameOver(true, information.players[currentTurn].name);
|
||||
} else if (state == Game.State.DRAW) {
|
||||
view.gameOver(false, "");
|
||||
}
|
||||
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onMoveResponse(NetworkEvents.GameMoveResponse response) {
|
||||
char playerChar;
|
||||
|
||||
if (response.player().equalsIgnoreCase(information.players[0].name)) {
|
||||
playerChar = myTurn == 0? 'B' : 'W';
|
||||
} else {
|
||||
playerChar = myTurn == 0? 'W' : 'B';
|
||||
}
|
||||
|
||||
final Game.Move move = new Game.Move(Integer.parseInt(response.move()), playerChar);
|
||||
final Game.State state = game.play(move);
|
||||
|
||||
if (state != Game.State.NORMAL) {
|
||||
if (state == Game.State.WIN) {
|
||||
if (response.player().equalsIgnoreCase(information.players[0].name)) {
|
||||
view.gameOver(true, information.players[0].name);
|
||||
} else {
|
||||
view.gameOver(false, information.players[1].name);
|
||||
}
|
||||
} else if (state == Game.State.DRAW) {
|
||||
view.gameOver(false, "");
|
||||
}
|
||||
}
|
||||
|
||||
updateCanvas();
|
||||
setGameLabels(game.getCurrentTurn() == myTurn);
|
||||
}
|
||||
|
||||
private void onYourTurnResponse(NetworkEvents.YourTurnResponse response) {
|
||||
moveQueue.clear();
|
||||
|
||||
int position = -1;
|
||||
|
||||
if (information.players[0].isHuman) {
|
||||
try {
|
||||
position = moveQueue.take().position();
|
||||
} catch (InterruptedException _) {}
|
||||
} else {
|
||||
final Game.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) {
|
||||
view.updateChat("anon", msg.message());
|
||||
}
|
||||
|
||||
private void updateCanvas() {
|
||||
// Todo: this is very inefficient. still very fast but if the grid is bigger it might cause issues. improve.
|
||||
|
||||
canvas.clear();
|
||||
canvas.render();
|
||||
|
||||
for (int i = 0; i < game.board.length; i++) {
|
||||
if (game.board[i] == 'B') {
|
||||
canvas.drawDot(Color.BLACK, i);
|
||||
} else if (game.board[i] == 'W') {
|
||||
canvas.drawDot(Color.WHITE, i);
|
||||
}
|
||||
}
|
||||
|
||||
final Game.Move[] legalMoves = game.getLegalMoves();
|
||||
|
||||
for (final Game.Move legalMove : legalMoves) {
|
||||
canvas.drawLegalPosition(legalMove.position());
|
||||
}
|
||||
}
|
||||
|
||||
private void setGameLabels(boolean isMe) {
|
||||
final int currentTurn = game.getCurrentTurn();
|
||||
final char currentValue = currentTurn == 0? 'B' : 'W';
|
||||
|
||||
view.nextPlayer(isMe,
|
||||
information.players[isMe? 0 : 1].name,
|
||||
String.valueOf(currentValue),
|
||||
information.players[isMe? 1 : 0].name);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package org.toop.app.layer.layers.game;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.paint.Color;
|
||||
import org.toop.app.App;
|
||||
import org.toop.app.canvas.ReversiCanvas;
|
||||
import org.toop.app.layer.*;
|
||||
import org.toop.app.layer.containers.HorizontalContainer;
|
||||
import org.toop.app.layer.containers.VerticalContainer;
|
||||
import org.toop.app.layer.layers.MainLayer;
|
||||
import org.toop.game.Game;
|
||||
import org.toop.game.reversi.Reversi;
|
||||
import org.toop.game.reversi.ReversiAI;
|
||||
import org.toop.local.AppContext;
|
||||
|
||||
public class ReversiLayer extends Layer{
|
||||
private ReversiCanvas canvas;
|
||||
private Reversi reversi;
|
||||
private ReversiAI reversiAI;
|
||||
public ReversiLayer(){
|
||||
super("bg-secondary"); //make reversiboard background dark green
|
||||
|
||||
canvas = new ReversiCanvas(Color.GREEN,(App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75, (cell) -> {
|
||||
reversi.play(new Game.Move(cell,reversi.getCurrentPlayer()));
|
||||
reload();
|
||||
canvas.drawLegalMoves(reversi.getLegalMoves());
|
||||
});
|
||||
reversi = new Reversi() ;
|
||||
reversiAI = new ReversiAI();
|
||||
|
||||
|
||||
reload();
|
||||
canvas.drawLegalMoves(reversi.getLegalMoves());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
popAll();
|
||||
canvas.resize((App.getHeight() / 100) * 75, (App.getHeight() / 100) * 75);
|
||||
|
||||
for (int i = 0; i < reversi.board.length; i++) {
|
||||
final char value = reversi.board[i];
|
||||
|
||||
if (value == 'B') {
|
||||
canvas.drawDot(Color.BLACK, i);
|
||||
} else if (value == 'W') {
|
||||
canvas.drawDot(Color.WHITE, i);
|
||||
}
|
||||
}
|
||||
|
||||
final var backButton = NodeBuilder.button(AppContext.getString("back"), () -> {
|
||||
App.activate(new MainLayer());
|
||||
});
|
||||
|
||||
final Container controlContainer = new VerticalContainer(5);
|
||||
controlContainer.addNodes(backButton);
|
||||
|
||||
final Container informationContainer = new HorizontalContainer(15);
|
||||
|
||||
addContainer(controlContainer, Pos.BOTTOM_LEFT, 2, -2, 0, 0);
|
||||
addContainer(informationContainer, Pos.TOP_LEFT, 2, 2, 0, 0);
|
||||
addGameCanvas(canvas, Pos.CENTER, 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.toop.app.view.views;
|
||||
|
||||
import org.toop.app.GameInformation;
|
||||
import org.toop.app.game.ReversiGame;
|
||||
import org.toop.app.game.TicTacToeGame;
|
||||
import org.toop.app.view.View;
|
||||
import org.toop.app.view.ViewStack;
|
||||
@@ -42,8 +43,8 @@ public final class LocalMultiplayerView extends View {
|
||||
}
|
||||
|
||||
switch (information.type) {
|
||||
case TICTACTOE: new TicTacToeGame(information, 0, null, null);
|
||||
case REVERSI: break;
|
||||
case TICTACTOE: new TicTacToeGame(information, 0, null, null); break;
|
||||
case REVERSI: new ReversiGame(information, 0, null, null); break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public final class LocalView extends View {
|
||||
|
||||
final Button reversiButton = button();
|
||||
reversiButton.setText(AppContext.getString("reversi"));
|
||||
reversiButton.setOnAction(_ -> {});
|
||||
reversiButton.setOnAction(_ -> { ViewStack.push(new LocalMultiplayerView(GameInformation.Type.REVERSI)); });
|
||||
|
||||
add(Pos.CENTER,
|
||||
fit(vboxFill(
|
||||
|
||||
@@ -3,6 +3,7 @@ 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.framework.audio.VolumeControl;
|
||||
import org.toop.framework.audio.events.AudioEvents;
|
||||
import org.toop.framework.eventbus.EventFlow;
|
||||
import org.toop.local.AppContext;
|
||||
@@ -143,7 +144,7 @@ public final class OptionsView extends View {
|
||||
|
||||
masterVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
|
||||
AppSettings.getSettings().setVolume(newValue.intValue());
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue())).asyncPostEvent();
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.MASTERVOLUME)).asyncPostEvent();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -158,7 +159,7 @@ public final class OptionsView extends View {
|
||||
|
||||
effectsVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
|
||||
AppSettings.getSettings().setFxVolume(newValue.intValue());
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeFxVolume(newValue.doubleValue())).asyncPostEvent();
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.FX)).asyncPostEvent();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ public final class OptionsView extends View {
|
||||
|
||||
musicVolumeSlider.valueProperty().addListener((_, _, newValue) -> {
|
||||
AppSettings.getSettings().setMusicVolume(newValue.intValue());
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeMusicVolume(newValue.doubleValue())).asyncPostEvent();
|
||||
new EventFlow().addPostEvent(new AudioEvents.ChangeVolume(newValue.doubleValue(), VolumeControl.MUSIC)).asyncPostEvent();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.toop.local;
|
||||
|
||||
import org.toop.app.App;
|
||||
import org.toop.framework.audio.VolumeControl;
|
||||
import org.toop.framework.audio.events.AudioEvents;
|
||||
import org.toop.framework.eventbus.EventFlow;
|
||||
import org.toop.framework.resource.ResourceManager;
|
||||
@@ -25,13 +26,13 @@ public class AppSettings {
|
||||
AppContext.setLocale(Locale.of(settingsData.locale));
|
||||
App.setFullscreen(settingsData.fullScreen);
|
||||
new EventFlow()
|
||||
.addPostEvent(new AudioEvents.ChangeVolume(settingsData.volume))
|
||||
.addPostEvent(new AudioEvents.ChangeVolume(settingsData.volume, VolumeControl.MASTERVOLUME))
|
||||
.asyncPostEvent();
|
||||
new EventFlow()
|
||||
.addPostEvent(new AudioEvents.ChangeFxVolume(settingsData.fxVolume))
|
||||
.addPostEvent(new AudioEvents.ChangeVolume(settingsData.fxVolume, VolumeControl.FX))
|
||||
.asyncPostEvent();
|
||||
new EventFlow()
|
||||
.addPostEvent(new AudioEvents.ChangeMusicVolume(settingsData.musicVolume))
|
||||
.addPostEvent(new AudioEvents.ChangeVolume(settingsData.musicVolume, VolumeControl.MUSIC))
|
||||
.asyncPostEvent();
|
||||
App.setStyle(settingsAsset.getTheme(), settingsAsset.getLayoutSize());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user