Skip to content
Snippets Groups Projects
Commit a0811bf2 authored by ayazb7's avatar ayazb7
Browse files

Adding Instruction scene and UI changes

parent 10f54c81
No related branches found
No related tags found
No related merge requests found
Showing
with 349 additions and 48 deletions
......@@ -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.canvas.GraphicsContext;
import javafx.scene.effect.BlendMode;
import javafx.scene.paint.*;
import org.apache.logging.log4j.LogManager;
......@@ -64,6 +65,10 @@ public class GameBlock extends Canvas {
*/
private final IntegerProperty value = new SimpleIntegerProperty(0);
private boolean isCentre = false;
private boolean isHovering = false;
/**
* Create a new single Game Block
*
......@@ -113,22 +118,31 @@ public class GameBlock extends Canvas {
//If the block is not empty, paint with the colour represented by the value
paintColor(COLOURS[value.get()]);
}
if (isHovering) {
paintHoverTile();
}
if (isCentre) {
paintCentreCircle();
}
}
/**
* Paint this canvas empty
*/
private void paintEmpty() {
var gc = getGraphicsContext2D();
GraphicsContext gc = getGraphicsContext2D();
//Clear
gc.clearRect(0.0D, 0.0D, this.width, this.height);
gc.clearRect(0, 0, this.width, this.height);
//Fill
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);
Color gradStart = Color.color(0.0, 0.0, 0.6, 0.3);
Color gradEnd = Color.color(0.0, 0.0, 0.2, 0.5);
gc.setFill(new LinearGradient(0.0, 0.0, 1.0, 1.0, true, CycleMethod.REFLECT, new Stop(0, gradStart), new Stop(1, gradEnd)));
gc.fillRect(0, 0, this.width, this.height);
//Border
gc.setStroke(Color.WHITE);
......@@ -142,21 +156,46 @@ public class GameBlock extends Canvas {
* @param colour the colour to paint
*/
private void paintColor(Paint colour) {
var gc = getGraphicsContext2D();
GraphicsContext gc = getGraphicsContext2D();
//Clear
gc.clearRect(0, 0, width, height);
//Colour fill
gc.setFill(colour);
gc.setGlobalAlpha(1);
gc.fillRect(0, 0, width, height);
gc.setFill(Color.color(1,1,1,0.3));
gc.fillPolygon(new double[]{0, width, 0}, new double[]{0, 0, height}, 3);
//Border
gc.setStroke(Color.BLACK);
gc.strokeRect(0, 0, width, height);
}
private void paintCentreCircle() {
GraphicsContext gc = getGraphicsContext2D();
gc.setFill(Color.color(1.0, 1.0, 1.0, 0.6));
gc.fillOval(this.width / 4, this.height / 4, this.width / 2, this.height / 2);
}
private void paintHoverTile() {
GraphicsContext gc = getGraphicsContext2D();
gc.setFill(Color.color(1.0, 1.0, 1.0, 0.4));
gc.fillRect(0,0, width, height);
}
public void setCentre() {
this.isCentre = true;
paint();
}
public void setHovering(boolean hovering) {
this.isHovering = hovering;
paint();
}
/**
* Get the column of this block
*
......
......@@ -60,6 +60,8 @@ public class GameBoard extends GridPane {
protected RightClickListener rightClickListener;
protected boolean isPieceBoard = false;
/**
* Create a new GameBoard, based off a given grid, with a visual width and height.
*
......@@ -161,6 +163,11 @@ public class GameBoard extends GridPane {
blockRightClicked(block);
}
});
block.setOnMouseEntered(e -> hover(block));
block.setOnMouseExited(e -> unhover(block));
return block;
}
......@@ -183,8 +190,6 @@ public class GameBoard extends GridPane {
* @param block block clicked on
*/
private void blockClicked(GameBlock block) {
logger.info("Block clicked: {}", block);
if (blockClickedListener != null) {
blockClickedListener.blockClicked(block);
}
......@@ -196,4 +201,14 @@ public class GameBoard extends GridPane {
}
}
private void hover(GameBlock block) {
if (isPieceBoard) return;
block.setHovering(true);
}
private void unhover(GameBlock block) {
if (isPieceBoard) return;
block.setHovering(false);
}
}
......@@ -7,6 +7,7 @@ public class PieceBoard extends GameBoard {
public PieceBoard(double width, double height) {
super(3, 3, width, height);
this.isPieceBoard = true;
}
public void displayPiece(GamePiece piece, int placeX, int placeY) {
......@@ -26,4 +27,8 @@ public class PieceBoard extends GameBoard {
this.blockClickedListener = handler;
}
public void drawCentre() {
this.blocks[1][1].setCentre();
}
}
......@@ -3,5 +3,5 @@ package uk.ac.soton.comp1206.event;
import uk.ac.soton.comp1206.game.GamePiece;
public interface NextPieceListener {
void nextPiece(GamePiece paramGamePiece);
void nextPiece(GamePiece piece);
}
......@@ -44,7 +44,7 @@ public class Game {
private int remainder = 0;
protected NextPieceListener nextPieceHandler = null;
protected NextPieceListener nextPieceListener = null;
/**
* Create a new game with the specified rows and columns. Creates a corresponding grid model.
......@@ -118,8 +118,8 @@ public class Game {
this.currentPiece = this.nextPiece;
this.nextPiece = spawnPiece();
if (this.nextPieceHandler != null) {
this.nextPieceHandler.nextPiece(this.currentPiece);
if (this.nextPieceListener != null) {
this.nextPieceListener.nextPiece(this.currentPiece);
}
logger.info("Current piece is : {}", this.currentPiece);
......@@ -132,7 +132,7 @@ public class Game {
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++) {
......@@ -147,7 +147,7 @@ public class Game {
}
}
/**
/*
* Check each horizontal row to see if it is full
*/
for (int y = 0; y < grid.getCols(); y++) {
......@@ -164,7 +164,7 @@ public class Game {
int numGridBlocks = 0;
/**
/*
* Removes all columns which are full
*/
for (int x : fullCols) {
......@@ -176,8 +176,8 @@ public class Game {
}
}
/**
* Removes all rows which are full
/*
Removes all rows which are full
*/
for (int y : fullRows) {
for (int x = 0; x < grid.getCols(); x++) {
......@@ -204,9 +204,11 @@ public class Game {
Multimedia.playSound("clear.wav");
this.setMultiplier(multiplier.get() + 1);
} else {
if (this.getMultiplier().get() > 1) {
this.setMultiplier(1);
}
}
}
public void swapPiece() {
GamePiece tempPiece = this.currentPiece;
......@@ -249,8 +251,8 @@ public class Game {
return nextPiece;
}
public void setOnNextPiece(NextPieceListener handler) {
this.nextPieceHandler = handler;
public void setNextPieceListener(NextPieceListener listener) {
this.nextPieceListener = listener;
}
public void rotatePiece(int rotations) {
......
......@@ -4,6 +4,8 @@ import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
......@@ -20,6 +22,7 @@ import uk.ac.soton.comp1206.ui.GamePane;
import uk.ac.soton.comp1206.ui.GameWindow;
import uk.ac.soton.comp1206.utility.Multimedia;
import java.security.Key;
import java.util.ArrayList;
/**
......@@ -44,6 +47,29 @@ public class ChallengeScene extends BaseScene {
logger.info("Creating Challenge Scene");
}
/**
* Initialise the scene and start the game
*/
@Override
public void initialise() {
logger.info("Initialising Challenge");
Multimedia.playBackgroundMusic("game_start.wav", false);
Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> Multimedia.playBackgroundMusic("game.wav", true));
this.game.setNextPieceListener(this::nextPiece);
this.scene.setOnKeyPressed(this::keyHandler);
game.start();
}
private void keyHandler(KeyEvent e) {
if (e.getCode().equals(KeyCode.ESCAPE)) {
Multimedia.stopSound();
this.gameWindow.startMenu();
}
}
/**
* Build the Challenge window
*/
......@@ -151,10 +177,12 @@ public class ChallengeScene extends BaseScene {
this.currentPieceBoard = new PieceBoard(gameWindow.getWidth() / 6, gameWindow.getWidth() / 6);
this.currentPieceBoard.setOnClick(this::rotateBlock);
this.currentPieceBoard.drawCentre();
gameInfo.getChildren().add(this.currentPieceBoard);
this.nextPieceBoard = new PieceBoard(gameWindow.getWidth() / 10, gameWindow.getWidth() / 10);
this.nextPieceBoard.setOnClick(this::swapPiece);
this.nextPieceBoard.drawCentre();
gameInfo.getChildren().add(this.nextPieceBoard);
gameInfo.setAlignment(Pos.CENTER);
......@@ -170,6 +198,7 @@ public class ChallengeScene extends BaseScene {
private void swapPiece(GameBlock gameBlock) {
logger.info("Swapping current and next piece");
Multimedia.playSound("rotate.wav");
this.currentPieceBoard.displayPiece(this.game.getNextPiece());
this.nextPieceBoard.displayPiece(this.game.getCurrentPiece());
this.game.swapPiece();
......@@ -209,19 +238,6 @@ public class ChallengeScene extends BaseScene {
game = new Game(5, 5);
}
/**
* Initialise the scene and start the game
*/
@Override
public void initialise() {
logger.info("Initialising Challenge");
Multimedia.playBackgroundMusic("game_start.wav", false);
Multimedia.getBackgroundPlayer().setOnEndOfMedia(() -> Multimedia.playBackgroundMusic("game.wav", true));
this.game.setOnNextPiece(this::nextPiece);
game.start();
}
protected void nextPiece(GamePiece nextPiece) {
logger.info("Next piece to place: " + nextPiece);
this.currentPieceBoard.displayPiece(nextPiece);
......
package uk.ac.soton.comp1206.scene;
import javafx.geometry.Pos;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextFlow;
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.PieceBoard;
import uk.ac.soton.comp1206.game.Game;
import uk.ac.soton.comp1206.game.GamePiece;
import uk.ac.soton.comp1206.ui.GamePane;
import uk.ac.soton.comp1206.ui.GameWindow;
import uk.ac.soton.comp1206.utility.Multimedia;
public class InstructionScene extends BaseScene{
private static final Logger logger = LogManager.getLogger(InstructionScene.class);
private int pieceNumber = 0;
private PieceBoard pieceBoard;
/**
* Create a new scene, passing in the GameWindow the scene will be displayed in
*
* @param gameWindow the game window
*/
public InstructionScene(GameWindow gameWindow) {
super(gameWindow);
logger.info("Creating Instructions Scene");
}
@Override
public void initialise() {
this.scene.setOnKeyPressed(this::escapeToMenu);
}
@Override
public void build() {
logger.info("Building " + this.getClass().getName());
root = new GamePane(gameWindow.getWidth(), gameWindow.getHeight());
StackPane instructionsPane = new StackPane();
instructionsPane.setMaxWidth(gameWindow.getWidth());
instructionsPane.setMaxHeight(gameWindow.getHeight());
instructionsPane.getStyleClass().add("menu-background");
root.getChildren().add(instructionsPane);
BorderPane mainPane = new BorderPane();
instructionsPane.getChildren().add(mainPane);
VBox widgets = new VBox();
Text instructionsTitle = new Text("How to Play");
instructionsTitle.getStyleClass().add("heading");
widgets.getChildren().add(instructionsTitle);
Text instructionsText = new Text("TetrECS is a fast-paced gravity-free block placement game, where you must survive by clearing rows through careful placement of the upcoming blocks before the time runs out. Lose all 3 lives and you're destroyed!");
TextFlow instructionTextBox = new TextFlow(instructionsText);
instructionsText.getStyleClass().add("instructions");
instructionTextBox.setTextAlignment(TextAlignment.CENTER);
widgets.getChildren().add(instructionTextBox);
ImageView instructionsImage = new ImageView(getClass().getResource("/images/Instructions.png").toExternalForm());
instructionsImage.setPreserveRatio(true);
instructionsImage.setFitWidth(this.gameWindow.getWidth() / 1.5D);
widgets.getChildren().add(instructionsImage);
Text gamePiecesLabel = new Text("Game Pieces");
gamePiecesLabel.getStyleClass().add("heading");
widgets.getChildren().add(gamePiecesLabel);
HBox pieceBoards = buildPieceBoards();
widgets.getChildren().add(pieceBoards);
widgets.setAlignment(Pos.TOP_CENTER);
widgets.setSpacing(10);
mainPane.setCenter(widgets);
}
private HBox buildPieceBoards() {
HBox pieceBoardLayout = new HBox();
ImageView prevArrow = new ImageView(getClass().getResource("/images/leftArrow.png").toExternalForm());
prevArrow.setOnMouseClicked(this::displayPrevPiece);
pieceBoardLayout.getChildren().add(prevArrow);
GamePiece piece = GamePiece.createPiece(pieceNumber);
pieceBoard = new PieceBoard((this.gameWindow.getWidth() / 6), (this.gameWindow.getWidth() / 6));
pieceBoard.displayPiece(piece);
pieceBoardLayout.getChildren().add(pieceBoard);
ImageView nextArrow = new ImageView(getClass().getResource("/images/rightArrow.png").toExternalForm());
nextArrow.setOnMouseClicked(this::displayNextPiece);
pieceBoardLayout.getChildren().add(nextArrow);
pieceBoardLayout.setAlignment(Pos.CENTER);
pieceBoardLayout.setSpacing(10);
return pieceBoardLayout;
}
private void displayNextPiece(MouseEvent event) {
if (pieceNumber != 14) {
pieceNumber++;
} else {
pieceNumber = 0;
}
GamePiece piece = GamePiece.createPiece(pieceNumber);
pieceBoard.displayPiece(piece);
}
private void displayPrevPiece(MouseEvent event) {
if (pieceNumber != 0) {
pieceNumber--;
} else {
pieceNumber = 14;
}
GamePiece piece = GamePiece.createPiece(pieceNumber);
pieceBoard.displayPiece(piece);
}
private void escapeToMenu(KeyEvent e) {
if (e.getCode().equals(KeyCode.ESCAPE)) {
Multimedia.stopSound();
this.gameWindow.startMenu();
}
}
}
package uk.ac.soton.comp1206.scene;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
......@@ -8,6 +9,7 @@ import javafx.scene.media.MediaPlayer;
import javafx.scene.text.Text;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import uk.ac.soton.comp1206.App;
import uk.ac.soton.comp1206.ui.GamePane;
import uk.ac.soton.comp1206.ui.GameWindow;
import uk.ac.soton.comp1206.utility.Multimedia;
......@@ -38,7 +40,7 @@ public class MenuScene extends BaseScene {
root = new GamePane(gameWindow.getWidth(), gameWindow.getHeight());
var menuPane = new StackPane();
StackPane menuPane = new StackPane();
menuPane.setMaxWidth(gameWindow.getWidth());
menuPane.setMaxHeight(gameWindow.getHeight());
menuPane.getStyleClass().add("menu-background");
......@@ -49,30 +51,46 @@ public class MenuScene extends BaseScene {
VBox menuWidgets = new VBox();
Region space = new Region();
space.setPrefHeight(100);
HBox.setHgrow(space, Priority.ALWAYS);
menuWidgets.getChildren().add(space);
//Awful title
var title = new Text("TetrECS");
Text title = new Text("TetrECS");
title.getStyleClass().add("bigtitle");
menuWidgets.getChildren().add(title);
VBox menuButtons = new VBox();
var singlePlay = new Text("Single Player");
Text singlePlay = new Text("Single Player");
singlePlay.getStyleClass().add("menuItem");
singlePlay.setOnMouseClicked(this::startGame);
menuButtons.getChildren().add(singlePlay);
Text multiPlayLabel = new Text("Multi Player");
multiPlayLabel.getStyleClass().add("menuItem");
menuButtons.getChildren().add(multiPlayLabel);
Text instructions = new Text("How To Play");
instructions.getStyleClass().add("menuItem");
instructions.setOnMouseClicked(this::showInstructions);
menuButtons.getChildren().add(instructions);
Text exitLabel = new Text("Exit");
exitLabel.getStyleClass().add("menuItem");
exitLabel.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
App.getInstance().shutdown();
}
});
menuButtons.getChildren().add(exitLabel);
menuButtons.setAlignment(Pos.CENTER);
menuButtons.setSpacing(5);
menuWidgets.getChildren().add(menuButtons);
menuWidgets.setAlignment(Pos.CENTER);
menuWidgets.setSpacing(150);
mainPane.setTop(menuWidgets);
mainPane.setCenter(menuButtons);
mainPane.setCenter(menuWidgets);
Multimedia.playBackgroundMusic("menu.mp3", true);
}
/**
......@@ -80,17 +98,20 @@ public class MenuScene extends BaseScene {
*/
@Override
public void initialise() {
Multimedia.playBackgroundMusic("menu.mp3", true);
}
/**
* Handle when the Start Game button is pressed
*
* @param event event
*/
private void startGame(MouseEvent event) {
Multimedia.stopSound();
gameWindow.startChallenge();
}
private void showInstructions(MouseEvent event) {
gameWindow.displayInstructions();
}
}
package uk.ac.soton.comp1206;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class test extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Drawing Operations Test");
Group root = new Group();
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
drawShapes(gc);
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
private void drawShapes(GraphicsContext gc) {
int firstX = 90;
int secondX = 190;
int thirdX = 10;
int firstY =30;
int secondY =170;
int thirdY =170;
gc.setFill(Color.GREEN);
gc.setStroke(Color.BLUE);
gc.fillPolygon(new double[]{firstX, secondX,thirdX},
new double[]{firstY, secondY, thirdY}, 3);
gc.strokePolygon(new double[]{firstX, secondX,thirdX},
new double[]{firstY, secondY, thirdY}, 3);
gc.setFill(javafx.scene.paint.Color.BLACK);
gc.fillText("1", firstX - 3, firstY - 4);
gc.fillText("2", secondX - 3, secondY - 4);
gc.fillText("3", thirdX - 3, thirdY - 4);
}
}
......@@ -88,6 +88,10 @@ public class GameWindow {
loadScene(new ChallengeScene(this));
}
public void displayInstructions() {
loadScene(new InstructionScene(this));
}
/**
* Setup the default settings for the stage itself (the window), such as the title and minimum width and height.
*/
......
......@@ -46,6 +46,7 @@ public class Multimedia {
}
public static void stopSound() {
logger.info("Stopping all current audio tracks");
if (mediaPlayer != null) {
mediaPlayer.stop();
}
......
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment