feat: make timer stop game (Fixes #15)
All checks were successful
Linux arm64 / Build (push) Successful in 29s

This commit is contained in:
2025-02-01 13:41:13 +01:00
parent f22debdf5f
commit 352aee49e4
11 changed files with 109 additions and 11 deletions

View File

@@ -12,7 +12,7 @@ import sudoku.structure.MultiDoku;
public class Game {
public static enum GameState {
GameNotStarted, GameGoing, GameEnd
GameNotStarted, GameGoing
}
private final Map<Integer, Player> players;
@@ -60,7 +60,7 @@ public class Game {
}
public void stopGame() {
this.gameState = GameState.GameEnd;
this.gameState = GameState.GameNotStarted;
}
public GameState getGameState() {

View File

@@ -0,0 +1,49 @@
package gui.menu;
import game.Player;
import gui.ColorGenerator;
import gui.widget.SudokuRenderer;
import imgui.ImGui;
import imgui.ImVec4;
import sudoku.structure.MultiDoku;
public class EndGameView extends BaseView {
private final Player winner;
private float time = 0;
private static final ImVec4 YELLOW = new ImVec4(1, 1, 0, 1);
private final SudokuRenderer sudokuRenderer;
public EndGameView(StateMachine stateMachine, MultiDoku resolved, Player winner) {
super(stateMachine);
this.winner = winner;
this.sudokuRenderer = new SudokuRenderer(resolved);
}
private ImVec4 getPseudoColor() {
time += ImGui.getIO().getDeltaTime();
float factor = (float) Math.cos(time);
var color = ColorGenerator.hslToRgb(factor * factor, 0.9f, 0.4f);
return new ImVec4(color.r, color.g, color.b, 1.0f);
}
private void renderWinText() {
String winText = " a gagné !";
String text = winner.getPseudo() + winText;
float textWidth = ImGui.calcTextSizeX(text);
ImGui.setCursorPosX(ImGui.getIO().getDisplaySizeX() / 2.0f - textWidth / 2.0f);
ImGui.textColored(getPseudoColor(), winner.getPseudo());
ImGui.sameLine();
ImGui.textColored(YELLOW, winText);
}
@Override
public void render() {
renderWinText();
this.sudokuRenderer.render();
renderReturnButton();
}
}

View File

@@ -1,6 +1,6 @@
package gui.menu;
import game.Game;
import game.Player;
import gui.widget.LeaderboardRenderer;
import gui.widget.MultiPlayerCompleteProgress;
import gui.widget.SudokuRenderer;
@@ -8,7 +8,10 @@ import gui.widget.TimerRenderer;
import imgui.ImGui;
import network.client.Client;
import network.server.Server;
import sudoku.solver.BacktrackingSolver;
import sudoku.solver.Solver;
import sudoku.structure.Cell;
import sudoku.structure.MultiDoku;
public class MultiPlayerDokuView extends BaseView {
@@ -27,10 +30,19 @@ public class MultiPlayerDokuView extends BaseView {
this.leaderboardRenderer = new LeaderboardRenderer(client.getGame(), client.getPlayer());
this.sudokuRenderer.onCellChange.connect(this::onCellChange);
this.client.onDisconnect.connect(this::onDisconnect);
this.client.onGameEnd.connect(this::onGameEnd);
this.timerRenderer = new TimerRenderer(this.client.getGame().getStartTime(), this.client.getGame().getGameDuration());
this.completeProgress = new MultiPlayerCompleteProgress(this.client.getGame());
}
private void onGameEnd(Player winner) {
MultiDoku doku = this.client.getGame().getDoku();
doku.clearMutableCells();
Solver solver = new BacktrackingSolver();
solver.solve(doku);
this.stateMachine.overrideState(new EndGameView(stateMachine, doku, winner));
}
private void onCellChange(Cell cell) {
this.client.sendCellChange(cell);
}

View File

@@ -27,6 +27,11 @@ public class StateMachine {
menus.add(menu);
}
public void overrideState(BaseView menu) {
menus.getLast().cleanResources();
menus.set(menus.size() - 1, menu);
}
public void popState() {
menus.getLast().cleanResources();
menus.pop();

View File

@@ -19,7 +19,7 @@ public class MultiPlayerCompleteProgress {
}
public void render() {
Player firstPlayer = game.getLeaderboard().get(0);
Player firstPlayer = game.getLeaderboard().getFirst();
ImGui.setCursorPosX(ImGui.getIO().getDisplaySizeX() / 2.0f - progressSize.x / 2.0f);
String progressText = firstPlayer.getPseudo() + " - " + (emptyCellCount - firstPlayer.getRemainingCells()) + "/" + emptyCellCount;
this.progressBar.render(progressText, progressSize, 1.0f - firstPlayer.getRemainingCells() / (float) emptyCellCount);

View File

@@ -4,6 +4,7 @@ import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Random;
import common.ConsumerSignal;
import common.Signal;
import game.Game;
import game.Player;
@@ -21,6 +22,7 @@ public class Client {
public final Signal onDisconnect = new Signal();
public final Signal onClosed = new Signal();
public final Signal onGameStarted = new Signal();
public final ConsumerSignal<Player> onGameEnd = new ConsumerSignal<>();
Player player;

View File

@@ -78,8 +78,9 @@ public class ClientConnexion extends Connexion {
@Override
public void visitPacket(EndGamePacket packet) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'visitPacket'");
Player winner = this.client.getGame().getLeaderboard().getFirst();
this.client.getGame().stopGame();
this.client.onGameEnd.emit(winner);
}
@Override

View File

@@ -8,7 +8,9 @@ import java.util.List;
import game.Game;
import game.Player;
import game.Game.GameState;
import network.protocol.Packet;
import network.protocol.packets.EndGamePacket;
import network.protocol.packets.StartGamePacket;
import sudoku.io.SudokuSerializer;
import sudoku.structure.MultiDoku;
@@ -38,7 +40,16 @@ public class Server {
}
}
public void update() {
private void checkTimer() {
if (getGame() == null || getGame().getGameState() != GameState.GameGoing)
return;
long now = Instant.now().getEpochSecond();
long end = getGame().getStartTime().getEpochSecond() + getGame().getGameDuration();
if (now > end)
stopGame();
}
private void checkConnexions() {
for (var it = connexions.iterator(); it.hasNext();) {
ServerConnexion connexion = it.next();
if (!connexion.update()) {
@@ -49,6 +60,11 @@ public class Server {
}
}
public void update() {
checkTimer();
checkConnexions();
}
public void stop() {
this.acceptThread.cancel();
this.logicThread.cancel();
@@ -78,4 +94,10 @@ public class Server {
broadcastPacket(new StartGamePacket(SudokuSerializer.serializeSudoku(doku).toString(), now, gameDuration));
}
public void stopGame() {
// we don't need to specify the winner since it has to be the first
broadcastPacket(new EndGamePacket());
getGame().stopGame();
}
}

View File

@@ -153,9 +153,7 @@ public class ServerConnexion extends Connexion {
private void checkWin() {
if (this.player.getRemainingCells() == 0) {
// we don't need to specify the winner since it has to be the first
this.server.broadcastPacket(new EndGamePacket());
this.server.getGame().stopGame();
this.server.stopGame();
}
}

View File

@@ -19,7 +19,7 @@ public class ServerLogicThread extends Thread {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// e.printStackTrace();
e.printStackTrace();
break;
}
}

View File

@@ -183,6 +183,15 @@ public class MultiDoku {
return emptyCells.get(randomIndex);
}
public void clearMutableCells() {
for (Sudoku s : getSubGrids()) {
for (Cell cell : s.getCells()) {
if (cell.isMutable())
cell.clearCurrentSymbol();
}
}
}
public MultiDoku clone() {
//TODO: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah
return SudokuSerializer.deserializeSudoku(SudokuSerializer.serializeSudoku(this));