diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBlock.java b/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBlock.java index 33b318b..4b347d7 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBlock.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBlock.java @@ -1,5 +1,6 @@ package uk.mgrove.ac.soton.comp1206.component; +import javafx.animation.AnimationTimer; import javafx.beans.property.IntegerProperty; import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.value.ObservableValue; @@ -63,6 +64,16 @@ public class GameBlock extends Canvas { */ private final IntegerProperty value = new SimpleIntegerProperty(0); + /** + * Whether the block should appear as focussed + */ + private boolean isFocussed = false; + + /** + * Whether indicator should be shown in the middle of the block + */ + private boolean showMiddleIndicator = false; + /** * Create a new single Game Block * @param gameBoard the board this block belongs to @@ -110,12 +121,18 @@ public class GameBlock extends Canvas { //If the block is not empty, paint with the colour represented by the value paintColor(COLOURS[value.get()]); } + // paint focus overlay if required + if (isFocussed) paintFocusOverlay(); + + // paint middle indicator if required + if (showMiddleIndicator) paintMiddleIndicator(); } /** * Paint this canvas empty */ private void paintEmpty() { + logger.info("Painting empty block at x: {}, y: {}", getX(), getY()); var gc = getGraphicsContext2D(); //Clear @@ -132,23 +149,111 @@ public class GameBlock extends Canvas { /** * Paint this canvas with the given colour - * @param colour the colour to paint + * @param color the colour to paint */ - private void paintColor(Paint colour) { + private void paintColor(Color color) { + logger.info("Painting color block at x: {}, y: {}", getX(), getY()); var gc = getGraphicsContext2D(); //Clear gc.clearRect(0,0,width,height); //Colour fill - gc.setFill(colour); + gc.setFill(color); gc.fillRect(0,0, width, height); + gc.setFill(color.deriveColor(0,1,0.8,1)); + gc.fillPolygon(new double[]{ + width, + width, + 0.0 + }, new double[]{ + 0, + height, + 0 + }, 3 + ); //Border gc.setStroke(Color.GRAY); gc.strokeRect(0,0,width,height); } + /** + * Paint indicator in middle of block + */ + private void paintMiddleIndicator() { + logger.info("Painting indicator on block at x: {}, y: {}", getX(), getY()); + + var gc = getGraphicsContext2D(); + gc.setFill(Color.WHITE.deriveColor(0,1,1,0.7)); + gc.fillOval(width/4, height/4, width/2, height/2); + } + + /** + * Paint overlay to indicate focus + */ + private void paintFocusOverlay() { + logger.info("Painting focus overlay on block at x: {}, y: {}", getX(), getY()); + + var gc = getGraphicsContext2D(); + gc.setFill(Color.WHITE.deriveColor(0,1,1,0.5)); + gc.fillRect(0,0,width,height); + } + + /** + * Set whether the block should appear as focussed + * @param value whether block should appear as focussed + */ + public void setFocussed(boolean value) { + logger.info("Block at x: {}, y: {} has been set to focus: {}", getX(), getY(), value); + isFocussed = value; + // TODO: add/remove overlay + paint(); + } + + /** + * Set whether an indicator should be shown in the middle of the block + * @param value whether indicator should be shown + */ + public void showMiddleIndicator(boolean value) { + logger.info("Setting middle indicator on block at x: {}, y: {} to: {}", getX(), getY(), value); + showMiddleIndicator = value; + paint(); + } + + /** + * Fade out block + */ + public void fadeOut() { + logger.info("Fading out block at x: {}, y: {}", getX(), getY()); + + AnimationTimer timer = new AnimationTimer() { + Color color = COLOURS[getValue()]; + int iterations = 0; + @Override + public void handle(long now) { + if (iterations < 12) { + color = color.deriveColor(0,1,1.2,1); + paintColor(color); + logger.info("New color brightness is {}", color.getBrightness()); + if (isFocussed) paintFocusOverlay(); + } else if (color.getOpacity() > 0.1) { + color = color.deriveColor(0,1,1,0.95); + paintColor(color); + logger.info("New color opacity is {}", color.getOpacity()); + if (isFocussed) paintFocusOverlay(); + } else { + paintEmpty(); + if (isFocussed) paintFocusOverlay(); + logger.info("Stopping timer at x: {}, y: {}", getX(), getY()); + stop(); + } + iterations++; + } + }; + timer.start(); + } + /** * Get the column of this block * @return column number diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBoard.java b/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBoard.java index 2ed9c35..81608ca 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBoard.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/component/GameBoard.java @@ -1,11 +1,16 @@ package uk.mgrove.ac.soton.comp1206.component; +import javafx.scene.input.MouseButton; import javafx.scene.input.MouseEvent; import javafx.scene.layout.GridPane; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import uk.mgrove.ac.soton.comp1206.event.BlockClickedListener; +import uk.mgrove.ac.soton.comp1206.event.MouseClickListener; import uk.mgrove.ac.soton.comp1206.game.Grid; +import uk.mgrove.ac.soton.comp1206.util.Multimedia; + +import java.util.Set; /** * A GameBoard is a visual component to represent the visual GameBoard. @@ -56,6 +61,25 @@ public class GameBoard extends GridPane { */ private BlockClickedListener blockClickedListener; + /** + * Listener to call when board is right-clicked + */ + protected MouseClickListener rightClickListener; + + /** + * Listener for board being left-clicked + */ + protected MouseClickListener leftClickListener; + + /** + * Currently focussed game block + */ + private GameBlock focussedBlock; + + /** + * Whether focus overlays should be shown + */ + protected boolean enableFocus = true; /** * Create a new GameBoard, based off a given grid, with a visual width and height. @@ -122,6 +146,15 @@ public class GameBoard extends GridPane { createBlock(x,y); } } + + setOnMouseClicked((event) -> { + logger.debug("Mouse button clicked: {}", event.getButton()); + if (event.getButton().equals(MouseButton.SECONDARY) && rightClickListener != null) { + rightClickListener.action(); + } else if (event.getButton().equals(MouseButton.PRIMARY) && leftClickListener != null) { + leftClickListener.action(); + } + }); } /** @@ -130,6 +163,7 @@ public class GameBoard extends GridPane { * @param y row */ protected GameBlock createBlock(int x, int y) { + logger.info("Creating new block at x: {}, y: {}", x, y); var blockWidth = width / cols; var blockHeight = height / rows; @@ -146,7 +180,12 @@ public class GameBoard extends GridPane { block.bind(grid.getGridProperty(x,y)); //Add a mouse click handler to the block to trigger GameBoard blockClicked method - block.setOnMouseClicked((e) -> blockClicked(e, block)); + block.setOnMouseClicked((e) -> { + if (e.getButton().equals(MouseButton.PRIMARY)) blockClicked(e, block); + }); + block.hoverProperty().addListener(((observable, oldValue, newValue) -> { + if (newValue) blockHovered(block); + })); return block; } @@ -172,4 +211,71 @@ public class GameBoard extends GridPane { } } + public void blockHovered(GameBlock gameBlock) { + if (enableFocus) { + logger.info("Block hovered: {}", gameBlock); + if (focussedBlock != null) focussedBlock.setFocussed(false); + focussedBlock = gameBlock; + focussedBlock.setFocussed(true); + } + } + + /** + * Change current x-coordinate focus by given amount + * @param amount amount to change by + */ + public void changeXFocus(int amount) { + logger.info("Change of {} requested to x-coordinate of focussed block", amount); + if (focussedBlock == null) blockHovered(getBlock(0,0)); + else if (focussedBlock.getX() + amount >= 0 && focussedBlock.getX() + amount < cols) blockHovered(getBlock(focussedBlock.getX() + amount, focussedBlock.getY())); + else Multimedia.playAudio("sounds/fail.wav"); + } + + /** + * Change current y-coordinate focus by given amount + * @param amount amount to change by + */ + public void changeYFocus(int amount) { + logger.info("Change of {} requested to y-coordinate of focussed block", amount); + if (focussedBlock == null) blockHovered(getBlock(0,0)); + else if (focussedBlock.getY() + amount >= 0 && focussedBlock.getY() + amount < rows) blockHovered(getBlock(focussedBlock.getX(), focussedBlock.getY() + amount)); + else Multimedia.playAudio("sounds/fail.wav"); + } + + /** + * Fade out all blocks located at a set of coordinates + * @param blockCoordinates block coordinates + */ + public void fadeOut(Set blockCoordinates) { + for (var block : blockCoordinates) { + getBlock(block.getX(), block.getY()).fadeOut(); + } + } + + /** + * Get the x-coordinate of the currently-focussed block + * @return x-coordinate of block + */ + public int getXFocus() { + if (focussedBlock != null) return focussedBlock.getX(); + else return 0; + } + + /** + * Get the y-coordinate of the currently-focussed block + * @return y-coordinate of block + */ + public int getYFocus() { + if (focussedBlock != null) return focussedBlock.getY(); + else return 0; + } + + public void setOnRightClicked(MouseClickListener listener) { + rightClickListener = listener; + } + + public void setOnLeftClicked(MouseClickListener listener) { + leftClickListener = listener; + } + } diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/component/PieceBoard.java b/src/main/java/uk/mgrove/ac/soton/comp1206/component/PieceBoard.java index 7cc584e..1eb25f0 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/component/PieceBoard.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/component/PieceBoard.java @@ -1,12 +1,18 @@ package uk.mgrove.ac.soton.comp1206.component; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import uk.mgrove.ac.soton.comp1206.game.GamePiece; -import uk.mgrove.ac.soton.comp1206.game.Grid; public class PieceBoard extends GameBoard { /** - * Create a new GameBoard with it's own internal grid, specifying the number of columns and rows, along with the + * Logger + */ + private static final Logger logger = LogManager.getLogger(PieceBoard.class); + + /** + * Create a new GameBoard with its own internal grid, specifying the number of columns and rows, along with the * visual width and height. * * @param width the visual width @@ -14,11 +20,21 @@ public class PieceBoard extends GameBoard { */ public PieceBoard(double width, double height) { super(3, 3, width, height); + enableFocus = false; } public void displayPiece(GamePiece piece) { + logger.info("Displaying new piece: {}", piece.toString()); grid.clearGrid(); grid.playPiece(piece,1,1); } + /** + * Set whether an indicator should be shown on the middle block of the grid + * @param value whether indicator should be shown + */ + public void showMiddleIndicator(boolean value) { + getBlock(1,1).showMiddleIndicator(value); + } + } diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/event/LineClearedListener.java b/src/main/java/uk/mgrove/ac/soton/comp1206/event/LineClearedListener.java new file mode 100644 index 0000000..66be8e5 --- /dev/null +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/event/LineClearedListener.java @@ -0,0 +1,11 @@ +package uk.mgrove.ac.soton.comp1206.event; + +import uk.mgrove.ac.soton.comp1206.component.GameBlockCoordinate; + +import java.util.Set; + +public interface LineClearedListener { + + public void clearLine(Set blockCoordinates); + +} diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/event/MouseClickListener.java b/src/main/java/uk/mgrove/ac/soton/comp1206/event/MouseClickListener.java new file mode 100644 index 0000000..0d7ae5e --- /dev/null +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/event/MouseClickListener.java @@ -0,0 +1,13 @@ +package uk.mgrove.ac.soton.comp1206.event; + +/** + * Listener for a node being right-clicked + */ +public interface MouseClickListener { + + /** + * Handle node being right-clicked + */ + public void action(); + +} diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/event/NextPieceListener.java b/src/main/java/uk/mgrove/ac/soton/comp1206/event/NextPieceListener.java index eabed6f..93f5fc4 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/event/NextPieceListener.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/event/NextPieceListener.java @@ -9,7 +9,8 @@ public interface NextPieceListener { /** * Handle a new piece being received by the game - * @param piece the piece that was received + * @param currentPiece the piece that was received + * @param followingPiece the piece that was received for the next iteration */ - public void nextPiece(GamePiece piece); + public void nextPiece(GamePiece currentPiece, GamePiece followingPiece); } \ No newline at end of file diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/game/Game.java b/src/main/java/uk/mgrove/ac/soton/comp1206/game/Game.java index df28c18..29e7ef6 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/game/Game.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/game/Game.java @@ -5,7 +5,10 @@ import javafx.beans.property.SimpleIntegerProperty; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import uk.mgrove.ac.soton.comp1206.component.GameBlock; +import uk.mgrove.ac.soton.comp1206.component.GameBlockCoordinate; +import uk.mgrove.ac.soton.comp1206.event.LineClearedListener; import uk.mgrove.ac.soton.comp1206.event.NextPieceListener; +import uk.mgrove.ac.soton.comp1206.util.Multimedia; import java.util.*; @@ -45,6 +48,11 @@ public class Game { */ private GamePiece currentPiece; + /** + * Next game piece for player to use + */ + private GamePiece followingPiece; + /** * Player's current score */ @@ -67,6 +75,11 @@ public class Game { */ private NextPieceListener nextPieceListener; + /** + * Listener for when lines of blocks are cleared + */ + private LineClearedListener lineClearedListener; + /** * Create a new game with the specified rows and columns. Creates a corresponding grid model. * @param cols number of columns @@ -93,12 +106,24 @@ public class Game { * @return the next piece */ public GamePiece nextPiece() { - currentPiece = spawnPiece(); - if (nextPieceListener != null) nextPieceListener.nextPiece(currentPiece); - logger.info("Next piece is: {}", currentPiece); + currentPiece = followingPiece; + followingPiece = spawnPiece(); + if (nextPieceListener != null) nextPieceListener.nextPiece(currentPiece, followingPiece); + logger.info("Next piece is: {} and following piece is: {}", currentPiece, followingPiece); return currentPiece; } + /** + * Swap the current and next game pieces + */ + public void swapPieces() { + logger.info("Swapping current and next pieces"); + var tmp = currentPiece; + currentPiece = followingPiece; + followingPiece = tmp; + if (nextPieceListener != null) nextPieceListener.nextPiece(currentPiece, followingPiece); + } + /** * Create a new game piece * @return newly created piece @@ -115,6 +140,7 @@ public class Game { */ public void initialiseGame() { logger.info("Initialising game"); + followingPiece = spawnPiece(); nextPiece(); } @@ -127,12 +153,27 @@ public class Game { int x = gameBlock.getX(); int y = gameBlock.getY(); + dropPiece(x,y); + } + + /** + * Play current piece at given coordinates + * @param x x-coordinate + * @param y y-coordinate + */ + public void dropPiece(int x, int y) { if (grid.canPlayPiece(currentPiece,x,y)) { + logger.info("Playing piece at x: {}, y: {}", x, y); grid.playPiece(currentPiece,x,y); afterPiece(); nextPiece(); + + Multimedia.playAudio("sounds/place.wav"); } else { // can't play the piece + logger.info("Couldn't play piece at x: {}, y: {}", x, y); + + Multimedia.playAudio("sounds/fail.wav"); } } @@ -143,20 +184,22 @@ public class Game { logger.info("Checking for columns and rows that need clearing"); Set blocksToRemove = new HashSet<>(); + Set blockCoordinatesToRemove = new HashSet<>(); int linesToRemove = 0; for (var x=0; x < grid.getCols(); x++) { - List columnBlocksToRemove = new ArrayList<>(); + Map columnBlocksToRemove = new HashMap<>(); for (var y=0; y < grid.getRows(); y++) { // if column isn't full then move to next column if (grid.get(x,y) <= 0) break; - columnBlocksToRemove.add(grid.getGridProperty(x,y)); + columnBlocksToRemove.put(new GameBlockCoordinate(x,y), grid.getGridProperty(x,y)); } // if column is full then store blocks to reset if (columnBlocksToRemove.size() == grid.getRows()) { - for (var block : columnBlocksToRemove) { - blocksToRemove.add(block); + for (var coordinates : columnBlocksToRemove.keySet()) { + blocksToRemove.add(columnBlocksToRemove.get(coordinates)); + blockCoordinatesToRemove.add(coordinates); linesToRemove++; } } @@ -164,22 +207,28 @@ public class Game { // do the same for rows for (var y=0; y < grid.getRows(); y++) { - List rowBlocksToRemove = new ArrayList<>(); + Map rowBlocksToRemove = new HashMap<>(); for (var x=0; x < grid.getCols(); x++) { // if row isn't full then move to next row if (grid.get(x,y) <= 0) break; - rowBlocksToRemove.add(grid.getGridProperty(x,y)); + rowBlocksToRemove.put(new GameBlockCoordinate(x,y), grid.getGridProperty(x,y)); } // if row is full then store blocks to reset if (rowBlocksToRemove.size() == grid.getCols()) { - for (var block : rowBlocksToRemove) { - blocksToRemove.add(block); + for (var coordinates : rowBlocksToRemove.keySet()) { + blocksToRemove.add(rowBlocksToRemove.get(coordinates)); + blockCoordinatesToRemove.add(coordinates); linesToRemove++; } } } + if (linesToRemove > 0) { + Multimedia.playAudio("sounds/clear.wav"); + if (lineClearedListener != null) lineClearedListener.clearLine(blockCoordinatesToRemove); + } + // update score and multiplier score(linesToRemove,blocksToRemove.size()); @@ -209,6 +258,28 @@ public class Game { level.set((int) Math.floor((double) score.get() / 1000)); } + /** + * Rotate the current piece clockwise + */ + public void rotateCurrentPiece() { + logger.info("Rotating current piece clockwise"); + currentPiece.rotate(); + Multimedia.playAudio("sounds/rotate.wav"); + + if (nextPieceListener != null) nextPieceListener.nextPiece(currentPiece, followingPiece); + } + + /** + * Rotate the current piece anticlockwise + */ + public void rotateCurrentPieceAnticlockwise() { + logger.info("Rotating current piece anticlockwise"); + currentPiece.rotate(3); + Multimedia.playAudio("sounds/rotate.wav"); + + if (nextPieceListener != null) nextPieceListener.nextPiece(currentPiece, followingPiece); + } + /** * Get the grid model inside this game representing the game state of the board * @return game grid model @@ -333,4 +404,12 @@ public class Game { nextPieceListener = listener; } + /** + * Set line cleared listener + * @param listener listener to set + */ + public void setLineClearedListener(LineClearedListener listener) { + lineClearedListener = listener; + } + } diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/scene/ChallengeScene.java b/src/main/java/uk/mgrove/ac/soton/comp1206/scene/ChallengeScene.java index 544cb43..093f055 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/scene/ChallengeScene.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/scene/ChallengeScene.java @@ -1,13 +1,12 @@ package uk.mgrove.ac.soton.comp1206.scene; -import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; import javafx.scene.layout.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import uk.mgrove.ac.soton.comp1206.component.GameBlock; import uk.mgrove.ac.soton.comp1206.component.GameBoard; import uk.mgrove.ac.soton.comp1206.component.PieceBoard; -import uk.mgrove.ac.soton.comp1206.event.NextPieceListener; import uk.mgrove.ac.soton.comp1206.game.Game; import uk.mgrove.ac.soton.comp1206.game.GamePiece; import uk.mgrove.ac.soton.comp1206.ui.GamePane; @@ -28,6 +27,16 @@ public class ChallengeScene extends BaseScene { */ private PieceBoard currentPieceBoard; + /** + * PieceBoard to display next piece + */ + private PieceBoard followingPieceBoard; + + /** + * GameBoard for main game + */ + private GameBoard board; + /** * Create a new Single Player challenge scene * @param gameWindow the Game Window @@ -57,15 +66,19 @@ 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); + board = new GameBoard(game.getGrid(),gameWindow.getWidth()/2,gameWindow.getWidth()/2); + board.setOnRightClicked(game::rotateCurrentPiece); mainPane.setCenter(board); var statsMenu = new StatsMenu(game.scoreProperty(),game.levelProperty(),game.livesProperty(),game.multiplierProperty()); currentPieceBoard = new PieceBoard(100, 100); + currentPieceBoard.showMiddleIndicator(true); + currentPieceBoard.setOnLeftClicked(game::rotateCurrentPiece); + followingPieceBoard = new PieceBoard(72, 72); var rightMenu = new VBox(); - rightMenu.getChildren().addAll(statsMenu,currentPieceBoard); + rightMenu.getChildren().addAll(statsMenu,currentPieceBoard,followingPieceBoard); mainPane.setRight(rightMenu); @@ -83,6 +96,24 @@ public class ChallengeScene extends BaseScene { game.blockClicked(gameBlock); } + /** + * Handle keypress for game keyboard controls + * @param event the keypress + */ + private void handleKeyboardControls(KeyEvent event) { + switch (event.getCode()) { + case ESCAPE -> returnToMenu(); + case ENTER, X -> game.dropPiece(board.getXFocus(),board.getYFocus()); + case SPACE, R -> game.swapPieces(); + case OPEN_BRACKET, Q, Z -> game.rotateCurrentPieceAnticlockwise(); + case CLOSE_BRACKET, E, C -> game.rotateCurrentPiece(); + case LEFT, A -> board.changeXFocus(-1); + case RIGHT, D -> board.changeXFocus(1); + case DOWN, S -> board.changeYFocus(1); + case UP, W -> board.changeYFocus(-1); + } + } + /** * Set up the game object and model */ @@ -100,15 +131,12 @@ public class ChallengeScene extends BaseScene { public void initialise() { logger.info("Initialising Challenge"); - // exit challenge when escape key pressed - scene.setOnKeyPressed((event) -> { - if (event.getCode() == KeyCode.ESCAPE) { - returnToMenu(); - } - }); + scene.setOnKeyPressed(this::handleKeyboardControls); game.setNextPieceListener(this::setCurrentPiece); + game.setLineClearedListener(board::fadeOut); + game.start(); } @@ -119,8 +147,9 @@ public class ChallengeScene extends BaseScene { gameWindow.startMenu(); } - private void setCurrentPiece(GamePiece piece) { - currentPieceBoard.displayPiece(piece); + private void setCurrentPiece(GamePiece currentPiece, GamePiece followingPiece) { + currentPieceBoard.displayPiece(currentPiece); + followingPieceBoard.displayPiece(followingPiece); } } diff --git a/src/main/java/uk/mgrove/ac/soton/comp1206/scene/InstructionsScene.java b/src/main/java/uk/mgrove/ac/soton/comp1206/scene/InstructionsScene.java index 0e07214..9e59a17 100644 --- a/src/main/java/uk/mgrove/ac/soton/comp1206/scene/InstructionsScene.java +++ b/src/main/java/uk/mgrove/ac/soton/comp1206/scene/InstructionsScene.java @@ -39,7 +39,7 @@ public class InstructionsScene extends BaseScene { public void initialise() { logger.info("Initialising Instructions"); - // exit challenge when escape key pressed + // exit instructions when escape key pressed scene.setOnKeyPressed((event) -> { if (event.getCode() == KeyCode.ESCAPE) { gameWindow.startMenu(); @@ -52,6 +52,8 @@ public class InstructionsScene extends BaseScene { */ @Override public void build() { + // TODO: styling and insets + logger.info("Building " + this.getClass().getName()); root = new GamePane(gameWindow.getWidth(),gameWindow.getHeight());