Merge remote-tracking branch 'origin/develop' into NewUI_merge

# Conflicts:
#	src/main/java/seng302/gameServer/GameState.java
#	src/main/java/seng302/gameServer/MainServerThread.java
#	src/main/java/seng302/gameServer/ServerToClientThread.java
#	src/main/java/seng302/visualiser/GameClient.java
#	src/main/java/seng302/visualiser/GameView.java
#	src/main/java/seng302/visualiser/controllers/FinishScreenViewController.java
#	src/main/java/seng302/visualiser/controllers/LobbyController.java
#	src/main/java/seng302/visualiser/controllers/RaceViewController.java
#	src/main/java/seng302/visualiser/controllers/StartScreenController.java
#	src/main/resources/views/LobbyView.fxml
#	src/main/resources/views/RaceView.fxml
#	src/main/resources/views/StartScreenView.fxml
This commit is contained in:
Haoming Yin
2017-09-11 18:15:08 +12:00
43 changed files with 1303 additions and 312 deletions
@@ -18,6 +18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatActionMessage;
import seng302.gameServer.messages.ChatterMessage;
import seng302.gameServer.messages.ClientType;
import seng302.gameServer.messages.CustomizeRequestMessage;
import seng302.gameServer.messages.CustomizeRequestType;
@@ -281,9 +282,17 @@ public class ClientToServerThread implements Runnable {
* @param message The given message type.
*/
private void sendBoatActionMessage(BoatActionMessage message) {
sendByteBuffer(message.getBuffer());
}
public void sendChatterMessage(String message) {
sendByteBuffer(new ChatterMessage(clientId, message).getBuffer());
}
private void sendByteBuffer(byte[] bytes) {
if (clientId != -1) {
try {
os.write(message.getBuffer());
os.write(bytes);
} catch (IOException e) {
logger.warn("IOException on attempting to sendBoatAction from Client");
notifyDisconnectListeners("Cannot communicate with server");
@@ -292,7 +301,7 @@ public class ClientToServerThread implements Runnable {
}
}
private void closeSocket() {
public void closeSocket() {
try {
socket.close();
socketOpen = false;
@@ -1,10 +1,13 @@
package seng302.visualiser;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.TimeZone;
import javafx.application.Platform;
@@ -14,14 +17,17 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import seng302.gameServer.GameStages;
import javafx.util.Pair;
import seng302.gameServer.GameState;
import seng302.gameServer.MainServerThread;
import seng302.gameServer.ServerDescription;
import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatStatus;
import seng302.gameServer.messages.YachtEventType;
import seng302.model.ClientYacht;
import seng302.model.RaceState;
import seng302.model.stream.packets.StreamPacket;
@@ -32,6 +38,7 @@ import seng302.model.stream.parser.RaceStatusData;
import seng302.model.stream.parser.YachtEventData;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.utilities.Sounds;
import seng302.utilities.StreamParser;
import seng302.utilities.XMLGenerator;
import seng302.utilities.XMLParser;
@@ -56,6 +63,8 @@ public class GameClient {
private RaceState raceState = new RaceState();
private LobbyController lobbyController;
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
/**
@@ -75,12 +84,11 @@ public class GameClient {
public void runAsClient(String ipAddress, Integer portNumber) {
try {
startClientToServerThread(ipAddress, portNumber);
// socketThread.addDisconnectionListener((cause) -> {
// showConnectionError(cause);
// Platform.runLater(this::loadStartScreen);
// });
socketThread.addDisconnectionListener((cause) -> {
showConnectionError(cause);
tearDownConnection();
Platform.runLater(this::loadStartScreen);
});
socketThread.addStreamObserver(this::parsePackets);
ViewManager.getInstance().setPlayerList(clientLobbyList);
@@ -203,9 +211,19 @@ public class GameClient {
raceView = fxmlLoader.getController();
ClientYacht player = allBoatsMap.get(socketThread.getClientId());
raceView.loadRace(allBoatsMap, courseData, raceState, player);
raceView.getSendPressedProperty().addListener((obs, old, isPressed) -> {
if (isPressed) {
formatAndSendChatMessage(raceView.readChatInput());
}
});
}
private void loadFinishScreenView() {
Sounds.stopMusic();
Sounds.stopSoundEffects();
Sounds.playFinishMusic();
FXMLLoader fxmlLoader = loadFXMLToHolder("/views/FinishScreenView.fxml");
FinishScreenViewController controller = fxmlLoader.getController();
controller.setFinishers(raceState.getPlayerPositions());
@@ -233,6 +251,7 @@ public class GameClient {
switch (packet.getType()) {
case RACE_STATUS:
processRaceStatusUpdate(StreamParser.extractRaceStatus(packet));
if (raceState.getTimeTillStart() <= 5000) {
startRaceIfAllDataReceived();
}
@@ -288,8 +307,21 @@ public class GameClient {
break;
case YACHT_EVENT_CODE:
showCollisionAlert(StreamParser.extractYachtEventCode(packet));
YachtEventData yachtEventData = StreamParser.extractYachtEventCode(packet);
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
showCollisionAlert(StreamParser.extractYachtEventCode(packet));
} else if (yachtEventData.getEventId() == YachtEventType.TOKEN.getCode()) {
showPickUp();
}
break;
case CHATTER_TEXT:
Pair<Integer, String> playerIdMessagePair = StreamParser
.extractChatterText(packet);
raceView.updateChatHistory(
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
playerIdMessagePair.getValue()
);
}
}
}
@@ -333,7 +365,6 @@ public class GameClient {
if (allXMLReceived()) {
ClientYacht clientYacht = allBoatsMap.get(roundingData.getBoatId());
clientYacht.roundMark(
courseData.getCompoundMarks().get(roundingData.getMarkId()),
roundingData.getTimeStamp(),
raceState.getRaceTime() - roundingData.getTimeStamp()
);
@@ -348,6 +379,9 @@ public class GameClient {
for (ClientYacht yacht : allBoatsMap.values()) {
if (yacht.getBoatStatus() != BoatStatus.FINISHED.getCode()) {
raceFinished = false;
} else if (!finishedBoats.contains(yacht)) {
finishedBoats.add(yacht);
Sounds.playFinishSound();
}
}
@@ -363,6 +397,7 @@ public class GameClient {
}
if (raceFinished) {
Sounds.playFinishSound();
close();
loadFinishScreenView();
}
@@ -385,7 +420,13 @@ public class GameClient {
* Handle the key-pressed event from the text field.
* @param e The key event triggering this call
*/
public void keyPressed(KeyEvent e) {
private void keyPressed(KeyEvent e) {
if (raceView.isChatInputFocused()) {
if (e.getCode() == KeyCode.ENTER) {
formatAndSendChatMessage(raceView.readChatInput());
}
return;
}
switch (e.getCode()) {
case SPACE: // align with vmg
socketThread.sendBoatAction(BoatAction.VMG); break;
@@ -394,12 +435,16 @@ public class GameClient {
case PAGE_DOWN: // downwind
socketThread.sendBoatAction(BoatAction.DOWNWIND); break;
case ENTER: // tack/gybe
// if chat box is active take whatever is in there and send it to server
socketThread.sendBoatAction(BoatAction.TACK_GYBE); break;
}
}
public void keyReleased(KeyEvent e) {
private void keyReleased(KeyEvent e) {
if (raceView.isChatInputFocused()) {
return;
}
switch (e.getCode()) {
//TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
case SHIFT: // sails in/sails out
@@ -420,31 +465,43 @@ public class GameClient {
* Tells race view to show a collision animation.
*/
private void showCollisionAlert(YachtEventData yachtEventData) {
// 33 is the agreed code to show collision
if (yachtEventData.getEventId() == 33) {
raceState.storeCollision(
allBoatsMap.get(
yachtEventData.getSubjectId().intValue()
)
Sounds.playCrashSound();
raceState.storeCollision(
allBoatsMap.get(
yachtEventData.getSubjectId().intValue()
)
);
}
// TODO: 11/09/17 wmu16 - Add in functionality to viually indicate a pickup to a user
private void showPickUp() {
Sounds.playTokenPickupSound();
}
private void formatAndSendChatMessage(String rawChat) {
if (rawChat.length() > 0) {
socketThread.sendChatterMessage(
new SimpleDateFormat("[HH:mm:ss] ").format(new Date()) +
allBoatsMap.get(socketThread.getClientId()).getShortName() + ": " + rawChat
);
}
}
public void startGame(){
server.startGame();
}
public ClientToServerThread getServerThread() {
return socketThread;
}
public List<String> getPlayerNames(){
return Collections.unmodifiableList(clientLobbyList.sorted());
}
public void stopGame() {
GameState.setCurrentStage(GameStages.CANCELLED);
if (server != null) server.terminate();
if (socketThread != null) socketThread.setSocketToClose();
}
// public void startGame(){
// server.startGame();
// }
//
// public ClientToServerThread getServerThread() {
// return socketThread;
// }
//
// public List<String> getPlayerNames(){
// return Collections.unmodifiableList(clientLobbyList.sorted());
// }
//
// public void stopGame() {
// GameState.setCurrentStage(GameStages.CANCELLED);
// if (server != null) server.terminate();
// if (socketThread != null) socketThread.setSocketToClose();
// }
}
+108 -35
View File
@@ -11,6 +11,8 @@ import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.geometry.Point2D;
import javafx.scene.*;
@@ -24,6 +26,7 @@ import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import javafx.scene.transform.Scale;
import javafx.util.Duration;
import seng302.gameServer.messages.RoundingSide;
import seng302.model.ClientYacht;
@@ -42,6 +45,13 @@ import seng302.visualiser.fxObjects.assets_2D.MarkArrowFactory;
import seng302.visualiser.fxObjects.assets_2D.Marker;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.fxObjects.assets_3D.ModelType;
import seng302.utilities.Sounds;
import seng302.visualiser.fxObjects.AnnotationBox;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.visualiser.fxObjects.CourseBoundary;
import seng302.visualiser.fxObjects.Gate;
import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.Marker;
import seng302.visualiser.map.Boundary;
import seng302.visualiser.map.CanvasMap;
@@ -51,7 +61,7 @@ import seng302.visualiser.map.CanvasMap;
public class GameView extends Pane {
private double bufferSize = 50;
private double panelWidth = 1260; // it should be 1280 but, minors 40 to cancel the bias.
private double panelWidth = 1280;
private double panelHeight = 960;
private double canvasWidth = 1100;
private double canvasHeight = 920;
@@ -63,7 +73,7 @@ public class GameView extends Pane {
private double referencePointX, referencePointY;
private double metersPerPixelX, metersPerPixelY;
final double SCALE_DELTA = 1.1;
private boolean isZoom = false;
private Text fpsDisplay = new Text();
private Polygon raceBorder = new CourseBoundary();
@@ -165,6 +175,48 @@ public class GameView extends Pane {
});
initializeTimer();
gameObjects.addAll(mapImage, raceBorder, markers, tokens, pl);
// TODO: 11/09/17 ajm412: do you even zoom bro?
// this.sceneProperty().addListener(((observable, oldValue, scene) -> {
// if (scene != null) {
// setupZoom();
// } else {
// disableZoom();
// }
// }));
//
// this.widthProperty().addListener(new ChangeListener<Number>() {
// @Override
// public void changed(ObservableValue<? extends Number> observable, Number oldValue,
// Number newValue) {
// scaleFactor = getWidth() / panelWidth;
//
// if (panelHeight * scaleFactor < getHeight()) {
// Scale scale = new Scale(scaleFactor, scaleFactor, 0, 0);
// getTransforms().remove(0, getTransforms().size());
// getTransforms().add(scale);
//
// setPrefWidth(getWidth() / scaleFactor);
// setPrefHeight(getHeight() / scaleFactor);
// }
// }
// });
//
// this.heightProperty().addListener(new ChangeListener<Number>() {
// @Override
// public void changed(ObservableValue<? extends Number> observable, Number oldValue,
// Number newValue) {
// scaleFactor = getHeight() / panelHeight;
//
// if (panelWidth * scaleFactor < getWidth()) {
// Scale scale = new Scale(scaleFactor, scaleFactor, 0, 0);
// getTransforms().remove(0, getTransforms().size());
// getTransforms().add(scale);
//
// setPrefWidth(getWidth() / scaleFactor);
// setPrefHeight(getHeight() / scaleFactor);
// }
// }
// });
}
private void initializeTimer() {
@@ -456,18 +508,18 @@ public class GameView extends Pane {
raceBorder.getPoints().setAll(boundaryPoints);
}
/**
* Rescales the race to the size of the window.
*
* @param limitingCoordinates the set of geo points that contains the extremities of the race.
*/
private void rescaleRace(List<GeoPoint> limitingCoordinates) {
//Check is called once to avoid unnecessarily change the course limits once the race is running
findMinMaxPoint(limitingCoordinates);
double minLonToMaxLon = scaleRaceExtremities();
calculateReferencePointLocation(minLonToMaxLon);
// drawGoogleMap();
}
// /**
// * Rescales the race to the size of the window.
// *
// * @param limitingCoordinates the set of geo points that contains the extremities of the race.
// */
// private void rescaleRace(List<GeoPoint> limitingCoordinates) {
// //Check is called once to avoid unnecessarily change the course limits once the race is running
// findMinMaxPoint(limitingCoordinates);
// double minLonToMaxLon = scaleRaceExtremities();
// calculateReferencePointLocation(minLonToMaxLon);
//// drawGoogleMap();
// }
/**
* Replaces all tokens in the course with those passed in
@@ -483,27 +535,46 @@ public class GameView extends Pane {
tokenObject.setLayoutY(location.getY());
mapTokens.add(tokenObject);
}
Platform.runLater(() -> {
tokens.getChildren().clear();
tokens.getChildren().addAll(mapTokens);
});
}
// TODO: 16/08/17 initialize zooming internal to GameView only
// // TODO: 16/08/17 initialize zooming internal to GameView only
// /**
// * Enables zoom. Has to be called after this is added to a scene.
// */
// private void setupZoom() {
// this.getScene().addEventHandler(KeyEvent.KEY_PRESSED, (event) -> {
// if (event.getCode() == KeyCode.Z) {
// zoomIn();
// } else if (event.getCode() == KeyCode.X) {
// zoomOut();
// }
// });
// enableZoom();
// }
////
// public void enableZoom() {
// isZoom = true;
// }
//
// public void disableZoom() {
// isZoom = false;
// }
/**
* Enables zoom. Has to be called after this is added to a scene.
* Rescales the race to the size of the window.
*
* @param limitingCoordinates the set of geo points that contains the extremities of the race.
*/
public void enableZoom () {
if (this.getScene() != null) {
this.getScene().addEventHandler(KeyEvent.KEY_PRESSED, (event) -> {
if (event.getCode() == KeyCode.Z) {
zoomIn();
} else if (event.getCode() == KeyCode.X) {
zoomOut();
}
});
}
private void rescaleRace(List<GeoPoint> limitingCoordinates) {
//Check is called once to avoid unnecessarily change the course limits once the race is running
findMinMaxPoint(limitingCoordinates);
double minLonToMaxLon = scaleRaceExtremities();
calculateReferencePointLocation(minLonToMaxLon);
// drawGoogleMap();
}
private void setSelectedBoat(BoatObject bo, Boolean isSelected) {
@@ -825,17 +896,11 @@ public class GameView extends Pane {
playerYacht.addMarkRoundingListener(this::updateMarkArrows);
}
private void updateMarkArrows (ClientYacht yacht, CompoundMark compoundMark, int legNumber) {
private void updateMarkArrows (ClientYacht yacht, int legNumber) {
//Only show arrows for this and next leg.
// System.out.println(markerObjects);
if (compoundMark != null) {
for (Mark mark : compoundMark.getMarks()) {
// System.out.println("markerObjects.get(mark) = " + markerObjects.get(mark));
markerObjects.get(mark).showNextExitArrow();
}
}
CompoundMark nextMark = null;
if (legNumber < course.size() - 1) {
Sounds.playMarkRoundingSound();
nextMark = course.get(legNumber);
for (Mark mark : nextMark.getMarks()) {
markerObjects.get(mark).showNextEnterArrow();
@@ -849,6 +914,14 @@ public class GameView extends Pane {
}
}
}
if (legNumber - 1 >= 0) {
CompoundMark thisMark = course.get(Math.max(0, legNumber - 1));
if (thisMark != nextMark) {
for (Mark mark : thisMark.getMarks()) {
markerObjects.get(mark).showNextExitArrow();
}
}
}
}
/**
@@ -7,6 +7,7 @@ import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import seng302.gameServer.messages.CustomizeRequestType;
import seng302.utilities.Sounds;
import seng302.visualiser.ClientToServerThread;
public class CustomizationController_old {
@@ -34,7 +35,8 @@ public class CustomizationController_old {
@FXML
public void submitCustomization() {
System.out.println("Attempting to send");
Sounds.playButtonClick();
// System.out.println("Attempting to send");
socketThread.sendCustomizationRequest(CustomizeRequestType.NAME, nameField.getText().getBytes());
// TODO: 16/08/17 ajm412: Turn colors into byte array.
Color color = boatColorPicker.getValue();
@@ -15,10 +15,12 @@ import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import seng302.model.ClientYacht;
import seng302.utilities.Sounds;
public class FinishScreenViewController implements Initializable {
@@ -85,6 +87,12 @@ public class FinishScreenViewController implements Initializable {
}
public void switchToStartScreenView() {
setContentPane("/views/StartScreenView_old.fxml");
Sounds.playButtonClick();
//TODO merge fix
setContentPane("/views/StartScreenView.fxml");
}
public void playButtonHoverSound(MouseEvent mouseEvent) {
Sounds.playHoverSound();
}
}
@@ -2,6 +2,8 @@ package seng302.visualiser.controllers;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
@@ -17,7 +19,8 @@ import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Slider;
import javafx.scene.layout.AnchorPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
@@ -32,10 +35,15 @@ import seng302.model.RaceState;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.utilities.Sounds;
import seng302.visualiser.GameView;
import seng302.visualiser.controllers.annotations.Annotation;
import seng302.visualiser.GameView3D;
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
import seng302.visualiser.fxObjects.BoatObject;
import seng302.visualiser.fxObjects.ChatHistory;
import seng302.visualiser.fxObjects.assets_2D.BoatObject;
import seng302.visualiser.fxObjects.assets_2D.WindArrow;
@@ -48,6 +56,16 @@ import java.util.concurrent.TimeUnit;
*/
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
private final int CHAT_LIMIT = 128;
@FXML
private Pane basePane;
@FXML
private Button chatSend;
@FXML
private Pane chatHistoryHolder;
@FXML
private TextField chatInput;
@FXML
private LineChart<String, Double> raceSparkLine;
@FXML
@@ -60,6 +78,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private Text timerLabel;
@FXML
private StackPane contentAnchorPane;
private GridPane contentGridPane;
@FXML
private AnchorPane rvAnchorPane;
@FXML
@@ -84,13 +103,18 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private GameView3D gameView;
private RaceState raceState;
private ChatHistory chatHistory;
private Timeline timerTimeline;
private Timer timer = new Timer();
private List<Series<String, Double>> sparkLineData = new ArrayList<>();
private ImportantAnnotationsState importantAnnotations;
private Polyline windArrow = new WindArrow(Color.LIGHTGRAY);
private ObservableList<ClientYacht> selectionComboBoxList = FXCollections.observableArrayList();
public void initialize() {
Sounds.stopMusic();
Sounds.playRaceMusic();
// Load a default important annotation state
//importantAnnotations = new ImportantAnnotationsState();
@@ -103,6 +127,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
//sparklineYAxis.setTickMarkVisible(false);
//positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
raceSparkLine.visibleProperty().setValue(false);
raceSparkLine.getYAxis().setAutoRanging(false);
sparklineYAxis.setTickMarkVisible(false);
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
//selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
// rvAnchorPane.prefWidthProperty().bind(ViewManager.getInstance().getDecorator().widthProperty());
@@ -112,6 +140,28 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// windArrow.setLayoutX(windArrowHolder.getWidth() / 2);
// windArrow.setLayoutY(windArrowHolder.getHeight() / 2);
selectAnnotationBtn.setOnAction(event -> loadSelectAnnotationView());
chatInput.lengthProperty().addListener((obs, oldLen, newLen) -> {
if (newLen.intValue() > CHAT_LIMIT) {
chatInput.setText(chatInput.getText().substring(0, CHAT_LIMIT));
}
});
chatHistory = new ChatHistory();
chatHistoryHolder.getChildren().addAll(chatHistory);
chatHistory.prefWidthProperty().bind(
chatHistoryHolder.widthProperty()
);
chatHistory.prefHeightProperty().bind(
chatHistoryHolder.heightProperty()
);
// chatHistory.setFitToWidth(true);
// chatHistory.setFitToHeight(true);
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
// chatHistory.setScrollTop(Double.MAX_VALUE);
// });
contentGridPane.setOnMouseClicked((event) ->
contentGridPane.requestFocus()
);
}
public void loadRace (
@@ -123,12 +173,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
this.markers = raceData.getCompoundMarks();
this.raceState = raceState;
initializeUpdateTimer();
initialiseFPSCheckBox();
initialiseAnnotationSlider();
initialiseBoatSelectionComboBox();
initialiseSparkLine();
raceState.getPlayerPositions().addListener((ListChangeListener<ClientYacht>) c -> {
while (c.next()) {
if (c.wasPermutated()) {
@@ -165,6 +209,33 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// updateWindSpeed(raceState.getWindSpeed());
// });
// gameView.setWindDir(raceState.windDirectionProperty().doubleValue());
//TODO extract chat stuff
// raceState.addCollisionListener(gameView::drawCollision);
// raceState.windDirectionProperty().addListener((obs, oldDirection, newDirection) -> {
// gameView.setWindDir(newDirection.doubleValue());
// updateWindDirection(newDirection.doubleValue());
// });
// raceState.windSpeedProperty().addListener((obs, oldSpeed, newSpeed) -> {
// updateWindSpeed(newSpeed.doubleValue());
// });
// updateWindDirection(raceState.windDirectionProperty().doubleValue());
// updateWindSpeed(raceState.getWindSpeed());
// gameView.setWindDir(raceState.windDirectionProperty().doubleValue());
// chatInput.focusedProperty().addListener((obs, oldValue, newValue) -> {
// if (newValue) {
// gameView.disableZoom();
// } else {
// gameView.enableZoom();
// }
// });
// Platform.runLater(() -> {
// initializeUpdateTimer();
// initialiseFPSCheckBox();
// initialiseAnnotationSlider();
// initialiseBoatSelectionComboBox();
// initialiseSparkLine();
// });
}
/**
@@ -315,13 +386,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
)
);
}
// XYChart.Series<String, Double> positionData = sparkLineData.get(yacht.getSourceID());
// positionData.getData().add(
// new XYChart.Data<>(
// Integer.toString(legNumber),
// 1.0 + participants.size() - yacht.getPlacing()
// )
// );
}
@@ -551,6 +615,15 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// if (selectedBoat != null) {
// gameView.selectBoat(selectedBoat);
// }
// });
//TODO uncomment out
// selectionComboBoxList.setAll(participants.values());
// yachtSelectionComboBox.setItems(selectionComboBoxList);
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
// if (selectedBoat != null) {
// gameView.selectBoat(selectedBoat);
// }
// });
}
@@ -561,9 +634,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml"));
try {
contentAnchorPane.getChildren().removeAll();
contentAnchorPane.getChildren().clear();
contentAnchorPane.getChildren().addAll((Pane) loader.load());
contentGridPane.getChildren().removeAll();
contentGridPane.getChildren().clear();
contentGridPane.getChildren().addAll((Pane) loader.load());
} catch (javafx.fxml.LoadException e) {
System.err.println(e.getCause().toString());
@@ -632,4 +705,24 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
gameView.updateBorder(raceData.getCourseLimit());
gameView.updateTokens(raceData.getTokens());
}
public ReadOnlyBooleanProperty getSendPressedProperty() {
return chatSend.pressedProperty();
}
public boolean isChatInputFocused() {
return chatInput.focusedProperty().getValue();
}
public String readChatInput() {
String chat = chatInput.getText();
chatInput.clear();
basePane.requestFocus();
return chat;
}
public void updateChatHistory(Paint playerColour, String newMessage) {
Platform.runLater(() -> chatHistory.addMessage(playerColour, newMessage));
}
}
@@ -6,6 +6,7 @@ import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
@@ -19,10 +20,14 @@ import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import seng302.gameServer.ServerAdvertiser;
import seng302.gameServer.ServerDescription;
import seng302.gameServer.GameState;
import seng302.utilities.Sounds;
import seng302.visualiser.GameClient;
import seng302.visualiser.ServerListener;
import seng302.visualiser.ServerListenerDelegate;
@@ -49,6 +54,23 @@ public class StartScreenController implements Initializable{
private Logger logger = LoggerFactory.getLogger(StartScreenController.class);
private List<ServerDescription> servers;
public void initialize(URL url, ResourceBundle resourceBundle) {
Sounds.stopMusic();
Sounds.stopSoundEffects();
Sounds.playMenuMusic();
if (Sounds.isMusicMuted()) {
muteMusicButton.setText("UnMute Music");
} else {
muteMusicButton.setText("Mute Music");
}
if (Sounds.isSoundEffectsMuted()) {
muteSoundsButton.setText("UnMute Sounds");
} else {
muteSoundsButton.setText("Mute Sounds");
}
Sounds.setMutes();
// gameClient = new GameClient(holder);
}
private void setInitialDropShadow(){
DropShadow dropShadow = new DropShadow();
@@ -57,7 +79,25 @@ public class StartScreenController implements Initializable{
dropShadow.setOffsetY(4.0);
dropShadow.setColor(Color.color(0, 0, 0, 0.5));
headText.setEffect(dropShadow);
/**
* Creates an instance of GameClient and runs it as a host.
*/
@FXML
public void hostButtonPressed() {
Sounds.playButtonClick();
gameClient = new GameClient(holder);
gameClient.runAsHost(getLocalHostIp(), 4942);
}
/**
* Creates an instance of GameClient and runs it has a client.
*/
@FXML
public void connectButtonPressed() {
// TODO: 10/07/17 wmu16 - Finish function
Sounds.playButtonClick();
gameClient = new GameClient(holder);
gameClient.runAsClient(ipTextField.getText().trim().toLowerCase(), 4942);
}
private void preloadServerListView(){
@@ -88,4 +128,27 @@ public class StartScreenController implements Initializable{
}
public void toggleMusic(ActionEvent actionEvent) {
Sounds.toggleMuteMusic();
Sounds.playButtonClick();
if (Sounds.isMusicMuted()) {
muteMusicButton.setText("UnMute Music");
} else {
muteMusicButton.setText("Mute Music");
}
}
public void toggleSounds(ActionEvent actionEvent) {
Sounds.toggleMuteEffects();
Sounds.playButtonClick();
if (Sounds.isSoundEffectsMuted()) {
muteSoundsButton.setText("UnMute Sounds");
} else {
muteSoundsButton.setText("Mute Sounds");
}
}
public void playButtonHoverSound(MouseEvent mouseEvent) {
Sounds.playHoverSound();
}
}
@@ -0,0 +1,75 @@
package seng302.visualiser.fxObjects;
import java.util.Arrays;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Background;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
/**
* Extension of a ScrollPane that contains a TextFlow. Has an addMessage() function to parse and
* display chatter text.
*/
public class ChatHistory extends ScrollPane {
private TextFlow textFlow = new TextFlow();
public ChatHistory() {
this.setContent(textFlow);
this.setFitToWidth(true);
this.setFitToHeight(true);
this.setMaxHeight(Double.MAX_VALUE);
this.setMaxWidth(Double.MAX_VALUE);
this.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
this.setHbarPolicy(ScrollBarPolicy.NEVER);
this.lookup(".scroll-pane").setStyle("-fx-background: rgba(255, 255, 255, 0.1); -fx-background-color: rgba(255, 255, 255, 0.1);");
this.textFlow.setStyle(
"-fx-background: rgba(255, 255, 255, 0.1); -fx-background-color: rgba(255, 255, 255, 0.1);"
);
//This makes the window auto scroll.
textFlow.getChildren().addListener((ListChangeListener<Node>) c ->
this.setVvalue(1.0)
);
//This just makes it so that the ChatHistory is on focus it passes it off to the parent.
this.parentProperty().addListener((obs, old, parent) ->
this.focusedProperty().addListener((obsVal, oldVal, onFocus) -> {
if (onFocus) {
parent.requestFocus();
}
})
);
}
/**
* Adds a message to chat history. Messages should be either of the form:
* "[HH:MM:ss] player_name: message_text" or
* "SERVER: message_text"
* @param colour The colour of the user sending the message
* @param Text The chatter text message to be displayed
*/
public void addMessage (Paint colour, String Text) {
String[] words = Text.split(":");
if (words[0].trim().equals("SERVER")) {
Text text = new Text(Text + "\n\n");
text.setStyle("-fx-font-weight: bolder");
textFlow.getChildren().add(text);
} else {
Text timePlayer = new Text(
String.join(":", Arrays.copyOfRange(words, 0, 3)) + ":"
);
timePlayer.setStyle("-fx-font-weight: bold");
timePlayer.setFill(colour);
Text message = new Text(
String.join(":", Arrays.copyOfRange(words, 3, words.length)) + "\n\n"
);
message.wrappingWidthProperty().bind(this.widthProperty());
textFlow.getChildren().addAll(timePlayer, message);
}
}
}