Finished online scores leaderboard
This commit is contained in:
parent
e55dace14d
commit
389e0fb41f
2
META-INF/MANIFEST.MF
Normal file
2
META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
||||
@ -160,6 +160,9 @@ public class GameBlock extends Canvas {
|
||||
gc.strokeRect(0,0,width,height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the blocks on mouse hover
|
||||
*/
|
||||
public void paintHover() {
|
||||
GraphicsContext gc = getGraphicsContext2D();
|
||||
gc.setFill(Color.color(1.0, 1.0, 1.0, 0.5));
|
||||
@ -198,10 +201,17 @@ public class GameBlock extends Canvas {
|
||||
value.bind(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the center grid square with a grey circle
|
||||
* @param centre
|
||||
*/
|
||||
public void setPaintCentre(boolean centre) {
|
||||
this.centre = centre;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set a circle in the center of the grid
|
||||
*/
|
||||
private void fillCenter(){
|
||||
GraphicsContext gc = getGraphicsContext2D();
|
||||
gc.setFill(Color.color(1.0, 1.0, 1.0, 0.5));
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
package uk.ac.soton.comp1206.component;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Pair;
|
||||
import javafx.scene.text.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import uk.ac.soton.comp1206.scene.ScoresScene;
|
||||
|
||||
public class Leaderboard extends VBox {
|
||||
|
||||
Logger logger = LogManager.getLogger(ScoresScene.class);
|
||||
private SimpleListProperty<Pair<String, Integer>> leaderboard;
|
||||
|
||||
|
||||
|
||||
public Leaderboard(SimpleListProperty<Pair<String, Integer>> leaderboard) {
|
||||
this.leaderboard = leaderboard;
|
||||
this.leaderboard.addListener((ListChangeListener<Pair<String, Integer>>) c -> {
|
||||
Platform.runLater(() -> updateLeaderBoard(c));
|
||||
});
|
||||
}
|
||||
|
||||
private void updateLeaderBoard(ListChangeListener.Change<? extends Pair<String, Integer>> change) {
|
||||
logger.info("Updating leaderboard");
|
||||
|
||||
if (change.next()) {
|
||||
if (change.wasPermutated() || change.wasReplaced() || change.wasRemoved()) {
|
||||
super.getChildren().clear();
|
||||
}
|
||||
|
||||
if (change.wasAdded()) {
|
||||
for (Pair<String, Integer> pair : change.getAddedSubList()) {
|
||||
var text = new Text(pair.getKey() + ": " + pair.getValue());
|
||||
text.getStyleClass().add("leaderboard");
|
||||
super.getChildren().add(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -4,6 +4,10 @@ import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
|
||||
public class Timer extends Rectangle {
|
||||
|
||||
/**
|
||||
* Setup basic timer colour and height
|
||||
*/
|
||||
public Timer() {
|
||||
this.setHeight(25);
|
||||
this.setFill(Color.GREEN);
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package uk.ac.soton.comp1206.event;
|
||||
|
||||
public interface GameLoopHandler {
|
||||
/**
|
||||
* Used for game loop events
|
||||
*/
|
||||
public void gameLoop(int time);;
|
||||
}
|
||||
|
||||
@ -3,5 +3,9 @@ package uk.ac.soton.comp1206.event;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
|
||||
public interface KeyPressListener {
|
||||
/**
|
||||
* key pressed event
|
||||
* @param e
|
||||
*/
|
||||
public void keyPressed(KeyEvent e);
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package uk.ac.soton.comp1206.event;
|
||||
|
||||
public interface LooseALife {
|
||||
/**
|
||||
* Used to signal the UI when a life is lost
|
||||
*/
|
||||
public void loose();
|
||||
}
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
package uk.ac.soton.comp1206.event;
|
||||
|
||||
public interface OutOfLives {
|
||||
/**
|
||||
* Sent when out of lives to signal game over
|
||||
*/
|
||||
public void OutOfLives();
|
||||
}
|
||||
|
||||
@ -162,48 +162,77 @@ public class Game {
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new random piece
|
||||
* @return the new piece
|
||||
*/
|
||||
public GamePiece spawnPiece() {
|
||||
Random rand = new Random();
|
||||
return GamePiece.createPiece(rand.nextInt(15));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles after Piece actions
|
||||
*/
|
||||
public void afterPiece () {
|
||||
this.restartGameLoop();
|
||||
this.incrementNextPieces();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void incrementNextPieces() {
|
||||
this.score.set(this.score.get() + grid.clearLines());
|
||||
this.currentPiece = this.nextPiece;
|
||||
this.nextPiece = this.spawnPiece();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get current score
|
||||
* @return InterProperty score
|
||||
*/
|
||||
public IntegerProperty getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of remaining lives
|
||||
* @return InterProperty lives
|
||||
*/
|
||||
public IntegerProperty getLives() {
|
||||
return lives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the level number
|
||||
* @return
|
||||
*/
|
||||
public IntegerProperty getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the piece currently being played
|
||||
* @return the piece
|
||||
*/
|
||||
public GamePiece getCurrentGamePiece() {
|
||||
return currentPiece;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the piece that is going to be played next
|
||||
* @return the piece
|
||||
*/
|
||||
public GamePiece getNextGamePiece() {
|
||||
return nextPiece;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the current and next game pieces
|
||||
*/
|
||||
public void swapNextPieces() {
|
||||
GamePiece tmpPiece = this.nextPiece;
|
||||
this.nextPiece = this.currentPiece;
|
||||
@ -211,18 +240,27 @@ public class Game {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the game loop
|
||||
*/
|
||||
public void startGameLoop() {
|
||||
logger.info("Starting game loop");
|
||||
this.nextLoop = this.executor.schedule(this::gameLoop, getTimerDelay(), TimeUnit.MILLISECONDS);
|
||||
this.gameLoopHandler.gameLoop(this.getTimerDelay());
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the game loop
|
||||
*/
|
||||
public void restartGameLoop() {
|
||||
logger.info("Restarting game loop");
|
||||
this.nextLoop.cancel(false);
|
||||
this.startGameLoop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the game loop
|
||||
*/
|
||||
public void killGameLoop() {
|
||||
logger.info("Killing game loop");
|
||||
this.nextLoop.cancel(false);
|
||||
@ -244,18 +282,34 @@ public class Game {
|
||||
return;
|
||||
}
|
||||
|
||||
public int getTimerDelay(){
|
||||
/**
|
||||
* Calculate the get the timer delay (the amount of time the player has to play the piece)
|
||||
* @return the time in milliseconds
|
||||
*/
|
||||
protected int getTimerDelay(){
|
||||
return Math.max(12000 - 500 * this.getLevel().get(), 2500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup event handler for gameLoop
|
||||
* @param gameLoopHandler
|
||||
*/
|
||||
public void setOnGameLoop(GameLoopHandler gameLoopHandler) {
|
||||
this.gameLoopHandler = gameLoopHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup event handler for out of lives event
|
||||
* @param outOfLives
|
||||
*/
|
||||
public void setOnOutOfLives(OutOfLives outOfLives) {
|
||||
this.outOfLives = outOfLives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup event handler for a loss of life event, when the player looses a life
|
||||
* @param looseALife
|
||||
*/
|
||||
public void setOnLossALife(LooseALife looseALife) {
|
||||
this.looseALife = looseALife;
|
||||
}
|
||||
|
||||
@ -109,6 +109,13 @@ public class Grid {
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the piece can be placed on the gird
|
||||
* @param gamePiece
|
||||
* @param pieceX
|
||||
* @param pieceY
|
||||
* @return true if piece can be played
|
||||
*/
|
||||
public boolean canPlayPiece(GamePiece gamePiece, int pieceX, int pieceY){
|
||||
//Calculate the offset due to middle piece
|
||||
pieceX --;
|
||||
@ -133,6 +140,12 @@ public class Grid {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Places piece on the grid
|
||||
* @param gamePiece
|
||||
* @param pieceX
|
||||
* @param pieceY
|
||||
*/
|
||||
public void addPiece(GamePiece gamePiece, int pieceX, int pieceY){
|
||||
pieceX --;
|
||||
pieceY --;
|
||||
@ -146,6 +159,10 @@ public class Grid {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks which lines can be cleared
|
||||
* @return number of blocks cleared
|
||||
*/
|
||||
public int clearLines() {
|
||||
//List of cords to clear
|
||||
HashSet<int[]> cordsToRemove = new HashSet<>();
|
||||
@ -193,6 +210,9 @@ public class Grid {
|
||||
return cordsToRemove.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the whole board
|
||||
*/
|
||||
public void clear() {
|
||||
for(int x = 0; x < cols; x++) {
|
||||
for(int y = 0; y < rows; y++) {
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
package uk.ac.soton.comp1206.network;
|
||||
|
||||
import com.neovisionaries.ws.client.*;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.util.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import uk.ac.soton.comp1206.event.CommunicationsListener;
|
||||
@ -120,4 +123,5 @@ public class Communicator {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -9,7 +9,9 @@ import uk.ac.soton.comp1206.ui.GameWindow;
|
||||
* A Base Scene used in the game. Handles common functionality between all scenes.
|
||||
*/
|
||||
public abstract class BaseScene {
|
||||
|
||||
/**
|
||||
* The game window
|
||||
*/
|
||||
protected final GameWindow gameWindow;
|
||||
|
||||
protected GamePane root;
|
||||
|
||||
@ -198,11 +198,17 @@ public class ChallengeScene extends BaseScene {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling loss of life events
|
||||
*/
|
||||
private void lossOfLife() {
|
||||
this.game.incrementNextPieces();
|
||||
this.updateNextPieces();
|
||||
}
|
||||
|
||||
/**
|
||||
* When the game is over
|
||||
*/
|
||||
private void gameOver() {
|
||||
//This is required so that it runs on the javaFX thread and not in the gameLoop thread
|
||||
Platform.runLater(() -> {
|
||||
@ -211,12 +217,18 @@ public class ChallengeScene extends BaseScene {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle the next piece being clicked
|
||||
* @param mouseEvent
|
||||
*/
|
||||
private void nextPieceClicked(MouseEvent mouseEvent) {
|
||||
this.rotateNext();
|
||||
}
|
||||
|
||||
//Handle when next piece 2 is clicked
|
||||
/**
|
||||
* Handle when the second next piece is clicked
|
||||
* @param mouseEvent
|
||||
*/
|
||||
private void nextPiece2Clicked(MouseEvent mouseEvent) {
|
||||
this.swampNextPieces();
|
||||
}
|
||||
@ -233,7 +245,7 @@ public class ChallengeScene extends BaseScene {
|
||||
|
||||
|
||||
/**
|
||||
* Setup the game object and model
|
||||
* Set up the game object and model
|
||||
*/
|
||||
public void setupGame() {
|
||||
logger.info("Starting a new challenge");
|
||||
@ -242,6 +254,10 @@ public class ChallengeScene extends BaseScene {
|
||||
game = new Game(5, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param time
|
||||
*/
|
||||
protected void gameLoop(int time) {
|
||||
logger.info("Game loop");
|
||||
var timeline = new Timeline(
|
||||
@ -250,6 +266,9 @@ public class ChallengeScene extends BaseScene {
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the next piece on the UI
|
||||
*/
|
||||
public void updateNextPieces() {
|
||||
this.nextPiece.setPiece(this.game.getCurrentGamePiece());
|
||||
this.nextPiece2.setPiece(this.game.getNextGamePiece());
|
||||
@ -275,23 +294,43 @@ public class ChallengeScene extends BaseScene {
|
||||
}
|
||||
});
|
||||
|
||||
this.scene.setOnMouseClicked(e -> {
|
||||
if(e.isSecondaryButtonDown()) {
|
||||
logger.info("Secondary button pressed");
|
||||
this.rotateNext();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GameBoard getNextPiece() {
|
||||
return nextPiece;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the next pieces in the queue
|
||||
*/
|
||||
public void swampNextPieces() {
|
||||
this.game.swapNextPieces();
|
||||
this.updateNextPieces();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the piece that is next up
|
||||
*/
|
||||
public void rotateNext() {
|
||||
this.game.getCurrentGamePiece().rotate();
|
||||
this.updateNextPieces();
|
||||
}
|
||||
|
||||
//Keyboard control functions
|
||||
/**
|
||||
* Handles key presses for the game
|
||||
* @param keyEvent
|
||||
*/
|
||||
public void handleKeyPressed(KeyEvent keyEvent) {
|
||||
logger.info("Handling key pressed");
|
||||
if(keyEvent.getCode() == KeyCode.SPACE || keyEvent.getCode() == KeyCode.R) {
|
||||
@ -299,8 +338,15 @@ public class ChallengeScene extends BaseScene {
|
||||
this.updateNextPieces();
|
||||
} else if(keyEvent.getCode() == KeyCode.ENTER) {
|
||||
|
||||
}
|
||||
|
||||
} else if(keyEvent.getCode() == KeyCode.Q || keyEvent.getCode() == KeyCode.OPEN_BRACKET || keyEvent.getCode() == KeyCode.Z) {
|
||||
logger.info("Rotating left");
|
||||
this.game.getCurrentGamePiece().rotate();
|
||||
this.updateNextPieces();
|
||||
return;
|
||||
} else if(keyEvent.getCode() == KeyCode.E || keyEvent.getCode() == KeyCode.C || keyEvent.getCode() == KeyCode.CLOSE_BRACKET);
|
||||
logger.info("Rotating right");
|
||||
this.game.getCurrentGamePiece().rotate(3);
|
||||
this.updateNextPieces();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,11 +25,17 @@ public class HowToPlay extends BaseScene {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise user interface, add event listeners.
|
||||
*/
|
||||
@Override
|
||||
public void initialise() {
|
||||
this.scene.setOnKeyPressed(e -> this.gameWindow.startMenu());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the user interface
|
||||
*/
|
||||
@Override
|
||||
public void build() {
|
||||
logger.info("Building how to play scene");
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
package uk.ac.soton.comp1206.scene;
|
||||
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import javafx.scene.text.*;
|
||||
import uk.ac.soton.comp1206.ui.GamePane;
|
||||
import uk.ac.soton.comp1206.ui.GameWindow;
|
||||
|
||||
public class LeaderBoard extends BaseScene {
|
||||
|
||||
Logger logger = LogManager.getLogger(LeaderBoard.class);
|
||||
/**
|
||||
* Create a new scene, passing in the GameWindow the scene will be displayed in
|
||||
*
|
||||
* @param gameWindow the game window
|
||||
*/
|
||||
public LeaderBoard(GameWindow gameWindow) {
|
||||
super(gameWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
this.scene.setOnKeyPressed(e -> this.gameWindow.startMenu());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build() {
|
||||
logger.info("Building " + this.getClass().getName());
|
||||
|
||||
root = new GamePane(gameWindow.getWidth(), gameWindow.getHeight());
|
||||
var leaderboardPane = new StackPane();
|
||||
leaderboardPane.setMaxWidth(gameWindow.getWidth());
|
||||
leaderboardPane.setMaxHeight(gameWindow.getHeight());
|
||||
leaderboardPane.getStyleClass().add("menu-background");
|
||||
root.getChildren().add(leaderboardPane);
|
||||
|
||||
var leaderboardBox = new VBox();
|
||||
leaderboardPane.getChildren().add(leaderboardBox);
|
||||
|
||||
// Set alignment of leaderboardBox to center
|
||||
leaderboardBox.setAlignment(Pos.TOP_CENTER);
|
||||
|
||||
ImageView title = new ImageView(new Image("file:src/main/resources/images/TetrECS.png"));
|
||||
title.setPreserveRatio(true);
|
||||
title.setFitWidth(gameWindow.getWidth() - 100);
|
||||
leaderboardBox.getChildren().add(title);
|
||||
|
||||
Text highScore = new Text("High Scores");
|
||||
highScore.getStyleClass().add("big-heading");
|
||||
leaderboardBox.getChildren().add(highScore);
|
||||
|
||||
var localScoreHeading = new Text("Local Scores");
|
||||
localScoreHeading.getStyleClass().add("heading");
|
||||
leaderboardBox.getChildren().add(localScoreHeading);
|
||||
}
|
||||
}
|
||||
@ -90,6 +90,11 @@ public class MenuScene extends BaseScene {
|
||||
leaderboardButton.setFocusTraversable(false);
|
||||
menuBox.getChildren().add(leaderboardButton);
|
||||
|
||||
var settingsButton = new Button("Settings");
|
||||
settingsButton.getStyleClass().add("menu-item");
|
||||
settingsButton.setFocusTraversable(false);
|
||||
menuBox.getChildren().add(settingsButton);
|
||||
|
||||
var quitButton = new Button("Quit");
|
||||
quitButton.getStyleClass().add("menu-item");
|
||||
quitButton.setFocusTraversable(false);
|
||||
@ -98,6 +103,7 @@ public class MenuScene extends BaseScene {
|
||||
|
||||
|
||||
|
||||
|
||||
//Bind the button action to the startGame method in the menu
|
||||
singlePlayerButton.setOnAction(this::startGame);
|
||||
multiPlayerButton.setOnAction(this::startGame);
|
||||
|
||||
160
src/main/java/uk/ac/soton/comp1206/scene/ScoresScene.java
Normal file
160
src/main/java/uk/ac/soton/comp1206/scene/ScoresScene.java
Normal file
@ -0,0 +1,160 @@
|
||||
package uk.ac.soton.comp1206.scene;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import javafx.scene.text.*;
|
||||
import uk.ac.soton.comp1206.network.Communicator;
|
||||
import uk.ac.soton.comp1206.ui.GamePane;
|
||||
import uk.ac.soton.comp1206.ui.GameWindow;
|
||||
import uk.ac.soton.comp1206.component.Leaderboard;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ScoresScene extends BaseScene {
|
||||
|
||||
Logger logger = LogManager.getLogger(ScoresScene.class);
|
||||
|
||||
private SimpleListProperty<Pair<String, Integer>> localScores = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||
private SimpleListProperty<Pair<String, Integer>> onlineScores = new SimpleListProperty<>(FXCollections.observableArrayList());
|
||||
|
||||
private Leaderboard onlineLeaderboard = new Leaderboard(onlineScores);
|
||||
|
||||
/**
|
||||
* Create a new scene, passing in the GameWindow the scene will be displayed in
|
||||
*
|
||||
* @param gameWindow the game window
|
||||
*/
|
||||
public ScoresScene(GameWindow gameWindow) {
|
||||
super(gameWindow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialise() {
|
||||
this.onlineScores = this.getOnlineScores();
|
||||
|
||||
this.scene.setOnKeyPressed(e -> this.gameWindow.startMenu());
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void build() {
|
||||
logger.info("Building " + this.getClass().getName());
|
||||
|
||||
root = new GamePane(gameWindow.getWidth(), gameWindow.getHeight());
|
||||
var leaderboardPane = new StackPane();
|
||||
leaderboardPane.setMaxWidth(gameWindow.getWidth());
|
||||
leaderboardPane.setMaxHeight(gameWindow.getHeight());
|
||||
leaderboardPane.getStyleClass().add("menu-background");
|
||||
root.getChildren().add(leaderboardPane);
|
||||
|
||||
var leaderboardBox = new VBox();
|
||||
leaderboardPane.getChildren().add(leaderboardBox);
|
||||
|
||||
// Set alignment of leaderboardBox to center
|
||||
leaderboardBox.setAlignment(Pos.TOP_CENTER);
|
||||
|
||||
ImageView title = new ImageView(new Image("file:src/main/resources/images/TetrECS.png"));
|
||||
title.setPreserveRatio(true);
|
||||
title.setFitWidth(gameWindow.getWidth() - 100);
|
||||
leaderboardBox.getChildren().add(title);
|
||||
|
||||
Text highScore = new Text("High Scores");
|
||||
highScore.getStyleClass().add("big-heading");
|
||||
leaderboardBox.getChildren().add(highScore);
|
||||
|
||||
var leaderboardHbox = new HBox();
|
||||
leaderboardHbox.setMinWidth(gameWindow.getWidth());
|
||||
leaderboardHbox.setAlignment(Pos.TOP_CENTER);
|
||||
leaderboardBox.getChildren().add(leaderboardHbox);
|
||||
|
||||
var localScoreBox = new VBox();
|
||||
localScoreBox.setAlignment(Pos.CENTER);
|
||||
localScoreBox.setPrefWidth(gameWindow.getWidth() / 2);
|
||||
leaderboardHbox.getChildren().add(localScoreBox);
|
||||
|
||||
var onlineScoreBox = new VBox();
|
||||
onlineScoreBox.setAlignment(Pos.CENTER);
|
||||
onlineScoreBox.setPrefWidth(gameWindow.getWidth() / 2);
|
||||
leaderboardHbox.getChildren().add(onlineScoreBox);
|
||||
|
||||
|
||||
var localScoreHeading = new Text("Local Scores");
|
||||
localScoreHeading.getStyleClass().add("heading");
|
||||
localScoreBox.getChildren().add(localScoreHeading);
|
||||
|
||||
|
||||
var onlineScoreHeading = new Text("Online Scores");
|
||||
onlineScoreHeading.getStyleClass().add("heading");
|
||||
onlineScoreBox.getChildren().add(onlineScoreHeading);
|
||||
|
||||
|
||||
onlineScoreBox.getChildren().add(onlineLeaderboard);
|
||||
onlineLeaderboard.setAlignment(Pos.CENTER);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches online scores from the server
|
||||
* @return
|
||||
*/
|
||||
private SimpleListProperty<Pair<String, Integer>> getOnlineScores() {
|
||||
Communicator communicator = gameWindow.getCommunicator();
|
||||
CompletableFuture<SimpleListProperty<Pair<String, Integer>>> futureScores = new CompletableFuture<>();
|
||||
communicator.addListener(response -> {
|
||||
if (response.startsWith("HISCORES")) {
|
||||
logger.info("HISCORES received");
|
||||
String scoreString = response.substring("HISCORES".length()).trim();
|
||||
futureScores.complete(parseHighScores(scoreString, onlineScores
|
||||
));
|
||||
}
|
||||
});
|
||||
communicator.send("HISCORES");
|
||||
|
||||
//Wait for response
|
||||
try {
|
||||
return futureScores.get();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a string of high scores and converts it
|
||||
* @param scoresString
|
||||
* @return SimpleListProperty of high scores
|
||||
*/
|
||||
private SimpleListProperty<Pair<String, Integer>> parseHighScores(String scoresString, SimpleListProperty<Pair<String, Integer>> highScoresList) {
|
||||
|
||||
String[] lines = scoresString.split("\n");
|
||||
for (String line : lines) {
|
||||
String[] parts = line.split(":");
|
||||
if (parts.length == 2) {
|
||||
String name = parts[0].trim();
|
||||
int score = Integer.parseInt(parts[1].trim());
|
||||
highScoresList.add(new Pair<>(name, score));
|
||||
}
|
||||
}
|
||||
|
||||
return highScoresList;
|
||||
}
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class GameWindow {
|
||||
}
|
||||
|
||||
public void showLeaderBoard() {
|
||||
loadScene(new LeaderBoard(this));
|
||||
loadScene(new ScoresScene(this));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -164,6 +164,8 @@
|
||||
|
||||
.leaderboard {
|
||||
-fx-font-size: 16px;
|
||||
-fx-fill: yellow;
|
||||
-fx-font-family: 'Orbitron';
|
||||
}
|
||||
|
||||
.gameBox {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user