diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java index e6c5c7855b8a941be9e9b94575441de53b99ba36..272c52512ac6e503de2371e21119a018c7cd5bd6 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/GameBlock.java @@ -4,6 +4,7 @@ import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.value.ObservableValue; import javafx.scene.canvas.Canvas; +import javafx.scene.effect.BlendMode; import javafx.scene.paint.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -119,14 +120,17 @@ public class GameBlock extends Canvas { var gc = getGraphicsContext2D(); //Clear - gc.clearRect(0,0,width,height); + gc.clearRect(0.0D, 0.0D, this.width, this.height); //Fill - gc.setFill(Color.WHITE); - gc.fillRect(0,0, width, height); + Color gradStart = Color.color(0.0D, 0.0D, 0.6D, 0.3D); + Color gradEnd = Color.color(0.0D, 0.0D, 0.2D, 0.5D); + gc.setFill(new LinearGradient(0.0D, 0.0D, 1.0D, 1.0D, true, CycleMethod.REFLECT, new Stop(0.0D, gradStart), new Stop(1.0D, gradEnd))); + gc.fillRect(0.0D, 0.0D, this.width, this.height); //Border - gc.setStroke(Color.BLACK); + gc.setStroke(Color.WHITE); + gc.setGlobalAlpha(0.7); gc.strokeRect(0,0,width,height); } @@ -142,6 +146,7 @@ public class GameBlock extends Canvas { //Colour fill gc.setFill(colour); + gc.setGlobalAlpha(1); gc.fillRect(0,0, width, height); //Border diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java new file mode 100644 index 0000000000000000000000000000000000000000..c2d35fd34beeccee411ac277c9a55fc9069c180a --- /dev/null +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/component/PieceBoard.java @@ -0,0 +1,16 @@ +package uk.ac.soton.comp1206.component; + +import uk.ac.soton.comp1206.game.GamePiece; + +public class PieceBoard extends GameBoard { + + private GamePiece pieceToDisplay; + + public PieceBoard(double width, double height) { + super(3, 3, width, height); + } + + public void displayPiece(GamePiece piece) { + this.pieceToDisplay = piece; + } +} diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java index d1dd5e048ac7dc70badbaf2d4357c10c291a246c..af904f43d19766988f4cea34288d1b0582a9e4a7 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Game.java @@ -33,17 +33,13 @@ public class Game { */ protected final Grid grid; - private GamePiece currentPiece; + protected GamePiece currentPiece; + protected GamePiece nextPiece; - private SimpleIntegerProperty score; - - private IntegerProperty level; - - private IntegerProperty lives; - - private IntegerProperty multiplier; - - private final Multimedia multimedia; + private IntegerProperty score = new SimpleIntegerProperty(0); + private IntegerProperty level = new SimpleIntegerProperty(0); + private IntegerProperty lives = new SimpleIntegerProperty(0); + private IntegerProperty multiplier = new SimpleIntegerProperty(0); private int remainder = 0; @@ -56,13 +52,6 @@ public class Game { this.cols = cols; this.rows = rows; - this.score = new SimpleIntegerProperty(0); - this.level = new SimpleIntegerProperty(0); - this.lives = new SimpleIntegerProperty(3); - this.multiplier = new SimpleIntegerProperty(1); - - this.multimedia = new Multimedia(); - //Create a new grid model to represent the game state this.grid = new Grid(cols,rows); } @@ -80,6 +69,14 @@ public class Game { */ public void initialiseGame() { logger.info("Initialising game"); + + this.score.set(0); + this.level.set(0); + this.lives.set(3); + this.multiplier.set(1); + + this.nextPiece = spawnPiece(); + nextPiece(); this.currentPiece = spawnPiece(); } @@ -103,13 +100,19 @@ public class Game { public GamePiece spawnPiece() { Random rand = new Random(); - int value = rand.nextInt(15); - logger.info("Spawning piece of value " + (value + 1)); - return GamePiece.createPiece(value); + GamePiece piece = GamePiece.createPiece(3, rand.nextInt(3)); + logger.info("Spawning piece: {}" , piece); + return piece; } - public void nextPiece() { - this.currentPiece = spawnPiece(); + public GamePiece nextPiece() { + this.currentPiece = this.nextPiece; + this.nextPiece = spawnPiece(); + + logger.info("Current piece is : {}", this.currentPiece); + logger.info("Next piece is: {}", this.nextPiece); + + return this.currentPiece; } public void afterPiece() { @@ -146,7 +149,6 @@ public class Game { } } - int numGridBlocks = 0; /** @@ -177,7 +179,6 @@ public class Game { int newScore = score.get() + (fullCols.size() + fullRows.size()) * numGridBlocks * 10 * multiplier.get(); this.setScore(newScore); int newRemainder = score.get() % 1000; - System.out.println("newRemainder = " + newRemainder + " remainder = " + remainder); if (newRemainder < remainder) { this.setLevel(level.get() + 1); remainder = 0; @@ -187,7 +188,7 @@ public class Game { if (fullCols.size() != 0 || fullRows.size() != 0) { logger.info("Removing rows/columns"); - multimedia.playSound("clear.wav"); + Multimedia.playSound("clear.wav"); this.setMultiplier(multiplier.get() + 1); } else { this.setMultiplier(1); @@ -241,7 +242,7 @@ public class Game { public void setLevel(int level) { logger.info("Increasing level to " + level); - multimedia.playSound("level.wav"); + Multimedia.playSound("level.wav"); this.level.set(level); } diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/GamePiece.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/GamePiece.java index 763897a874d4bbb1ebd12165e7fb4100ff6206b9..761666e36322daf3ae4f76b08f8ac5819f30630b 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/GamePiece.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/GamePiece.java @@ -28,6 +28,7 @@ public class GamePiece { */ private final String name; + /** * Create a new GamePiece of the specified piece number * @param piece piece number diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java index fc583daf8327a40983f1a56017a2819af0c20c14..7905236966906c866d7b7a80091eaa2baa898609 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/game/Grid.java @@ -35,8 +35,6 @@ public class Grid { */ private final SimpleIntegerProperty[][] grid; - private final Multimedia multimedia; - /** * Create a new Grid with the specified number of columns and rows and initialise them * @param cols number of columns @@ -49,8 +47,6 @@ public class Grid { //Create the grid itself grid = new SimpleIntegerProperty[cols][rows]; - this.multimedia = new Multimedia(); - //Add a SimpleIntegerProperty to every block in the grid for(var y = 0; y < rows; y++) { for(var x = 0; x < cols; x++) { @@ -106,7 +102,7 @@ public class Grid { if (value == 0) continue; if (get(x + placeX, y + placeY) != 0) { logger.info("Cannot place piece here"); - multimedia.playSound("fail.wav"); + Multimedia.playSound("fail.wav"); return false; } } @@ -118,7 +114,7 @@ public class Grid { if (!this.canPlayPiece(gamePiece, placeX, placeY)) return false; logger.info("Placing block at x:{} y:{}",placeX,placeY); - multimedia.playSound("place.wav"); + Multimedia.playSound("place.wav"); int[][] blocks = gamePiece.getBlocks(); placeX = placeX - 1; placeY = placeY - 1; diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java index 82798501e82fd54e0454e1f373e83f2e5c444d11..b5fbf9609d5a9633d074bac1042d3971476f5bf4 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/ChallengeScene.java @@ -1,19 +1,26 @@ package uk.ac.soton.comp1206.scene; import javafx.beans.property.Property; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.layout.*; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; import javafx.scene.text.Text; import javafx.util.converter.NumberStringConverter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import uk.ac.soton.comp1206.component.GameBlock; import uk.ac.soton.comp1206.component.GameBoard; +import uk.ac.soton.comp1206.component.PieceBoard; import uk.ac.soton.comp1206.game.Game; import uk.ac.soton.comp1206.ui.GamePane; import uk.ac.soton.comp1206.ui.GameWindow; import uk.ac.soton.comp1206.utility.Multimedia; +import java.util.ArrayList; + /** * The Single Player challenge scene. Holds the UI for the single player challenge mode in the game. */ @@ -22,8 +29,6 @@ public class ChallengeScene extends BaseScene { private static final Logger logger = LogManager.getLogger(MenuScene.class); protected Game game; - private Multimedia multimedia; - /** * Create a new Single Player challenge scene * @param gameWindow the Game Window @@ -44,7 +49,8 @@ public class ChallengeScene extends BaseScene { root = new GamePane(gameWindow.getWidth(),gameWindow.getHeight()); - var challengePane = new StackPane(); + StackPane challengePane = new StackPane(); + challengePane.setBackground(new Background(new BackgroundFill[] { new BackgroundFill((Paint) Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY) })); challengePane.setMaxWidth(gameWindow.getWidth()); challengePane.setMaxHeight(gameWindow.getHeight()); challengePane.getStyleClass().add("menu-background"); @@ -53,36 +59,41 @@ public class ChallengeScene extends BaseScene { var mainPane = new BorderPane(); challengePane.getChildren().add(mainPane); - var board = new GameBoard(game.getGrid(),gameWindow.getWidth()/2,gameWindow.getWidth()/2); - mainPane.setCenter(board); + //Header of Challenge Scene + HBox header = buildHeader(); + + mainPane.setTop(header); + + HBox boards = buildBoards(); + + mainPane.setCenter(boards); + } + + public HBox buildHeader() { + //Header of Challenge Scene HBox header = new HBox(); + //VBox to hold the Score title and value VBox scoreBox = new VBox(); var scoreTitle = new Text("Score"); scoreTitle.getStyleClass().add("heading"); var scoreValue = new Text(); - scoreValue.textProperty().bindBidirectional(game.getScore(), new NumberStringConverter()); + scoreValue.textProperty().bind(game.getScore().asString()); scoreValue.getStyleClass().add("score"); scoreBox.getChildren().addAll(scoreTitle,scoreValue); scoreBox.setAlignment(Pos.BASELINE_CENTER); header.getChildren().add(scoreBox); - Region space = new Region(); - space.setMaxWidth(140); - HBox.setHgrow(space,Priority.ALWAYS); - header.getChildren().add(space); - var challengeTitle = new Text("Challenge Scene"); + //Challenge scene title + var challengeTitle = new Text("Challenge Mode"); challengeTitle.getStyleClass().add("title"); header.getChildren().add(challengeTitle); - Region space2 = new Region(); - space2.setMaxWidth(140); - HBox.setHgrow(space2,Priority.ALWAYS); - header.getChildren().add(space2); + //VBox to store lives title and value VBox livesBox = new VBox(); var livesTitle = new Text("Lives"); livesTitle.getStyleClass().add("heading"); @@ -93,12 +104,60 @@ public class ChallengeScene extends BaseScene { livesBox.setAlignment(Pos.BASELINE_CENTER); header.getChildren().add(livesBox); + header.setAlignment(Pos.CENTER); + header.setSpacing(140); - mainPane.setTop(header); + return header; + } + + public HBox buildBoards() { + HBox boards = new HBox(); + var board = new GameBoard(game.getGrid(),gameWindow.getWidth()/2,gameWindow.getWidth()/2); //Handle block on gameboard grid being clicked board.setOnBlockClick(this::blockClicked); + + boards.getChildren().add(board); + + VBox gameInfo = new VBox(); + + var hiScoreTitle = new Text("High Score"); + hiScoreTitle.getStyleClass().add("heading"); + gameInfo.getChildren().add(hiScoreTitle); + + var hiScoreVal = new Text("10000"); + hiScoreVal.getStyleClass().add("hiscore"); + gameInfo.getChildren().add(hiScoreVal); + + var levelTitle = new Text("Level"); + levelTitle.getStyleClass().add("heading"); + gameInfo.getChildren().add(levelTitle); + + var levelVal = new Text(); + levelVal.textProperty().bind(game.getLevel().asString()); + levelVal.getStyleClass().add("level"); + gameInfo.getChildren().add(levelVal); + + var incomingTitle = new Text("Incoming"); + incomingTitle.getStyleClass().add("heading"); + gameInfo.getChildren().add(incomingTitle); + + PieceBoard currentPieceBoard = new PieceBoard(gameWindow.getWidth()/6, gameWindow.getWidth()/6); + gameInfo.getChildren().add(currentPieceBoard); + + PieceBoard nextPieceBoard = new PieceBoard(gameWindow.getWidth()/10, gameWindow.getWidth()/10); + gameInfo.getChildren().add(nextPieceBoard); + + gameInfo.setAlignment(Pos.CENTER); + gameInfo.setSpacing(10); + + boards.getChildren().add(gameInfo); + + boards.setAlignment(Pos.CENTER); + boards.setSpacing(100); + + return boards; } /** @@ -109,14 +168,14 @@ public class ChallengeScene extends BaseScene { game.blockClicked(gameBlock); } + /** * Setup the game object and model */ public void setupGame() { logger.info("Starting a new challenge"); - multimedia = new Multimedia(); - multimedia.playBackgroundMusic("game_start.wav", false); - Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> multimedia.playBackgroundMusic("game.wav", true)); + Multimedia.playBackgroundMusic("game_start.wav", false); + Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> Multimedia.playBackgroundMusic("game.wav", true)); //Start new game game = new Game(5, 5); } diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/MenuScene.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/MenuScene.java index 7d65d35660b97149582942ac42abe18123a21f36..82084aaab7fd8b26cd25dc49e8694052fec131c2 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/MenuScene.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/scene/MenuScene.java @@ -19,8 +19,6 @@ public class MenuScene extends BaseScene { private static final Logger logger = LogManager.getLogger(MenuScene.class); - private Multimedia multimedia; - /** * Create a new menu scene * @param gameWindow the Game Window this will be displayed in @@ -73,9 +71,7 @@ public class MenuScene extends BaseScene { mainPane.setTop(menuWidgets); mainPane.setCenter(menuButtons); - multimedia = new Multimedia(); - multimedia.playBackgroundMusic("menu.mp3", true); - + Multimedia.playBackgroundMusic("menu.mp3", true); } /** @@ -91,7 +87,7 @@ public class MenuScene extends BaseScene { * @param event event */ private void startGame(MouseEvent event) { - multimedia.stopSound(); + Multimedia.stopSound(); gameWindow.startChallenge(); } diff --git a/tetrecs/src/main/java/uk/ac/soton/comp1206/utility/Multimedia.java b/tetrecs/src/main/java/uk/ac/soton/comp1206/utility/Multimedia.java index 7019bc04ec58700f3faee201ebe80de62be3b62d..ad81aba6f1d8c98ab51cf316d00e62ce29282d0c 100644 --- a/tetrecs/src/main/java/uk/ac/soton/comp1206/utility/Multimedia.java +++ b/tetrecs/src/main/java/uk/ac/soton/comp1206/utility/Multimedia.java @@ -13,7 +13,7 @@ public class Multimedia { private static MediaPlayer mediaPlayer; private static MediaPlayer backgroundPlayer; - public void playBackgroundMusic(String music, boolean toLoop) { + public static void playBackgroundMusic(String music, boolean toLoop) { String toPlay = Multimedia.class.getResource("/music/" + music).toExternalForm(); try{ Media play = new Media(toPlay); @@ -30,7 +30,7 @@ public class Multimedia { } } - public void playSound(String sound) { + public static void playSound(String sound) { String toPlay = Multimedia.class.getResource("/sounds/" + sound).toExternalForm(); try{ @@ -45,8 +45,13 @@ public class Multimedia { } } - public void stopSound() { - backgroundPlayer.stop(); + public static void stopSound() { + if (mediaPlayer != null) { + mediaPlayer.stop(); + } + if (backgroundPlayer != null) { + backgroundPlayer.stop(); + } } public static MediaPlayer getBackgroundPlayer() { diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBlock.class b/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBlock.class index 7c9c377343b37d114af6e8c5f0f596739e75fa20..191944d061dfb8e127c3714cc9e7ba0b0dea72d2 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBlock.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/component/GameBlock.class differ diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class index 7e03052f6beac83c683a6cc7985ca105d8c325b4..54142e5420e92cd5cec8ffadb11a9b80935bf8b5 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Game.class differ diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/game/GamePiece.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/GamePiece.class index 8590c34d155c9dc7b40da0d08787509f20795464..ddf9544daf0af815a0ae54f0b67fcb34868d21c6 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/game/GamePiece.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/game/GamePiece.class differ diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class index 2db3128f7f1a99970c6eb3b5f28bc952ebf73173..002e059f2affcc6dc3522671f50858fd1a9f5865 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class differ diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class index d3b846bf114e63d4cac1d643ca442a651e0a42dc..db3f11b372bf64a21aa8eddfd74d0f4317da0970 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/ChallengeScene.class differ diff --git a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/MenuScene.class b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/MenuScene.class index 71d171fc0b09428b00659938d81a5d448b8b49c5..ab27c55069861c8e139ae82305e1f07cad2366a0 100644 Binary files a/tetrecs/target/classes/uk/ac/soton/comp1206/scene/MenuScene.class and b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/MenuScene.class differ