diff --git a/tetrecs/.idea/checkstyle-idea.xml b/tetrecs/.idea/checkstyle-idea.xml new file mode 100644 index 0000000000000000000000000000000000000000..25a0edc662facbb5978fee6ed47c36be9559fa70 --- /dev/null +++ b/tetrecs/.idea/checkstyle-idea.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CheckStyle-IDEA"> + <option name="configuration"> + <map> + <entry key="checkstyle-version" value="9.2.1" /> + <entry key="copy-libs" value="true" /> + <entry key="location-0" value="BUNDLED:(bundled):Sun Checks" /> + <entry key="location-1" value="BUNDLED:(bundled):Google Checks" /> + <entry key="scan-before-checkin" value="false" /> + <entry key="scanscope" value="JavaOnly" /> + <entry key="suppress-errors" value="false" /> + </map> + </option> + </component> +</project> \ No newline at end of file diff --git a/tetrecs/.idea/google-java-format.xml b/tetrecs/.idea/google-java-format.xml new file mode 100644 index 0000000000000000000000000000000000000000..2aa056da349dddd834c2c648fc49c936f390dbfc --- /dev/null +++ b/tetrecs/.idea/google-java-format.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="GoogleJavaFormatSettings"> + <option name="enabled" value="false" /> + </component> +</project> \ No newline at end of file diff --git a/tetrecs/.idea/tetrecs.iml b/tetrecs/.idea/tetrecs.iml new file mode 100644 index 0000000000000000000000000000000000000000..4a4ce55406053014eaaca4546111548f263f24ed --- /dev/null +++ b/tetrecs/.idea/tetrecs.iml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module version="4"> + <component name="CheckStyle-IDEA-Module"> + <option name="configuration"> + <map /> + </option> + </component> +</module> \ No newline at end of file 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 a379daf1a0dcafbc1b076de28dac837dbf0d6d46..21b1fb6ea412bdc595549daac0ea208bf428c3a2 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 @@ -4,6 +4,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import uk.ac.soton.comp1206.component.GameBlock; +import java.util.ArrayList; +import java.util.Random; + /** * The Game class handles the main logic, state and properties of the TetrECS game. Methods to manipulate the game state * and to handle actions made by the player should take place inside this class. @@ -27,6 +30,8 @@ public class Game { */ protected final Grid grid; + private GamePiece currentPiece; + /** * Create a new game with the specified rows and columns. Creates a corresponding grid model. * @param cols number of columns @@ -53,6 +58,7 @@ public class Game { */ public void initialiseGame() { logger.info("Initialising game"); + this.currentPiece = spawnPiece(); } /** @@ -65,14 +71,80 @@ public class Game { int y = gameBlock.getY(); //Get the new value for this block - int previousValue = grid.get(x,y); - int newValue = previousValue + 1; - if (newValue > GamePiece.PIECES) { - newValue = 0; + logger.info("Block clicked at x = {} y = {}",x,y); + boolean placed = grid.playPiece(currentPiece, x, y); + if (placed) { + this.afterPiece(); + this.nextPiece(); + } + } + + public GamePiece spawnPiece() { + Random rand = new Random(); + int value = rand.nextInt(15); + logger.info("Spawning piece of value " + (value + 1)); + return GamePiece.createPiece(14); + } + + public void nextPiece() { + this.currentPiece = spawnPiece(); + } + + public void afterPiece() { + ArrayList<Integer> fullCols = new ArrayList<>(); + ArrayList<Integer> fullRows = new ArrayList<>(); + + /** + * Check each vertical column to see if it is full + */ + for (int x = 0; x < grid.getCols(); x++) { + boolean full = true; + for (int y = 0; y < grid.getRows(); y++) { + if (grid.get(x,y) == 0) { + full = false; + } + } + if (full) { + fullCols.add(x); + } + } + + /** + * Check each horizontal row to see if it is full + */ + for (int y = 0; y < grid.getCols(); y++) { + boolean full = true; + for (int x = 0; x < grid.getRows(); x++) { + if (grid.get(x,y) == 0) { + full = false; + } + } + if (full) { + fullRows.add(y); + } + } + + if (fullCols.size() != 0 || fullRows.size() != 0) { + logger.info("Removing rows/columns"); + } + + /** + * Removes all columns which are full + */ + for (int x : fullCols) { + for (int y = 0; y < grid.getCols(); y++) { + grid.set(x,y,0); + } } - //Update the grid with the new value - grid.set(x,y,newValue); + /** + * Removes all rows which are full + */ + for (int y : fullRows) { + for (int x = 0; x < grid.getCols(); x++) { + grid.set(x,y,0); + } + } } /** 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 4924c99d923f528782dcc4d38610a61322aefe74..e876bee020bb5ab0ea1da0be3f759e7f023d390b 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 @@ -2,6 +2,9 @@ package uk.ac.soton.comp1206.game; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import uk.ac.soton.comp1206.App; /** * The Grid is a model which holds the state of a game board. It is made up of a set of Integer values arranged in a 2D @@ -15,7 +18,7 @@ import javafx.beans.property.SimpleIntegerProperty; * The Grid should be linked to a GameBoard for it's display. */ public class Grid { - + private static final Logger logger = LogManager.getLogger(App.class); /** * The number of columns in this grid */ @@ -87,6 +90,42 @@ public class Grid { } } + public boolean canPlayPiece(GamePiece gamePiece, int placeX, int placeY) { + int[][] blocks = gamePiece.getBlocks(); + placeX = placeX - 1; + placeY = placeY - 1; + + for (int x = 0; x < blocks.length; x++) { + for (int y = 0; y < blocks[x].length; y++) { + int value = blocks[x][y]; + if (value == 0) continue; + if (get(x + placeX, y + placeY) != 0) { + logger.info("Cannot place piece here"); + return false; + } + } + } + return true; + } + + public boolean playPiece(GamePiece gamePiece, int placeX, int placeY) { + if (!this.canPlayPiece(gamePiece, placeX, placeY)) return false; + + logger.info("Placing block at x:{} y:{}",placeX,placeY); + int[][] blocks = gamePiece.getBlocks(); + placeX = placeX - 1; + placeY = placeY - 1; + + for (int x = 0; x < blocks.length; x++) { + for (int y = 0; y < blocks[x].length; y++) { + int value = blocks[x][y]; + if (value == 0) continue; + set(x + placeX, y + placeY, value); + } + } + return true; + } + /** * Get the number of columns in this game * @return number of columns 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 4bcc9d8076ce1adb2d0b91afee552df92c4ae5a1..433d719adf0aa9ad885e8a9abbff05daa204bdb9 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 @@ -1,7 +1,8 @@ package uk.ac.soton.comp1206.scene; -import javafx.event.ActionEvent; +import javafx.geometry.Pos; import javafx.scene.control.Button; +import javafx.scene.input.MouseEvent; import javafx.scene.layout.*; import javafx.scene.text.Text; import org.apache.logging.log4j.LogManager; @@ -43,17 +44,27 @@ public class MenuScene extends BaseScene { var mainPane = new BorderPane(); menuPane.getChildren().add(mainPane); + VBox menuWidgets = new VBox(); + //Awful title var title = new Text("TetrECS"); title.getStyleClass().add("title"); - mainPane.setTop(title); + menuWidgets.getChildren().add(title); + + VBox menuButtons = new VBox(); + + var singlePlay = new Text("Single Player"); + singlePlay.getStyleClass().add("menuItem"); + singlePlay.setOnMouseClicked(this::startGame); + menuButtons.getChildren().add(singlePlay); + + + menuButtons.setAlignment(Pos.CENTER); + menuWidgets.setAlignment(Pos.TOP_CENTER); - //For now, let us just add a button that starts the game. I'm sure you'll do something way better. - var button = new Button("Play"); - mainPane.setCenter(button); + mainPane.setTop(menuWidgets); + mainPane.setCenter(menuButtons); - //Bind the button action to the startGame method in the menu - button.setOnAction(this::startGame); } /** @@ -68,7 +79,7 @@ public class MenuScene extends BaseScene { * Handle when the Start Game button is pressed * @param event event */ - private void startGame(ActionEvent event) { + private void startGame(MouseEvent event) { gameWindow.startChallenge(); } diff --git a/tetrecs/src/main/resources/style/game.css b/tetrecs/src/main/resources/style/game.css index 2b77c42f98257cac0becaa2d4a7b619953b14647..df6fa61442ab1589ac24570a3cd468d9301a6e33 100644 --- a/tetrecs/src/main/resources/style/game.css +++ b/tetrecs/src/main/resources/style/game.css @@ -58,6 +58,7 @@ -fx-effect: dropshadow(gaussian, black, 1, 1.0, 1, 1); } + .heading { -fx-fill: white; -fx-font-family: 'Orbitron'; diff --git a/tetrecs/target/classes/module-info.class b/tetrecs/target/classes/module-info.class index 169423cbd32058f54488d9da3774220e62112626..b6eb5d5dc3206e20460f1afbfd5d3d22095a88f2 100644 Binary files a/tetrecs/target/classes/module-info.class and b/tetrecs/target/classes/module-info.class differ diff --git a/tetrecs/target/classes/style/game.css b/tetrecs/target/classes/style/game.css index 2b77c42f98257cac0becaa2d4a7b619953b14647..df6fa61442ab1589ac24570a3cd468d9301a6e33 100644 --- a/tetrecs/target/classes/style/game.css +++ b/tetrecs/target/classes/style/game.css @@ -58,6 +58,7 @@ -fx-effect: dropshadow(gaussian, black, 1, 1.0, 1, 1); } + .heading { -fx-fill: white; -fx-font-family: 'Orbitron'; 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 502eb787ba62b881f08c8284cd207fea113cba2b..be32772624ed05d9eb70fad41f3f0732615e7bea 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/Grid.class b/tetrecs/target/classes/uk/ac/soton/comp1206/game/Grid.class index 5d628c07162ffec1d8f0e9bb2ab0da9bb901d404..2db3128f7f1a99970c6eb3b5f28bc952ebf73173 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/MenuScene.class b/tetrecs/target/classes/uk/ac/soton/comp1206/scene/MenuScene.class index 9d27b9d5339524e9e9c2a3752f5b47e21b3e63dd..b58df00055fca0f690452354818862658dbb1c86 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