[FEAT] Piece previews on hover

This commit is contained in:
2023-04-22 00:34:30 +01:00
parent 0b3dfa5817
commit cc205f5c6e
6 changed files with 130 additions and 3 deletions

View File

@@ -64,6 +64,11 @@ public class GameBlock extends Canvas {
*/
private final IntegerProperty value = new SimpleIntegerProperty(0);
/**
* The preview value of this block (0 = empty, otherwise specifies the colour to render as)
*/
private final IntegerProperty previewValue = new SimpleIntegerProperty(0);
/**
* Whether the block should appear as focussed
*/
@@ -98,6 +103,7 @@ public class GameBlock extends Canvas {
//When the value property is updated, call the internal updateValue method
value.addListener(this::updateValue);
previewValue.addListener(this::updateValue);
}
/**
@@ -121,6 +127,9 @@ public class GameBlock extends Canvas {
//If the block is not empty, paint with the colour represented by the value
paintColor(COLOURS[value.get()]);
}
if (previewValue.get() != 0) paintPreview(COLOURS[previewValue.get()]);
// paint focus overlay if required
if (isFocussed) paintFocusOverlay();
@@ -128,6 +137,29 @@ public class GameBlock extends Canvas {
if (showMiddleIndicator) paintMiddleIndicator();
}
/**
* Handle painting of the block canvas with block preview
*/
public void paintPreview(Color color) {
logger.info("Painting preview overlay on block at x: {}, y: {} with color: {}", getX(), getY(), color);
var gc = getGraphicsContext2D();
gc.setFill(color.deriveColor(0, 1, 1, 0.25));
gc.fillRect(0,0, width, height);
gc.setFill(color.deriveColor(0,1,0.8,0.25));
gc.fillPolygon(new double[]{
width,
width,
0
}, new double[]{
0,
height,
0
}, 3
);
}
/**
* Paint this canvas empty
*/
@@ -283,6 +315,14 @@ public class GameBlock extends Canvas {
value.bind(input);
}
/**
* Bind the value of this block to another property. Used to link the visual block to a corresponding block in the Grid.
* @param input property to bind the value to
*/
public void bindPreview(ObservableValue<? extends Number> input) {
previewValue.bind(input);
}
@Override
public String toString() {
return "GameBlock{" +

View File

@@ -7,6 +7,7 @@ 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.GamePiece;
import uk.mgrove.ac.soton.comp1206.game.Grid;
import uk.mgrove.ac.soton.comp1206.util.Multimedia;
@@ -16,7 +17,7 @@ import java.util.Set;
* A GameBoard is a visual component to represent the visual GameBoard.
* It extends a GridPane to hold a grid of GameBlocks.
*
* The GameBoard can hold an internal grid of it's own, for example, for displaying an upcoming block. It also be
* The GameBoard can hold an internal grid of its own, for example, for displaying an upcoming block. It also be
* linked to an external grid, for the main game board.
*
* The GameBoard is only a visual representation and should not contain game logic or model logic in it, which should
@@ -81,6 +82,11 @@ public class GameBoard extends GridPane {
*/
protected boolean enableFocus = true;
/**
* Current game piece
*/
protected GamePiece currentPiece;
/**
* Create a new GameBoard, based off a given grid, with a visual width and height.
* @param grid linked grid
@@ -151,6 +157,8 @@ public class GameBoard extends GridPane {
logger.debug("Mouse button clicked: {}", event.getButton());
if (event.getButton().equals(MouseButton.SECONDARY) && rightClickListener != null) {
rightClickListener.action();
grid.clearPreview();
grid.previewPiece(currentPiece, getXFocus(), getYFocus());
} else if (event.getButton().equals(MouseButton.PRIMARY) && leftClickListener != null) {
leftClickListener.action();
}
@@ -178,6 +186,7 @@ public class GameBoard extends GridPane {
//Link the GameBlock component to the corresponding value in the Grid
block.bind(grid.getGridProperty(x,y));
block.bindPreview(grid.getPreviewGridProperty(x,y));
//Add a mouse click handler to the block to trigger GameBoard blockClicked method
block.setOnMouseClicked((e) -> {
@@ -212,11 +221,13 @@ public class GameBoard extends GridPane {
}
public void blockHovered(GameBlock gameBlock) {
grid.clearPreview();
if (enableFocus) {
logger.info("Block hovered: {}", gameBlock);
if (focussedBlock != null) focussedBlock.setFocussed(false);
focussedBlock = gameBlock;
focussedBlock.setFocussed(true);
grid.previewPiece(currentPiece, getXFocus(), getYFocus());
}
}
@@ -270,12 +281,28 @@ public class GameBoard extends GridPane {
else return 0;
}
/**
* Set listener for when secondary mouse button clicked
* @param listener listener to set
*/
public void setOnRightClicked(MouseClickListener listener) {
rightClickListener = listener;
}
/**
* Set listener for when primary mouse button clicked
* @param listener listener to set
*/
public void setOnLeftClicked(MouseClickListener listener) {
leftClickListener = listener;
}
/**
* Update current game piece
* @param newPiece current piece
*/
public void setCurrentPiece(GamePiece newPiece) {
currentPiece = newPiece;
}
}

View File

@@ -38,6 +38,11 @@ public class Grid {
*/
private final SimpleIntegerProperty[][] grid;
/**
* The preview grid is a 2D arrow with rows and columns of SimpleIntegerProperties, storing which blocks are currently showing previews.
*/
private final SimpleIntegerProperty[][] previewGrid;
/**
* Create a new Grid with the specified number of columns and rows and initialise them
* @param cols number of columns
@@ -56,6 +61,16 @@ public class Grid {
grid[x][y] = new SimpleIntegerProperty(0);
}
}
//Create the grid itself
previewGrid = new SimpleIntegerProperty[cols][rows];
//Add a SimpleIntegerProperty to every block in the grid
for(var y = 0; y < rows; y++) {
for(var x = 0; x < cols; x++) {
previewGrid[x][y] = new SimpleIntegerProperty(0);
}
}
}
/**
@@ -68,6 +83,16 @@ public class Grid {
return grid[x][y];
}
/**
* Get the Integer property contained inside the preview grid at a given row and column index. Can be used for binding.
* @param x column
* @param y row
* @return the IntegerProperty at the given x and y in this grid
*/
public IntegerProperty getPreviewGridProperty(int x, int y) {
return previewGrid[x][y];
}
/**
* Update the value at the given x and y index within the grid
* @param x column
@@ -175,4 +200,37 @@ public class Grid {
return rows;
}
/**
* Preview piece on board
* @param piece piece to preview
* @param x x-coordinate of piece centre
* @param y y-coordinate of piece centre
*/
public void previewPiece(GamePiece piece, int x, int y) {
if (!canPlayPiece(piece, x, y)) return;
logger.info("Previewing piece {} at {},{}", piece, x, y);
int value = piece.getValue();
int[][] blocks = piece.getBlocks();
for (var blockX = 0; blockX < blocks.length; blockX++) {
for (var blockY = 0; blockY < blocks.length; blockY++) {
if (blocks[blockX][blockY] > 0) {
previewGrid[x + blockX - 1][y + blockY - 1].set(value);
}
}
}
}
/**
* Clear previewed blocks from the grid
*/
public void clearPreview() {
for (var resetX = 0; resetX < previewGrid.length; resetX++) {
for (var resetY = 0; resetY < previewGrid[0].length; resetY++) {
previewGrid[resetX][resetY].set(0);
}
}
}
}

View File

@@ -218,6 +218,7 @@ public class ChallengeScene extends BaseScene {
protected void setCurrentPiece(GamePiece currentPiece, GamePiece followingPiece) {
currentPieceBoard.displayPiece(currentPiece);
followingPieceBoard.displayPiece(followingPiece);
board.setCurrentPiece(currentPiece);
}
/**

View File

@@ -34,7 +34,7 @@ public class Multimedia {
if (audioPlayer != null) audioPlayer.stop();
var media = new Media(Multimedia.class.getResource("/" + filePath).toExternalForm());
audioPlayer = new MediaPlayer(media);
// audioPlayer.play();
audioPlayer.play();
}
/**
@@ -47,7 +47,7 @@ public class Multimedia {
if (musicPlayer != null) musicPlayer.stop();
var media = new Media(Multimedia.class.getResource("/" + filePath).toExternalForm());
musicPlayer = new MediaPlayer(media);
// musicPlayer.setAutoPlay(true);
musicPlayer.setAutoPlay(true);
musicPlayer.setCycleCount(MediaPlayer.INDEFINITE);
}

View File

@@ -8,6 +8,7 @@
Text {
-fx-fill: white;
-fx-font-family: 'Orbitron';
}
Label {