diff --git a/src/main/java/com/boredxgames/tictactoeclient/presentation/GameController.java b/src/main/java/com/boredxgames/tictactoeclient/presentation/GameController.java
index fe84999..8ed23dd 100644
--- a/src/main/java/com/boredxgames/tictactoeclient/presentation/GameController.java
+++ b/src/main/java/com/boredxgames/tictactoeclient/presentation/GameController.java
@@ -9,12 +9,10 @@
import com.boredxgames.tictactoeclient.domain.model.Move;
import com.boredxgames.tictactoeclient.domain.services.game.GameBoard;
import com.boredxgames.tictactoeclient.domain.model.GameState;
-import com.boredxgames.tictactoeclient.domain.services.AIService;
import com.boredxgames.tictactoeclient.domain.services.game.GameService;
import com.boredxgames.tictactoeclient.domain.services.game.OfflinePVEAIService;
import com.boredxgames.tictactoeclient.domain.services.game.OfflinePVPService;
import javafx.animation.PauseTransition;
-import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
@@ -30,13 +28,11 @@
import javafx.scene.media.MediaView;
import javafx.scene.text.Text;
import javafx.util.Duration;
+
import java.net.URL;
import java.util.Objects;
import java.util.ResourceBundle;
-/**
- * @author Tasneem
- */
public class GameController implements Initializable, NavigationParameterAware {
public GridPane gameGrid;
@@ -86,8 +82,6 @@ public class GameController implements Initializable, NavigationParameterAware {
@FXML
private Button playAgainButton;
@FXML
- private Button changeDifficultyButton;
- @FXML
private Button mainMenuButton;
private GameBoard gameBoard;
@@ -100,12 +94,14 @@ public class GameController implements Initializable, NavigationParameterAware {
private GameService gameService;
+ private MediaPlayer currentMediaPlayer;
+
@Override
public void initialize(URL url, ResourceBundle rb) {
cells = new Button[][]{
- {cell00, cell01, cell02},
- {cell10, cell11, cell12},
- {cell20, cell21, cell22}
+ {cell00, cell01, cell02},
+ {cell10, cell11, cell12},
+ {cell20, cell21, cell22}
};
gameBoard = new GameBoard();
setupCellHandlers();
@@ -119,15 +115,11 @@ public void setNavigationParameter(Object parameter) {
this.player2Name = params.player2();
this.gameMode = params.mode();
} else {
- // Default
this.gameMode = GameMode.OFFLINE_PVP;
- this.player1Name = "Player 1";
- this.player2Name = "Player 2";
}
applyPlayerInfo();
applyGameModeSettings();
-
resetGame();
}
@@ -139,28 +131,21 @@ private void applyPlayerInfo() {
private void applyGameModeSettings() {
switch (gameMode) {
case OFFLINE_PVP -> {
- opponentTypeLabel.setText("PLAYER 2");
+ opponentTypeLabel.setText(player2Name);
difficultyBadge.setVisible(false);
difficultyBadge.setManaged(false);
- changeDifficultyButton.setVisible(false);
- changeDifficultyButton.setManaged(false);
gameService = new OfflinePVPService();
}
case OFFLINE_PVE -> {
opponentTypeLabel.setText("CPU (O)");
difficultyBadge.setVisible(true);
difficultyBadge.setManaged(true);
- changeDifficultyButton.setVisible(true);
- changeDifficultyButton.setManaged(true);
gameService = new OfflinePVEAIService();
}
case ONLINE_PVP -> {
- opponentTypeLabel.setText("ONLINE PLAYER");
+ opponentTypeLabel.setText(player2Name);
difficultyBadge.setVisible(false);
difficultyBadge.setManaged(false);
- changeDifficultyButton.setVisible(false);
- changeDifficultyButton.setManaged(false);
- // gameService = new OnlinePVPService(); // TODO: implement online pvp service
}
}
}
@@ -180,21 +165,17 @@ private void setupButtonHandlers() {
playAgainButton.setOnAction(e -> resetGame());
mainMenuButton.setOnAction(e -> {
- NavigationManager.navigate(Screens.PRIMARY, NavigationAction.REPLACE_ALL); // TODO: change to mode selection screen
+ NavigationManager.navigate(Screens.GAME_MODE, NavigationAction.REPLACE_ALL);
});
backButton.setOnAction(e -> {
- NavigationManager.pop();
+ NavigationManager.navigate(Screens.GAME_MODE, NavigationAction.REPLACE_ALL);
});
settingsButton.setOnAction(e -> {
NavigationManager.navigate(Screens.SETTINGS, NavigationAction.REPLACE_ALL);
});
-
- changeDifficultyButton.setOnAction(e -> {
- // TODO change difficulty
- });
}
private void handleCellClick(int row, int col) {
@@ -316,32 +297,6 @@ private void setActiveCard(VBox activeCard, VBox inactiveCard) {
inactiveCard.getStyleClass().remove("active-card");
}
- private void makeCPUMove() {
- if (gameMode != GameMode.OFFLINE_PVE) {
- return;
- }
-
- int[] aiMove = AIService.nextMove(gameBoard, AIService.getDiffiulty());
- if (aiMove == null) {
- return;
- }
-
- Platform.runLater(() -> {
- if (gameBoard.makeMove(aiMove[0], aiMove[1], GameBoard.PLAYER_O)) {
- updateCell(aiMove[0], aiMove[1], GameBoard.PLAYER_O);
-
- GameState state = gameBoard.getGameState();
- if (state != GameState.IN_PROGRESS) {
- handleGameEnd();
- } else {
- gameBoard.switchPlayer();
- updateTurnIndicator();
- enableBoard();
- }
- }
- });
- }
-
private void handleGameEnd() {
GameState state = gameBoard.getGameState();
@@ -354,13 +309,18 @@ private void handleGameEnd() {
}
}
- if (state == GameState.X_WINS) {
- playerScore++;
- playerScoreLabel.setText(String.valueOf(playerScore));
- playVictoryVideo();
- } else if (state == GameState.O_WINS) {
- opponentScore++;
- opponentScoreLabel.setText(String.valueOf(opponentScore));
+ switch (state) {
+ case X_WINS -> {
+ playerScore++;
+ playerScoreLabel.setText(String.valueOf(playerScore));
+ playVictoryVideo("you_win");
+ }
+ case O_WINS -> {
+ opponentScore++;
+ opponentScoreLabel.setText(String.valueOf(opponentScore));
+ playVictoryVideo("loser");
+ }
+ case DRAW -> playVictoryVideo("handshake");
}
PauseTransition pause = new PauseTransition(Duration.millis(800));
@@ -370,66 +330,68 @@ private void handleGameEnd() {
private void showGameOverModal(GameState state) {
switch (state) {
- case X_WINS:
- modalIcon.setText("emoji_events");
+ case X_WINS -> {
modalTitle.setText("Victory!");
- modalMessage.setText(gameMode == GameMode.OFFLINE_PVE
- ? "The CPU didn't stand a chance against your moves."
- : "Player 1 wins the game!");
- break;
-
- case O_WINS:
- modalIcon.setText("sentiment_dissatisfied");
+ modalMessage.setText(player1Name + " wins!");
+ }
+ case O_WINS -> {
modalTitle.setText("Defeat!");
- modalMessage.setText(gameMode == GameMode.OFFLINE_PVE
- ? "The CPU outsmarted you this time."
- : "Player 2 wins the game!");
- break;
-
- case DRAW:
- modalIcon.setText("handshake");
+ modalMessage.setText(player2Name + " wins!");
+ }
+ case DRAW -> {
modalTitle.setText("Draw!");
- modalMessage.setText("It's a tie! Both players played well.");
- break;
+ modalMessage.setText("Both players played well.");
+ }
}
-
modalOverlay.setVisible(true);
}
- private void playVictoryVideo() {
+ private void playVictoryVideo(String videoName) {
try {
String videoPath = Objects.requireNonNull(
- getClass().getResource("/assets/videos/you_win.mp4")
+ getClass().getResource("/assets/videos/" + videoName + ".mp4")
).toExternalForm();
+ if (currentMediaPlayer != null) {
+ currentMediaPlayer.stop();
+ currentMediaPlayer.dispose();
+ }
+
Media media = new Media(videoPath);
- MediaPlayer player = new MediaPlayer(media);
- victoryVideo.setMediaPlayer(player);
+ currentMediaPlayer = new MediaPlayer(media);
+ victoryVideo.setMediaPlayer(currentMediaPlayer);
+ currentMediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
+ currentMediaPlayer.setAutoPlay(true);
victoryVideo.setVisible(true);
- player.setAutoPlay(true);
-
- player.setOnEndOfMedia(() -> {
- victoryVideo.setVisible(false);
- });
} catch (Exception e) {
- System.out.println("Error getting the video: " + e);
+ System.out.println("Video error: " + e.getMessage());
}
}
public void resetGame() {
gameBoard.resetGame();
- for (int row = 0; row < 3; row++) {
- for (int col = 0; col < 3; col++) {
- cells[row][col].setGraphic(null);
- cells[row][col].setDisable(false);
- cells[row][col].getStyleClass().remove("cell-winning");
+ for (Button[] row : cells) {
+ for (Button cell : row) {
+ cell.setGraphic(null);
+ cell.setDisable(false);
+ cell.getStyleClass().remove("cell-winning");
}
}
modalOverlay.setVisible(false);
+
+ if (currentMediaPlayer != null) {
+ currentMediaPlayer.stop();
+ currentMediaPlayer.dispose();
+ currentMediaPlayer = null;
+ }
+
+ victoryVideo.setVisible(false);
+ victoryVideo.setMediaPlayer(null);
+
updateTurnIndicator();
enableBoard();
}
diff --git a/src/main/resources/assets/videos/handshake.gif b/src/main/resources/assets/videos/handshake.gif
new file mode 100644
index 0000000..7322328
Binary files /dev/null and b/src/main/resources/assets/videos/handshake.gif differ
diff --git a/src/main/resources/assets/videos/loser.mp4 b/src/main/resources/assets/videos/loser.mp4
new file mode 100644
index 0000000..0a5f0de
Binary files /dev/null and b/src/main/resources/assets/videos/loser.mp4 differ
diff --git a/src/main/resources/css/features/game_screen.css b/src/main/resources/css/features/game_screen.css
index 49988c7..6277da4 100644
--- a/src/main/resources/css/features/game_screen.css
+++ b/src/main/resources/css/features/game_screen.css
@@ -235,8 +235,8 @@
}
.trophy-container {
- -fx-background-color: -surface-darker;
- -fx-background-radius: 50%;
+ -fx-background-color: transparent;
+ -fx-background-radius: 0;
-fx-padding: 16;
-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, 0.3), 10, 0, 0, 4);
}
diff --git a/src/main/resources/fxml/game_screen.fxml b/src/main/resources/fxml/game_screen.fxml
index c87eb8d..c03b74b 100644
--- a/src/main/resources/fxml/game_screen.fxml
+++ b/src/main/resources/fxml/game_screen.fxml
@@ -41,8 +41,6 @@
-
-
-
-
-