Merge branch 'develop' into story1275_host_customization

# Conflicts:
#	src/main/java/seng302/gameServer/GameState.java
#	src/main/java/seng302/gameServer/ServerToClientThread.java
#	src/main/java/seng302/model/ServerYacht.java
#	src/main/java/seng302/visualiser/ClientToServerThread.java
#	src/main/java/seng302/visualiser/controllers/LobbyController.java
#	src/test/java/seng302/models/YachtTest.java
This commit is contained in:
Calum
2017-09-25 23:25:33 +13:00
54 changed files with 1393 additions and 452 deletions
@@ -9,7 +9,17 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import seng302.gameServer.messages.BoatAction; import seng302.gameServer.messages.BoatAction;
@@ -27,6 +37,23 @@ import seng302.model.Limit;
import seng302.model.Player; import seng302.model.Player;
import seng302.model.PolarTable; import seng302.model.PolarTable;
import seng302.model.ServerYacht; import seng302.model.ServerYacht;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatStatus;
import seng302.gameServer.messages.ChatterMessage;
import seng302.gameServer.messages.CustomizeRequestType;
import seng302.gameServer.messages.MarkRoundingMessage;
import seng302.gameServer.messages.MarkType;
import seng302.gameServer.messages.Message;
import seng302.gameServer.messages.RoundingBoatStatus;
import seng302.gameServer.messages.YachtEventCodeMessage;
import seng302.gameServer.messages.YachtEventType;
import seng302.model.GeoPoint;
import seng302.model.Limit;
import seng302.model.Player;
import seng302.model.PolarTable;
import seng302.model.ServerYacht;
import seng302.model.mark.CompoundMark; import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark; import seng302.model.mark.Mark;
import seng302.model.mark.MarkOrder; import seng302.model.mark.MarkOrder;
@@ -34,6 +61,8 @@ import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.token.Token; import seng302.model.token.Token;
import seng302.model.token.TokenType; import seng302.model.token.TokenType;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.utilities.XMLParser;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* A Static class to hold information about the current state of the game (model) * A Static class to hold information about the current state of the game (model)
@@ -237,7 +266,6 @@ public class GameState implements Runnable {
System.out.println("[GameState] interrupted exception"); System.out.println("[GameState] interrupted exception");
} }
if (currentStage == GameStages.PRE_RACE || currentStage == GameStages.RACING) { if (currentStage == GameStages.PRE_RACE || currentStage == GameStages.RACING) {
// System.out.println("update");
update(); update();
} }
} }
@@ -264,6 +292,12 @@ public class GameState implements Runnable {
case DOWNWIND: case DOWNWIND:
playerYacht.turnDownwind(); playerYacht.turnDownwind();
break; break;
case CONTINUOUSLY_TURNING:
playerYacht.setContinuouslyTurning(true);
break;
case DEFAULT_TURNING:
playerYacht.setContinuouslyTurning(false);
break;
} }
} }
@@ -442,8 +476,7 @@ public class GameState implements Runnable {
private void updateVelocity(ServerYacht yacht) { private void updateVelocity(ServerYacht yacht) {
Double trueWindAngle = Math.abs(windDirection - yacht.getHeading()); Double trueWindAngle = Math.abs(windDirection - yacht.getHeading());
Double boatSpeedInKnots = PolarTable.getBoatSpeed(getWindSpeedKnots(), trueWindAngle); Double boatSpeedInKnots = PolarTable.getBoatSpeed(getWindSpeedKnots(), trueWindAngle);
Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots) * speedMultiplier; Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots) * speedMultiplier * yacht.getMaxSpeedMultiplier();
System.out.println(maxBoatSpeed);
if (yacht.getPowerUp() != null) { if (yacht.getPowerUp() != null) {
if (yacht.getPowerUp().equals(TokenType.BOOST)) { if (yacht.getPowerUp().equals(TokenType.BOOST)) {
// TODO: 11/09/17 wmu16 CHANGE THIS TO MAGIC NUMBER // TODO: 11/09/17 wmu16 CHANGE THIS TO MAGIC NUMBER
@@ -455,17 +488,17 @@ public class GameState implements Runnable {
// TODO: 15/08/17 remove magic numbers from these equations. // TODO: 15/08/17 remove magic numbers from these equations.
if (yacht.getSailIn()) { if (yacht.getSailIn()) {
if (currentVelocity < maxBoatSpeed - 500) { if (currentVelocity < maxBoatSpeed - 500) {
yacht.changeVelocity(maxBoatSpeed / 100); yacht.changeVelocity((maxBoatSpeed / 100) * yacht.getAccelerationMultiplier());
} else if (currentVelocity > maxBoatSpeed + 500) { } else if (currentVelocity > maxBoatSpeed + 500) {
yacht.changeVelocity(-currentVelocity / 200); yacht.changeVelocity((-currentVelocity / 200) * yacht.getAccelerationMultiplier());
} else { } else {
yacht.setCurrentVelocity(maxBoatSpeed); yacht.setCurrentVelocity((maxBoatSpeed) * yacht.getAccelerationMultiplier());
} }
} else { } else {
if (currentVelocity > 3000) { if (currentVelocity > 3000) {
yacht.changeVelocity(-currentVelocity / 200); yacht.changeVelocity((-currentVelocity / 200) * yacht.getAccelerationMultiplier());
} else if (currentVelocity > 100) { } else if (currentVelocity > 100) {
yacht.changeVelocity(-currentVelocity / 50); yacht.changeVelocity((-currentVelocity / 50) * yacht.getAccelerationMultiplier());
} else if (currentVelocity <= 100) { } else if (currentVelocity <= 100) {
yacht.setCurrentVelocity(0d); yacht.setCurrentVelocity(0d);
} }
@@ -696,6 +729,9 @@ public class GameState implements Runnable {
int blue = customizeData[2] & 0xFF; int blue = customizeData[2] & 0xFF;
Color yachtColor = Color.rgb(red, green, blue); Color yachtColor = Color.rgb(red, green, blue);
playerYacht.setBoatColor(yachtColor); playerYacht.setBoatColor(yachtColor);
} else if (requestType.equals(CustomizeRequestType.SHAPE)) {
String type = new String(customizeData);
playerYacht.setBoatType(BoatMeshType.valueOf(type));
} }
} }
@@ -30,6 +30,7 @@ import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData; import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.utilities.StreamParser; import seng302.utilities.StreamParser;
import seng302.utilities.XMLGenerator; import seng302.utilities.XMLGenerator;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.utilities.XMLParser; import seng302.utilities.XMLParser;
/** /**
@@ -104,7 +105,7 @@ public class ServerToClientThread implements Runnable {
String fName = "Player " + GameState.getNumberOfPlayers().toString(); String fName = "Player " + GameState.getNumberOfPlayers().toString();
String lName = ""; String lName = "";
ServerYacht yacht = new ServerYacht( ServerYacht yacht = new ServerYacht(
"Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ" BoatMeshType.DINGHY, sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ"
); );
player = new Player(socket, yacht); player = new Player(socket, yacht);
@@ -14,7 +14,9 @@ public enum BoatAction {
TACK_GYBE(4), TACK_GYBE(4),
UPWIND(5), UPWIND(5),
DOWNWIND(6), DOWNWIND(6),
MAINTAIN_HEADING(7); MAINTAIN_HEADING(7),
CONTINUOUSLY_TURNING(8),
DEFAULT_TURNING(9);
private final int type; private final int type;
private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>(); private static final Map<Integer, BoatAction> intToTypeMap = new HashMap<>();
@@ -5,19 +5,19 @@ package seng302.gameServer.messages;
*/ */
public class BoatActionMessage extends Message{ public class BoatActionMessage extends Message{
private final MessageType MESSAGE_TYPE = MessageType.BOAT_ACTION; private final MessageType MESSAGE_TYPE = MessageType.BOAT_ACTION;
private final int MESSAGE_SIZE = 1; private final int MESSAGE_SIZE = 5;
private BoatAction actionType; private BoatAction actionType;
public BoatActionMessage(BoatAction actionType) { public BoatActionMessage(BoatAction actionType, int sourceId) {
this.actionType = actionType; this.actionType = actionType;
setHeader(new Header(MessageType.BOAT_ACTION, 0, (short) 1)); // the second variable is the source id setHeader(new Header(MessageType.BOAT_ACTION, sourceId, (short) MESSAGE_SIZE)); // the second variable is the source id
allocateBuffer(); allocateBuffer();
writeHeaderToBuffer(); writeHeaderToBuffer();
// Write message fields // Write message fields
putInt(actionType.getValue(), 1); putInt(actionType.getValue(), 1);
putInt(sourceId, 4);
writeCRC(); writeCRC();
rewind(); rewind();
} }
@Override @Override
@@ -4,8 +4,8 @@ package seng302.gameServer.messages;
public class RegistrationRequestMessage extends Message { public class RegistrationRequestMessage extends Message {
private static int MESSAGE_LENGTH = 2; private static int MESSAGE_LENGTH = 2;
public RegistrationRequestMessage(ClientType type){ public RegistrationRequestMessage(ClientType type, int clientID){
setHeader(new Header(MessageType.REGISTRATION_REQUEST, 1, (short) getSize())); setHeader(new Header(MessageType.REGISTRATION_REQUEST, clientID, (short) getSize()));
allocateBuffer(); allocateBuffer();
writeHeaderToBuffer(); writeHeaderToBuffer();
+5 -4
View File
@@ -15,6 +15,7 @@ import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses) * Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
@@ -37,7 +38,7 @@ public class ClientYacht extends Observable {
private Logger logger = LoggerFactory.getLogger(ClientYacht.class); private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
private String boatType; private BoatMeshType boatType;
private Integer sourceId; private Integer sourceId;
private String hullID; //matches HullNum in the XML spec. private String hullID; //matches HullNum in the XML spec.
private String shortName; private String shortName;
@@ -46,7 +47,7 @@ public class ClientYacht extends Observable {
private Integer position; private Integer position;
private Long estimateTimeAtFinish; private Long estimateTimeAtFinish;
private Boolean sailIn = false; private Boolean sailIn = true;
private Integer currentMarkSeqID = 0; private Integer currentMarkSeqID = 0;
private Long markRoundTime; private Long markRoundTime;
private Long timeTillNext; private Long timeTillNext;
@@ -64,7 +65,7 @@ public class ClientYacht extends Observable {
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper(); private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
private Color colour; private Color colour;
public ClientYacht(String boatType, Integer sourceId, String hullID, String shortName, public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
String boatName, String country) { String boatName, String country) {
this.boatType = boatType; this.boatType = boatType;
this.sourceId = sourceId; this.sourceId = sourceId;
@@ -88,7 +89,7 @@ public class ClientYacht extends Observable {
super.addObserver(o); super.addObserver(o);
} }
public String getBoatType() { public BoatMeshType getBoatType() {
return boatType; return boatType;
} }
@@ -0,0 +1,78 @@
package seng302.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javafx.scene.input.KeyCode;
public class GameKeyBind {
private static GameKeyBind instance;
private Map<KeyCode, KeyAction> keyToActionMap;
private Map<KeyAction, KeyCode> actionToKeyMap;
private Boolean continuouslyTurning;
private GameKeyBind() {
setToDefault();
}
public void setToDefault() {
actionToKeyMap = new HashMap<>();
keyToActionMap = new HashMap<>();
continuouslyTurning = false;
// default key bindings
ArrayList<KeyCode> keys = new ArrayList<>();
keys.add(KeyCode.Z);
keys.add(KeyCode.X);
keys.add(KeyCode.SPACE);
keys.add(KeyCode.SHIFT);
keys.add(KeyCode.ENTER);
keys.add(KeyCode.PAGE_UP);
keys.add(KeyCode.PAGE_DOWN);
for (int i = 0; i < 7; i++) {
actionToKeyMap.put(KeyAction.getType(i + 1), keys.get(i));
keyToActionMap.put(keys.get(i), KeyAction.getType(i + 1));
}
}
public static GameKeyBind getInstance() {
if (instance == null) {
instance = new GameKeyBind();
}
return instance;
}
public KeyCode getKeyCode(KeyAction keyAction) {
return instance.actionToKeyMap.get(keyAction);
}
/**
* Binds a key to a key action
*
* @return true if successfully bind
*/
public boolean bindKeyToAction(KeyCode keyCode, KeyAction keyAction) {
if (instance.keyToActionMap.containsKey(keyCode)) {
// if the key has been bound to other action, return false
return false;
} else {
instance.keyToActionMap.put(keyCode, keyAction); // add key -> action
KeyCode oldKeyCode = instance.actionToKeyMap
.get(keyAction); // get old key for the action
instance.keyToActionMap.remove(oldKeyCode); // remove the old key -> action
instance.actionToKeyMap
.replace(keyAction, keyCode); // replace the old key by the newer one
return true;
}
}
public void toggleTurningMode() {
continuouslyTurning = !continuouslyTurning;
}
public Boolean isContinuouslyTurning() {
return continuouslyTurning;
}
}
@@ -0,0 +1,35 @@
package seng302.model;
import java.util.HashMap;
import java.util.Map;
public enum KeyAction {
ZOOM_IN(1),
ZOOM_OUT(2),
VMG(3),
SAILS_STATE(4),
TACK_GYBE(5),
UPWIND(6),
DOWNWIND(7);
private final int type;
private static final Map<Integer, KeyAction> intToTypeMap = new HashMap<>();
static {
for (KeyAction type : KeyAction.values()) {
intToTypeMap.put(type.getValue(), type);
}
}
KeyAction(int type) {
this.type = type;
}
public static KeyAction getType(int value) {
return intToTypeMap.get(value);
}
public int getValue() {
return this.type;
}
}
+78 -40
View File
@@ -9,6 +9,7 @@ import seng302.gameServer.messages.BoatStatus;
import seng302.model.mark.Mark; import seng302.model.mark.Mark;
import seng302.model.token.TokenType; import seng302.model.token.TokenType;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses) * Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
@@ -17,12 +18,14 @@ import seng302.utilities.GeoUtility;
*/ */
public class ServerYacht { public class ServerYacht {
private Logger logger = LoggerFactory.getLogger(ClientYacht.class); private Logger logger = LoggerFactory.getLogger(ServerYacht.class);
public static final Double TURN_STEP = 5.0;
//Boat info //Boat info
private String boatType; private BoatMeshType boatType;
private Double turnStep = 5.0;
private Double maxSpeedMultiplier = 1.0;
private Double turnStepMultiplier = 1.0;
private Double accelerationMultiplier = 1.0;
private Integer sourceId; private Integer sourceId;
private String hullID; //matches HullNum in the XML spec. private String hullID; //matches HullNum in the XML spec.
private String shortName; private String shortName;
@@ -53,10 +56,12 @@ public class ServerYacht {
private TokenType powerUp; private TokenType powerUp;
private Long powerUpStartTime; private Long powerUpStartTime;
//turning mode
private Boolean continuouslyTurning;
public ServerYacht(String boatType, Integer sourceId, String hullID, String shortName, public ServerYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
String boatName, String country) { String boatName, String country) {
this.boatType = boatType; setBoatType(boatType);
this.boatStatus = BoatStatus.PRESTART; this.boatStatus = BoatStatus.PRESTART;
this.sourceId = sourceId; this.sourceId = sourceId;
this.hullID = hullID; this.hullID = hullID;
@@ -77,6 +82,8 @@ public class ServerYacht {
this.hasEnteredRoundingZone = false; this.hasEnteredRoundingZone = false;
this.hasPassedLine = false; this.hasPassedLine = false;
this.hasPassedThroughGate = false; this.hasPassedThroughGate = false;
this.continuouslyTurning = false;
} }
@@ -126,7 +133,7 @@ public class ServerYacht {
* @param amount the amount by which to adjust the boat heading. * @param amount the amount by which to adjust the boat heading.
*/ */
public void adjustHeading(Double amount) { public void adjustHeading(Double amount) {
Double newVal = heading + amount; Double newVal = heading + (amount * turnStepMultiplier);
lastHeading = heading; lastHeading = heading;
heading = (double) Math.floorMod(newVal.longValue(), 360L); heading = (double) Math.floorMod(newVal.longValue(), 360L);
} }
@@ -171,7 +178,7 @@ public class ServerYacht {
if (isAuto) { if (isAuto) {
turnTowardsHeading(autoHeading); turnTowardsHeading(autoHeading);
if (Math.abs(heading - autoHeading) if (Math.abs(heading - autoHeading)
<= TURN_STEP) { //Cancel when within 1 turn step of target. <= turnStep) { //Cancel when within 1 turn step of target.
isAuto = false; isAuto = false;
} }
} }
@@ -184,44 +191,52 @@ public class ServerYacht {
public void turnUpwind() { public void turnUpwind() {
disableAutoPilot(); disableAutoPilot();
Double normalizedHeading = normalizeHeading(); Double normalizedHeading = normalizeHeading();
if (normalizedHeading == 0) { if (continuouslyTurning) {
if (lastHeading < 180) { adjustHeading(turnStep);
adjustHeading(-TURN_STEP);
} else {
adjustHeading(TURN_STEP);
}
} else if (normalizedHeading == 180) {
if (lastHeading < 180) {
adjustHeading(TURN_STEP);
} else {
adjustHeading(-TURN_STEP);
}
} else if (normalizedHeading < 180) {
adjustHeading(-TURN_STEP);
} else { } else {
adjustHeading(TURN_STEP); if (normalizedHeading == 0) {
if (lastHeading < 180) {
adjustHeading(-turnStep);
} else {
adjustHeading(turnStep);
}
} else if (normalizedHeading == 180) {
if (lastHeading < 180) {
adjustHeading(turnStep);
} else {
adjustHeading(-turnStep);
}
} else if (normalizedHeading < 180) {
adjustHeading(-turnStep);
} else {
adjustHeading(turnStep);
}
} }
} }
public void turnDownwind() { public void turnDownwind() {
disableAutoPilot(); disableAutoPilot();
Double normalizedHeading = normalizeHeading(); Double normalizedHeading = normalizeHeading();
if (normalizedHeading == 0) { if (continuouslyTurning) {
if (lastHeading < 180) { adjustHeading(-turnStep);
adjustHeading(TURN_STEP);
} else {
adjustHeading(-TURN_STEP);
}
} else if (normalizedHeading == 180) {
if (lastHeading < 180) {
adjustHeading(-TURN_STEP);
} else {
adjustHeading(TURN_STEP);
}
} else if (normalizedHeading < 180) {
adjustHeading(TURN_STEP);
} else { } else {
adjustHeading(-TURN_STEP); if (normalizedHeading == 0) {
if (lastHeading < 180) {
adjustHeading(turnStep);
} else {
adjustHeading(-turnStep);
}
} else if (normalizedHeading == 180) {
if (lastHeading < 180) {
adjustHeading(-turnStep);
} else {
adjustHeading(turnStep);
}
} else if (normalizedHeading < 180) {
adjustHeading(turnStep);
} else {
adjustHeading(-turnStep);
}
} }
} }
@@ -265,9 +280,9 @@ public class ServerYacht {
private void turnTowardsHeading(Double newHeading) { private void turnTowardsHeading(Double newHeading) {
Double newVal = heading - newHeading; Double newVal = heading - newHeading;
if (Math.floorMod(newVal.longValue(), 360L) > 180) { if (Math.floorMod(newVal.longValue(), 360L) > 180) {
adjustHeading(TURN_STEP / 5); adjustHeading(turnStep / 5);
} else { } else {
adjustHeading(-TURN_STEP / 5); adjustHeading(-turnStep / 5);
} }
} }
@@ -418,4 +433,27 @@ public class ServerYacht {
return boatColor; return boatColor;
} }
public void setBoatType(BoatMeshType boatType) {
this.accelerationMultiplier = boatType.accelerationMultiplier;
this.maxSpeedMultiplier = boatType.maxSpeedMultiplier;
this.turnStepMultiplier = boatType.turnStep;
this.boatType = boatType;
}
public Double getMaxSpeedMultiplier() {
return maxSpeedMultiplier;
}
public Double getAccelerationMultiplier(){
return accelerationMultiplier;
}
public BoatMeshType getBoatType() {
return boatType;
}
public void setContinuouslyTurning(Boolean continuouslyTurning) {
this.continuouslyTurning = continuouslyTurning;
}
} }
+15 -7
View File
@@ -14,8 +14,10 @@ public class Sounds {
private static MediaPlayer soundEffect; private static MediaPlayer soundEffect;
private static MediaPlayer soundPlayer; private static MediaPlayer soundPlayer;
private static MediaPlayer hoverSoundPlayer; private static MediaPlayer hoverSoundPlayer;
private static MediaPlayer crashSoundPlayer;
private static boolean hoverInitialized = false; private static boolean hoverInitialized = false;
private static boolean crashInitialized = false;
private static boolean musicMuted = false; private static boolean musicMuted = false;
private static boolean soundEffectsMuted = false; private static boolean soundEffectsMuted = false;
@@ -155,11 +157,17 @@ public class Sounds {
public static void playCrashSound() { public static void playCrashSound() {
if (!soundEffectsMuted) { if (!soundEffectsMuted) {
Media crashSound = new Media( if (!crashInitialized) {
Sounds.class.getClassLoader().getResource("sounds/Large-metal-door-slam.mp3") Media pickupSound = new Media(
.toString()); Sounds.class.getClassLoader().getResource("sounds/Large-metal-door-slam.mp3")
soundPlayer = new MediaPlayer(crashSound); .toString());
soundPlayer.play(); crashSoundPlayer = new MediaPlayer(pickupSound);
crashInitialized = true;
}
if (crashSoundPlayer != null) {
crashSoundPlayer.stop();
}
crashSoundPlayer.play();
} }
} }
@@ -176,10 +184,10 @@ public class Sounds {
public static void playHoverSound() { public static void playHoverSound() {
if (!soundEffectsMuted) { if (!soundEffectsMuted) {
if (!hoverInitialized) { if (!hoverInitialized) {
Media crashSound = new Media( Media hoverSound = new Media(
Sounds.class.getClassLoader().getResource("sounds/Error-sound-effect.mp3") Sounds.class.getClassLoader().getResource("sounds/Error-sound-effect.mp3")
.toString()); .toString());
hoverSoundPlayer = new MediaPlayer(crashSound); hoverSoundPlayer = new MediaPlayer(hoverSound);
hoverInitialized = true; hoverInitialized = true;
} }
hoverSoundPlayer.setVolume(0.5); hoverSoundPlayer.setVolume(0.5);
+30 -14
View File
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.util.Pair; import javafx.util.Pair;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
@@ -16,6 +17,7 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.Colors;
import seng302.model.Limit; import seng302.model.Limit;
import seng302.model.mark.CompoundMark; import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner; import seng302.model.mark.Corner;
@@ -26,6 +28,7 @@ import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData; import seng302.model.stream.xml.parser.RegattaXMLData;
import seng302.model.token.Token; import seng302.model.token.Token;
import seng302.model.token.TokenType; import seng302.model.token.TokenType;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* Utilities for parsing XML documents * Utilities for parsing XML documents
@@ -146,17 +149,27 @@ public class XMLParser {
Node currentBoat = boatsList.item(i); Node currentBoat = boatsList.item(i);
if (currentBoat.getNodeName().equals("Boat")) { if (currentBoat.getNodeName().equals("Boat")) {
// Boat boat = new Boat(currentBoat); // Boat boat = new Boat(currentBoat);
BoatMeshType boatMeshType;
try {
boatMeshType = BoatMeshType.valueOf(XMLParser.getNodeAttributeString(currentBoat, "Type"));
} catch (IllegalArgumentException e){
boatMeshType = BoatMeshType.DINGHY;
}
Color color;
try {
color = Color.web(getNodeAttributeString(currentBoat, "Color"));
} catch (NullPointerException npe) {
color = Colors.getColor(new Random().nextInt(8));
}
ClientYacht yacht = new ClientYacht( ClientYacht yacht = new ClientYacht(
XMLParser.getNodeAttributeString(currentBoat, "Type"), boatMeshType,
XMLParser.getNodeAttributeInt(currentBoat, "SourceID"), XMLParser.getNodeAttributeInt(currentBoat, "SourceID"),
XMLParser.getNodeAttributeString(currentBoat, "HullNum"), XMLParser.getNodeAttributeString(currentBoat, "HullNum"),
XMLParser.getNodeAttributeString(currentBoat, "ShortName"), XMLParser.getNodeAttributeString(currentBoat, "ShortName"),
XMLParser.getNodeAttributeString(currentBoat, "BoatName"), XMLParser.getNodeAttributeString(currentBoat, "BoatName"),
XMLParser.getNodeAttributeString(currentBoat, "Country")); XMLParser.getNodeAttributeString(currentBoat, "Country"));
yacht.setColour(Color.web(getNodeAttributeString(currentBoat, "Color"))); yacht.setColour(color);
if (yacht.getBoatType().equals("Yacht")) { competingBoats.put(yacht.getSourceId(), yacht);
competingBoats.put(yacht.getSourceId(), yacht);
}
} }
} }
return competingBoats; return competingBoats;
@@ -204,17 +217,20 @@ public class XMLParser {
*/ */
private static List<Token> extractTokens(Element docEle) { private static List<Token> extractTokens(Element docEle) {
List<Token> tokens = new ArrayList<>(); List<Token> tokens = new ArrayList<>();
NodeList tokenList = docEle.getElementsByTagName("Tokens").item(0).getChildNodes(); try {
for (int i = 0; i < tokenList.getLength(); i++) { NodeList tokenList = docEle.getElementsByTagName("Tokens").item(0).getChildNodes();
Node tokenNode = tokenList.item(i); for (int i = 0; i < tokenList.getLength(); i++) {
if (tokenNode.getNodeName().equals("Token")) { Node tokenNode = tokenList.item(i);
String tokenType = getNodeAttributeString(tokenNode, "TokenType"); if (tokenNode.getNodeName().equals("Token")) {
Double lat = getNodeAttributeDouble(tokenNode, "TargetLat"); String tokenType = getNodeAttributeString(tokenNode, "TokenType");
Double lng = getNodeAttributeDouble(tokenNode, "TargetLng"); Double lat = getNodeAttributeDouble(tokenNode, "TargetLat");
tokens.add(new Token(TokenType.valueOf(tokenType), lat, lng)); Double lng = getNodeAttributeDouble(tokenNode, "TargetLng");
tokens.add(new Token(TokenType.valueOf(tokenType), lat, lng));
}
} }
} catch (NullPointerException npe) {
return new ArrayList<>();
} }
return tokens; return tokens;
} }
@@ -179,7 +179,7 @@ public class ClientToServerThread implements Runnable {
* Sends a request to the server asking for a source ID * Sends a request to the server asking for a source ID
*/ */
private void sendRegistrationRequest() { private void sendRegistrationRequest() {
RegistrationRequestMessage requestMessage = new RegistrationRequestMessage(ClientType.PLAYER); RegistrationRequestMessage requestMessage = new RegistrationRequestMessage(ClientType.PLAYER, clientId);
try { try {
os.write(requestMessage.getBuffer()); os.write(requestMessage.getBuffer());
@@ -197,9 +197,6 @@ public class ClientToServerThread implements Runnable {
private void processRegistrationResponse(StreamPacket packet){ private void processRegistrationResponse(StreamPacket packet){
int sourceId = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 0, 4)); int sourceId = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 0, 4));
int statusCode = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 4,5)); int statusCode = (int) Message.bytesToLong(Arrays.copyOfRange(packet.getPayload(), 4,5));
System.out.println("sourceId = " + sourceId);
System.out.println("statusCode = " + statusCode);
RegistrationResponseStatus status = RegistrationResponseStatus.getResponseStatus(statusCode); RegistrationResponseStatus status = RegistrationResponseStatus.getResponseStatus(statusCode);
if (status.equals(RegistrationResponseStatus.SUCCESS_PLAYING)){ if (status.equals(RegistrationResponseStatus.SUCCESS_PLAYING)){
@@ -249,7 +246,7 @@ public class ClientToServerThread implements Runnable {
new TimerTask() { new TimerTask() {
@Override @Override
public void run() { public void run() {
sendBoatActionMessage(new BoatActionMessage(BoatAction.DOWNWIND)); sendBoatActionMessage(new BoatActionMessage(BoatAction.DOWNWIND, clientId));
} }
}, 0, PACKET_SENDING_INTERVAL_MS }, 0, PACKET_SENDING_INTERVAL_MS
); );
@@ -262,14 +259,14 @@ public class ClientToServerThread implements Runnable {
new TimerTask() { new TimerTask() {
@Override @Override
public void run() { public void run() {
sendBoatActionMessage(new BoatActionMessage(BoatAction.UPWIND)); sendBoatActionMessage(new BoatActionMessage(BoatAction.UPWIND, clientId));
} }
}, 0, PACKET_SENDING_INTERVAL_MS }, 0, PACKET_SENDING_INTERVAL_MS
); );
} }
break; break;
default: default:
sendBoatActionMessage(new BoatActionMessage(actionType)); sendBoatActionMessage(new BoatActionMessage(actionType, clientId));
break; break;
} }
} }
@@ -28,6 +28,8 @@ import seng302.gameServer.messages.BoatAction;
import seng302.gameServer.messages.BoatStatus; import seng302.gameServer.messages.BoatStatus;
import seng302.gameServer.messages.YachtEventType; import seng302.gameServer.messages.YachtEventType;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.GameKeyBind;
import seng302.model.KeyAction;
import seng302.model.RaceState; import seng302.model.RaceState;
import seng302.model.stream.packets.StreamPacket; import seng302.model.stream.packets.StreamPacket;
import seng302.model.stream.parser.MarkRoundingData; import seng302.model.stream.parser.MarkRoundingData;
@@ -66,6 +68,8 @@ public class GameClient {
private ArrayList<ClientYacht> finishedBoats = new ArrayList<>(); private ArrayList<ClientYacht> finishedBoats = new ArrayList<>();
private GameKeyBind gameKeyBind; // all the key binding setting.
private ObservableList<String> clientLobbyList = FXCollections.observableArrayList(); private ObservableList<String> clientLobbyList = FXCollections.observableArrayList();
/** /**
@@ -75,6 +79,7 @@ public class GameClient {
*/ */
public GameClient(Pane holder) { public GameClient(Pane holder) {
this.holderPane = holder; this.holderPane = holder;
this.gameKeyBind = GameKeyBind.getInstance();
} }
/** /**
@@ -373,16 +378,16 @@ public class GameClient {
} }
return; return;
} }
switch (e.getCode()) {
case SPACE: // align with vmg if (gameKeyBind.getKeyCode(KeyAction.VMG) == e.getCode()) { // align with vmg
socketThread.sendBoatAction(BoatAction.VMG); break; socketThread.sendBoatAction(BoatAction.VMG);
case PAGE_UP: // upwind } else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()) { // upwind
socketThread.sendBoatAction(BoatAction.UPWIND); break; socketThread.sendBoatAction(BoatAction.UPWIND);
case PAGE_DOWN: // downwind } else if (gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) { // downwind
socketThread.sendBoatAction(BoatAction.DOWNWIND); break; socketThread.sendBoatAction(BoatAction.DOWNWIND);
case ENTER: // tack/gybe } else if (gameKeyBind.getKeyCode(KeyAction.TACK_GYBE) == e.getCode()) { // tack/gybe
// if chat box is active take whatever is in there and send it to server // if chat box is active take whatever is in there and send it to server
socketThread.sendBoatAction(BoatAction.TACK_GYBE); break; socketThread.sendBoatAction(BoatAction.TACK_GYBE);
} }
} }
@@ -391,15 +396,17 @@ public class GameClient {
if (raceView.isChatInputFocused()) { if (raceView.isChatInputFocused()) {
return; 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) if (gameKeyBind.getKeyCode(KeyAction.SAILS_STATE) == e.getCode()) { // sails in/sails out
case SHIFT: // sails in/sails out if (allBoatsMap.get(socketThread.getClientId()).getSailIn()) {
socketThread.sendBoatAction(BoatAction.SAILS_OUT);
} else {
socketThread.sendBoatAction(BoatAction.SAILS_IN); socketThread.sendBoatAction(BoatAction.SAILS_IN);
allBoatsMap.get(socketThread.getClientId()).toggleSail(); }
break; allBoatsMap.get(socketThread.getClientId()).toggleSail();
case PAGE_UP: } else if (gameKeyBind.getKeyCode(KeyAction.UPWIND) == e.getCode()
case PAGE_DOWN: || gameKeyBind.getKeyCode(KeyAction.DOWNWIND) == e.getCode()) {
socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING); break; socketThread.sendBoatAction(BoatAction.MAINTAIN_HEADING);
} }
} }
@@ -456,4 +463,14 @@ public class GameClient {
public Map<Integer, ClientYacht> getAllBoatsMap() { public Map<Integer, ClientYacht> getAllBoatsMap() {
return allBoatsMap; return allBoatsMap;
} }
public void sendToggleTurningModePacket() {
if (socketThread != null) {
if (gameKeyBind.isContinuouslyTurning()) {
socketThread.sendBoatAction(BoatAction.CONTINUOUSLY_TURNING);
} else {
socketThread.sendBoatAction(BoatAction.DEFAULT_TURNING);
}
}
}
} }
@@ -30,6 +30,7 @@ import seng302.model.token.Token;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.utilities.Sounds; import seng302.utilities.Sounds;
import seng302.visualiser.fxObjects.MarkArrowFactory; import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatObject; import seng302.visualiser.fxObjects.assets_3D.BoatObject;
import seng302.visualiser.fxObjects.assets_3D.Marker3D; import seng302.visualiser.fxObjects.assets_3D.Marker3D;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory; import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
@@ -459,7 +460,7 @@ public class GameView3D {
final List<Group> wakes = new ArrayList<>(); final List<Group> wakes = new ArrayList<>();
for (ClientYacht clientYacht : yachts) { for (ClientYacht clientYacht : yachts) {
Color colour = clientYacht.getColour(); Color colour = clientYacht.getColour();
newBoat = new BoatObject(); newBoat = new BoatObject(clientYacht.getBoatType());
newBoat.setFill(colour); newBoat.setFill(colour);
boatObjects.put(clientYacht, newBoat); boatObjects.put(clientYacht, newBoat);
wakesGroup.getChildren().add(newBoat.getWake()); wakesGroup.getChildren().add(newBoat.getWake());
@@ -568,6 +569,7 @@ public class GameView3D {
} }
public void setBoatAsPlayer (ClientYacht playerYacht) { public void setBoatAsPlayer (ClientYacht playerYacht) {
playerYacht.toggleSail();
playerBoatAnimationTimer = new AnimationTimer() { playerBoatAnimationTimer = new AnimationTimer() {
double count = 60; double count = 60;
@@ -88,7 +88,6 @@ public class FinishScreenViewController implements Initializable {
public void switchToStartScreenView() { public void switchToStartScreenView() {
Sounds.playButtonClick(); Sounds.playButtonClick();
//TODO merge fix
setContentPane("/views/StartScreenView.fxml"); setContentPane("/views/StartScreenView.fxml");
} }
@@ -59,7 +59,6 @@ public class LobbyController implements Initializable {
private JFXDialog customizationDialog; private JFXDialog customizationDialog;
public Color playersColor; public Color playersColor;
private Map<Integer, ClientYacht> playerBoats; private Map<Integer, ClientYacht> playerBoats;
private Double mapWidth = INITIAL_MAP_WIDTH, mapHeight = INITIAL_MAP_HEIGHT; private Double mapWidth = INITIAL_MAP_WIDTH, mapHeight = INITIAL_MAP_HEIGHT;
private GameView gameView; private GameView gameView;
@@ -93,16 +92,16 @@ public class LobbyController implements Initializable {
ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted()); ViewManager.getInstance().getPlayerList().setAll(ViewManager.getInstance().getPlayerList().sorted());
}); });
customizeButton.setOnMouseReleased(event -> {
customizationDialog = createCustomizeDialog();
Sounds.playButtonClick();
customizationDialog.show();
});
Platform.runLater(() -> { Platform.runLater(() -> {
Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId(); Integer playerId = ViewManager.getInstance().getGameClient().getServerThread().getClientId();
playersColor = Colors.getColor(playerId - 1); playersColor = Colors.getColor(playerId - 1);
customizationDialog = createCustomizeDialog();
customizeButton.setOnMouseReleased(event -> {
Sounds.playButtonClick();
customizationDialog.show();
});
}); });
leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound()); leaveLobbyButton.setOnMouseEntered(e -> Sounds.playHoverSound());
@@ -132,6 +131,8 @@ public class LobbyController implements Initializable {
controller.setPlayerName(this.playerBoats controller.setPlayerName(this.playerBoats
.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId()) .get(ViewManager.getInstance().getGameClient().getServerThread().getClientId())
.getBoatName()); .getBoatName());
controller.setCurrentBoat(this.playerBoats.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId())
.getBoatType().toString());
return customizationDialog; return customizationDialog;
} }
@@ -190,7 +191,7 @@ public class LobbyController implements Initializable {
FXMLLoader loader = new FXMLLoader( FXMLLoader loader = new FXMLLoader(
getClass().getResource("/views/cells/PlayerCell.fxml")); getClass().getResource("/views/cells/PlayerCell.fxml"));
loader.setController(new PlayerCell(playerId, yacht.getBoatName(), yacht.getColour())); loader.setController(new PlayerCell(playerId, yacht));
try { try {
pane = loader.load(); pane = loader.load();
@@ -87,7 +87,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
@FXML @FXML
private Label timerLabel; private Label timerLabel;
@FXML @FXML
private StackPane contentAnchorPane; private StackPane contentStackPane;
private GridPane contentGridPane; private GridPane contentGridPane;
@FXML @FXML
@@ -134,8 +134,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
Sounds.stopMusic(); Sounds.stopMusic();
Sounds.playRaceMusic(); Sounds.playRaceMusic();
finishScreenDialog = createFinishDialog();
// Load a default important annotation state // Load a default important annotation state
//importantAnnotations = new ImportantAnnotationsState(); //importantAnnotations = new ImportantAnnotationsState();
@@ -180,9 +178,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
// chatHistory.textProperty().addListener((obs, oldValue, newValue) -> { // chatHistory.textProperty().addListener((obs, oldValue, newValue) -> {
// chatHistory.setScrollTop(Double.MAX_VALUE); // chatHistory.setScrollTop(Double.MAX_VALUE);
// }); // });
rvAnchorPane.setOnMouseClicked((event) ->
rvAnchorPane.requestFocus() contentStackPane.setOnMouseClicked(event -> {
); contentStackPane.requestFocus();
});
//Makes the chat history non transparent when clicked on //Makes the chat history non transparent when clicked on
chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() { chatInput.focusedProperty().addListener(new ChangeListener<Boolean>() {
@@ -200,26 +199,27 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) { public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
raceState.setRaceStarted(false); raceState.setRaceStarted(false);
finishDialogController.setFinishedBoats(finishedBoats); createFinishDialog(finishedBoats);
finishScreenDialog.show();
} }
private JFXDialog createFinishDialog() { /**
* Create finishScreenDialog and set up finishDialogController.
*/
private void createFinishDialog(ArrayList<ClientYacht> finishedBoats) {
FXMLLoader dialog = new FXMLLoader( FXMLLoader dialog = new FXMLLoader(
getClass().getResource("/views/dialogs/RaceFinishDialog.fxml")); getClass().getResource("/views/dialogs/RaceFinishDialog.fxml"));
JFXDialog finishScreenDialog = null; Platform.runLater(() -> {
try {
try { finishScreenDialog = new JFXDialog(contentStackPane, dialog.load(),
finishScreenDialog = new JFXDialog(contentAnchorPane, dialog.load(), JFXDialog.DialogTransition.CENTER);
JFXDialog.DialogTransition.CENTER); finishDialogController = dialog.getController();
} catch (IOException e) { finishDialogController.setFinishedBoats(finishedBoats);
e.printStackTrace(); finishScreenDialog.show();
} } catch (IOException e) {
e.printStackTrace();
finishDialogController = dialog.getController(); }
});
return finishScreenDialog;
} }
public void loadRace ( public void loadRace (
@@ -245,7 +245,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
gameView = new GameView3D(); gameView = new GameView3D();
// gameView.setFrameRateFXText(fpsDisplay); // gameView.setFrameRateFXText(fpsDisplay);
Platform.runLater(() -> { Platform.runLater(() -> {
contentAnchorPane.getChildren().add(0, gameView.getAssets()); contentStackPane.getChildren().add(0, gameView.getAssets());
((SubScene) gameView.getAssets()).widthProperty() ((SubScene) gameView.getAssets()).widthProperty()
.bind(ViewManager.getInstance().getStage().widthProperty()); .bind(ViewManager.getInstance().getStage().widthProperty());
((SubScene) gameView.getAssets()).heightProperty() ((SubScene) gameView.getAssets()).heightProperty()
@@ -805,7 +805,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
public String readChatInput() { public String readChatInput() {
String chat = chatInput.getText(); String chat = chatInput.getText();
chatInput.clear(); chatInput.clear();
rvAnchorPane.requestFocus(); contentStackPane.requestFocus();
return chat; return chat;
} }
@@ -112,16 +112,23 @@ public class ServerListController implements Initializable, ServerListenerDelega
serverListVBox.getChildren().add(noServersFound); serverListVBox.getChildren().add(noServersFound);
// Set up dialog for server creation // Set up dialog for server creation
serverListHostButton.setOnAction(action -> {
showServerCreationDialog();
});
}
/**
* Shows Server Creation Dialog when "Host" button is clicked.
*/
private void showServerCreationDialog() {
Platform.runLater(() -> { Platform.runLater(() -> {
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource( FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
"/views/dialogs/ServerCreationDialog.fxml")); "/views/dialogs/ServerCreationDialog.fxml"));
try { try {
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(), JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
DialogTransition.CENTER); DialogTransition.CENTER);
serverListHostButton.setOnAction(action -> { dialog.show();
dialog.show(); Sounds.playButtonClick();
Sounds.playButtonClick();
});
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
logger.warn("Could not create Server Creation Dialog."); logger.warn("Could not create Server Creation Dialog.");
@@ -2,6 +2,9 @@ package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDecorator; import com.jfoenix.controls.JFXDecorator;
import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialog.DialogTransition;
import com.jfoenix.controls.JFXSnackbar;
import com.jfoenix.svg.SVGGlyph; import com.jfoenix.svg.SVGGlyph;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@@ -15,6 +18,7 @@ import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing; import javafx.scene.SceneAntialiasing;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -23,6 +27,7 @@ import seng302.gameServer.ServerAdvertiser;
import seng302.utilities.BonjourInstallChecker; import seng302.utilities.BonjourInstallChecker;
import seng302.utilities.Sounds; import seng302.utilities.Sounds;
import seng302.visualiser.GameClient; import seng302.visualiser.GameClient;
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
public class ViewManager { public class ViewManager {
@@ -32,12 +37,9 @@ public class ViewManager {
private HashMap<String, String> properties; //TODO is this the best way to do this?? private HashMap<String, String> properties; //TODO is this the best way to do this??
private ObservableList<String> playerList; private ObservableList<String> playerList;
private Logger logger = LoggerFactory.getLogger(ViewManager.class); private Logger logger = LoggerFactory.getLogger(ViewManager.class);
public Stage getStage() {
return stage;
}
private Stage stage; private Stage stage;
private JFXSnackbar jfxSnackbar;
private JFXDialog keyBindingDialog;
private ViewManager() { private ViewManager() {
properties = new HashMap<>(); properties = new HashMap<>();
@@ -99,6 +101,8 @@ public class ViewManager {
gameClient.stopGame(); gameClient.stopGame();
System.exit(0); System.exit(0);
}); });
jfxSnackbar = new JFXSnackbar(decorator);
} }
/** /**
@@ -119,12 +123,31 @@ public class ViewManager {
//Get the button box //Get the button box
HBox btns = (HBox) decorator.getChildren().get(0); HBox btns = (HBox) decorator.getChildren().get(0);
//Create settings button -- [WIP]
JFXButton btnKeyBinding = new JFXButton();
btnKeyBinding.setText(" Key Bindings");
btnKeyBinding.setStyle("-fx-text-fill:#fff");
btnKeyBinding.getStyleClass().add("jfx-decorator-button");
btnKeyBinding.setCursor(Cursor.HAND);
btnKeyBinding.setFocusTraversable(false);
btnKeyBinding.setOnMouseClicked(event -> Platform.runLater(() -> {
try {
if (!checkDialogOpened(decorator.getChildren())) {
showKeyBindingDialog();
}
} catch (IOException e) {
logger.warn("Something went wrong when opening key bind dialog");
}
}));
//Create new button //Create new button
JFXButton btnMute = new JFXButton(); JFXButton btnMute = new JFXButton();
btnMute.setText(" Toggle Sound"); btnMute.setText(" Toggle Sound");
btnMute.setStyle("-fx-text-fill:#fff"); btnMute.setStyle("-fx-text-fill:#fff");
btnMute.getStyleClass().add("jfx-decorator-button"); btnMute.getStyleClass().add("jfx-decorator-button");
btnMute.setCursor(Cursor.HAND); btnMute.setCursor(Cursor.HAND);
btnMute.setFocusTraversable(false);
//Create Graphics //Create Graphics
SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE); SVGGlyph spacer = new SVGGlyph(0, "SPACER", "", Color.WHITE);
@@ -134,9 +157,13 @@ public class ViewManager {
SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON", SVGGlyph volumeOff = new SVGGlyph(0, "VOLUME_ON",
"M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z", "M13.5,9 C13.5,7.2 12.5,5.7 11,5 L11,7.2 L13.5,9.7 L13.5,9 L13.5,9 Z M16,9 C16,9.9 15.8,10.8 15.5,11.6 L17,13.1 C17.7,11.9 18,10.4 18,8.9 C18,4.6 15,1 11,0.1 L11,2.2 C13.9,3.2 16,5.8 16,9 L16,9 Z M1.3,0 L0,1.3 L4.7,6 L0,6 L0,12 L4,12 L9,17 L9,10.3 L13.3,14.6 C12.6,15.1 11.9,15.5 11,15.8 L11,17.9 C12.4,17.6 13.6,17 14.7,16.1 L16.7,18.1 L18,16.8 L9,7.8 L1.3,0 L1.3,0 Z M9,1 L6.9,3.1 L9,5.2 L9,1 L9,1 Z",
Color.WHITE); Color.WHITE);
SVGGlyph keyBindingGlyph = new SVGGlyph(0, "KEY_BINDING",
"M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z",
Color.WHITE);
volumeOn.setSize(16, 16); volumeOn.setSize(16, 16);
volumeOff.setSize(16, 16); volumeOff.setSize(16, 16);
spacer.setSize(40, 16); spacer.setSize(40, 16);
keyBindingGlyph.setSize(24, 16);
// Determine which graphic should go on the button // Determine which graphic should go on the button
if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) { if (Sounds.isMusicMuted() && Sounds.isSoundEffectsMuted()) {
@@ -145,9 +172,12 @@ public class ViewManager {
btnMute.setGraphic(volumeOn); btnMute.setGraphic(volumeOn);
} }
btnKeyBinding.setGraphic(keyBindingGlyph);
// Add Buttons // Add Buttons
btns.getChildren().add(0, spacer); btns.getChildren().add(0, spacer);
btns.getChildren().add(0, btnMute); btns.getChildren().add(0, btnMute);
btns.getChildren().add(0, btnKeyBinding);
btnMute.setOnAction((action) -> { btnMute.setOnAction((action) -> {
Sounds.toggleAllSounds(); Sounds.toggleAllSounds();
if (btnMute.getGraphic().equals(volumeOff)) { if (btnMute.getGraphic().equals(volumeOff)) {
@@ -159,6 +189,63 @@ public class ViewManager {
} }
/**
* Recursively find JFXDialog given a starting node. Will traverse children of StackPane.
*
* @param nodes children nodes to be check.
* @return true if node contains JFXDialog.
*/
private Boolean checkDialogOpened(ObservableList<Node> nodes) {
boolean foundJFXDialog = false;
for (Node node : nodes) {
if (node instanceof JFXDialog) {
return true;
} else if (node instanceof StackPane) {
foundJFXDialog = checkDialogOpened(((StackPane) node).getChildren());
}
}
return foundJFXDialog;
}
private void showKeyBindingDialog() throws IOException {
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
"/views/dialogs/KeyBindingDialog.fxml"));
for (Node node : decorator.getChildren()) {
if (node instanceof StackPane) {
keyBindingDialog = new JFXDialog((StackPane) node,
dialogContent.load(),
DialogTransition.CENTER);
KeyBindingDialogController keyBindingDialogController = dialogContent
.getController();
keyBindingDialogController.setGameClient(this.gameClient);
keyBindingDialog.show();
Sounds.playButtonClick();
}
}
}
public void closeKeyBindingDialog() {
keyBindingDialog.close();
}
/**
* Show a snackbar at the bottom of the app for 1 second.
*
* @param snackbarText text to be displayed.
*/
public void showSnackbar(String snackbarText, boolean isWarning) {
if (isWarning) {
decorator.getStylesheets()
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
} else {
if (decorator.getStylesheets().size() > 1) {
decorator.getStylesheets().remove(1);
}
}
jfxSnackbar.show(snackbarText, 1500);
}
/** /**
* Determines if a PC has compatibility with the bonjour protocol for server detection. * Determines if a PC has compatibility with the bonjour protocol for server detection.
*/ */
@@ -221,6 +308,7 @@ public class ViewManager {
/** /**
* Change the view to the Lobby Screen * Change the view to the Lobby Screen
*
* @param disableReadyButton Boolean value so that clients can't try start a game. * @param disableReadyButton Boolean value so that clients can't try start a game.
* @return A LobbyController object for the Lobby Screen. * @return A LobbyController object for the Lobby Screen.
*/ */
@@ -243,6 +331,7 @@ public class ViewManager {
/** /**
* Sets up the view for the race. Creating a new decorator and destroying the old one. * Sets up the view for the race. Creating a new decorator and destroying the old one.
*
* @return A RaceViewController for the race view screen. * @return A RaceViewController for the race view screen.
*/ */
@@ -267,17 +356,10 @@ public class ViewManager {
scene.setOnKeyPressed(gameClient::keyPressed); scene.setOnKeyPressed(gameClient::keyPressed);
scene.setOnKeyReleased(gameClient::keyReleased); scene.setOnKeyReleased(gameClient::keyReleased);
// uncomment to make it full screen
// Rectangle2D visualBounds = Screen.getPrimary().getVisualBounds();
// stage.setX(visualBounds.getMinX());
// stage.setY(visualBounds.getMinY());
// stage.setWidth(visualBounds.getWidth());
// stage.setHeight(visualBounds.getHeight());
// stage.setMaximized(true);
// stage.setFullScreen(true);
stage.setMinHeight(500); stage.setMinHeight(500);
stage.setMinWidth(800); stage.setMinWidth(800);
stage.setTitle("Party Parrots At Sea");
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
stage.setOnCloseRequest(e -> closeAll()); stage.setOnCloseRequest(e -> closeAll());
stage.setScene(scene); stage.setScene(scene);
stage.show(); stage.show();
@@ -286,7 +368,7 @@ public class ViewManager {
} }
}); });
while (loader.getController() == null){ while (loader.getController() == null) {
try { try {
Thread.sleep(50); Thread.sleep(50);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -296,4 +378,9 @@ public class ViewManager {
return loader.getController(); return loader.getController();
} }
public Stage getStage() {
return stage;
}
} }
@@ -6,6 +6,7 @@ import javafx.scene.control.Label;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import seng302.model.ClientYacht;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType; import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatModel; import seng302.visualiser.fxObjects.assets_3D.BoatModel;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory; import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
@@ -24,11 +25,13 @@ public class PlayerCell {
private String name; private String name;
private Color boatColor; private Color boatColor;
private Integer playerId; private Integer playerId;
private BoatMeshType boatType;
public PlayerCell(Integer playerId, String playerName, Color color) { public PlayerCell(Integer playerId, ClientYacht yacht) {
this.playerId = playerId; this.playerId = playerId;
this.name = playerName; this.name = yacht.getBoatName();
this.boatColor = color; this.boatColor = yacht.getColour();
this.boatType = yacht.getBoatType();
} }
public void initialize() { public void initialize() {
@@ -37,7 +40,7 @@ public class PlayerCell {
// Add Rotating Boat to Player Cell with players color on it. // Add Rotating Boat to Player Cell with players color on it.
Group group = new Group(); Group group = new Group();
boatPane.getChildren().add(group); boatPane.getChildren().add(group);
BoatModel bo = ModelFactory.boatIconView(BoatMeshType.DINGHY, this.boatColor); BoatModel bo = ModelFactory.boatIconView(boatType, boatColor);
group.getChildren().add(bo.getAssets()); group.getChildren().add(bo.getAssets());
} }
@@ -6,15 +6,25 @@ import com.jfoenix.controls.JFXTextField;
import com.jfoenix.validation.RequiredFieldValidator; import com.jfoenix.validation.RequiredFieldValidator;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.PointLight;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import seng302.gameServer.messages.CustomizeRequestType; import seng302.gameServer.messages.CustomizeRequestType;
import seng302.utilities.Sounds; import seng302.utilities.Sounds;
import seng302.visualiser.ClientToServerThread; import seng302.visualiser.ClientToServerThread;
import seng302.visualiser.controllers.LobbyController; import seng302.visualiser.controllers.LobbyController;
import seng302.visualiser.controllers.ViewManager; import seng302.visualiser.controllers.ViewManager;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatModel;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.validators.FieldLengthValidator; import seng302.visualiser.validators.FieldLengthValidator;
import seng302.visualiser.validators.ValidationTools; import seng302.visualiser.validators.ValidationTools;
@@ -24,23 +34,35 @@ public class BoatCustomizeController implements Initializable{
@FXML @FXML
private JFXColorPicker colorPicker; private JFXColorPicker colorPicker;
@FXML @FXML
private ProgressBar speedBar;
@FXML
private ProgressBar accelBar;
@FXML
private ProgressBar handleBar;
@FXML
private JFXButton submitBtn; private JFXButton submitBtn;
@FXML @FXML
private JFXTextField boatName; private JFXTextField boatName;
@FXML @FXML
void colorChanged(ActionEvent event) { private Pane boatPane;
Color color = colorPicker.getValue(); @FXML
void colorChanged() {
refreshBoat();
} }
//---------FXML END---------// //---------FXML END---------//
private ClientToServerThread socketThread; private ClientToServerThread socketThread;
private LobbyController lobbyController; private LobbyController lobbyController;
private BoatMeshType currentBoat;
private Double maxSpeedMultiplier = 1.0;
private Double maxTurnRateMultiplier = 1.0;
private Double maxAccelerationMultiplier = 1.0;
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
socketThread = ViewManager.getInstance().getGameClient().getServerThread(); socketThread = ViewManager.getInstance().getGameClient().getServerThread();
findMaxStats();
RequiredFieldValidator playerNameReqValidator = new RequiredFieldValidator(); RequiredFieldValidator playerNameReqValidator = new RequiredFieldValidator();
playerNameReqValidator.setMessage("Player name required."); playerNameReqValidator.setMessage("Player name required.");
@@ -48,6 +70,8 @@ public class BoatCustomizeController implements Initializable{
playerNameLengthValidator.setMessage("Player name too long."); playerNameLengthValidator.setMessage("Player name too long.");
boatName.setValidators(playerNameLengthValidator, playerNameReqValidator); boatName.setValidators(playerNameLengthValidator, playerNameReqValidator);
boatPane.setBackground(
new Background(new BackgroundFill(Color.SKYBLUE, CornerRadii.EMPTY, Insets.EMPTY)));
submitBtn.setOnMouseReleased(event -> { submitBtn.setOnMouseReleased(event -> {
Sounds.playButtonClick(); Sounds.playButtonClick();
@@ -78,7 +102,10 @@ public class BoatCustomizeController implements Initializable{
colorArray[2] = (byte) blue; colorArray[2] = (byte) blue;
socketThread.sendCustomizationRequest(CustomizeRequestType.COLOR, colorArray); socketThread.sendCustomizationRequest(CustomizeRequestType.COLOR, colorArray);
socketThread.sendCustomizationRequest(CustomizeRequestType.SHAPE, currentBoat.toString().getBytes());
lobbyController.closeCustomizationDialog(); lobbyController.closeCustomizationDialog();
} }
} }
@@ -93,4 +120,61 @@ public class BoatCustomizeController implements Initializable{
public void setParentController(LobbyController lobbyController){ public void setParentController(LobbyController lobbyController){
this.lobbyController = lobbyController; this.lobbyController = lobbyController;
} }
public void setCurrentBoat(String boatType) {
currentBoat = BoatMeshType.valueOf(boatType);
displayCurrentBoat();
refreshStatBars(currentBoat);
}
public void nextBoat() {
currentBoat = BoatMeshType.getNextBoatType(currentBoat);
displayCurrentBoat();
refreshStatBars(currentBoat);
}
public void prevBoat() {
currentBoat = BoatMeshType.getPrevBoatType(currentBoat);
displayCurrentBoat();
refreshStatBars(currentBoat);
}
private void displayCurrentBoat() {
boatPane.getChildren().clear();
Group group = new Group();
boatPane.getChildren().add(group);
BoatModel bo = ModelFactory.boatCustomiseView(currentBoat, colorPicker.getValue());
group.getChildren().add(bo.getAssets());
group.getChildren().add(new PointLight());
}
private void refreshBoat() {
boatPane.getChildren().clear();
Group group = new Group();
boatPane.getChildren().add(group);
BoatModel bo = ModelFactory.boatCustomiseView(currentBoat, colorPicker.getValue());
group.getChildren().add(bo.getAssets());
refreshStatBars(currentBoat);
}
private void findMaxStats() {
for (BoatMeshType bmt: BoatMeshType.values()) {
if (bmt.turnStep > maxTurnRateMultiplier) {
maxTurnRateMultiplier = bmt.turnStep;
}
if (bmt.maxSpeedMultiplier > maxSpeedMultiplier) {
maxSpeedMultiplier = bmt.maxSpeedMultiplier;
}
if (bmt.accelerationMultiplier > maxAccelerationMultiplier) {
maxAccelerationMultiplier = bmt.accelerationMultiplier;
}
}
}
private void refreshStatBars(BoatMeshType bo) {
speedBar.setProgress((bo.maxSpeedMultiplier) / maxSpeedMultiplier);
accelBar.setProgress(bo.accelerationMultiplier / maxAccelerationMultiplier);
handleBar.setProgress(bo.turnStep / maxTurnRateMultiplier);
}
} }
@@ -0,0 +1,185 @@
package seng302.visualiser.controllers.dialogs;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXToggleButton;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.KeyEvent;
import seng302.model.GameKeyBind;
import seng302.model.KeyAction;
import seng302.visualiser.GameClient;
import seng302.visualiser.controllers.ViewManager;
public class KeyBindingDialogController implements Initializable {
//--------FXML BEGIN--------//
@FXML
private Label keyBindingDialogHeader;
@FXML
private Label closeLabel;
@FXML
private JFXButton zoomInbtn;
@FXML
private JFXButton zoomOutBtn;
@FXML
private JFXButton vmgBtn;
@FXML
private JFXButton sailInOutBtn;
@FXML
private JFXButton tackGybeBtn;
@FXML
private JFXButton upwindBtn;
@FXML
private JFXButton downwindBtn;
@FXML
private JFXButton resetBtn;
@FXML
private Label upwindLabel;
@FXML
private Label downwindLabel;
@FXML
private JFXToggleButton turningToggle;
//---------FXML END---------//
private GameKeyBind gameKeyBind;
private List<JFXButton> buttons = new ArrayList<>();
private Map<Button, KeyAction> buttonActionMap;
private GameClient gameClient; // to send turning mode packet
@Override
public void initialize(URL location, ResourceBundle resources) {
gameKeyBind = GameKeyBind.getInstance();
buttons = new ArrayList<>();
Collections.addAll(buttons,
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn);
bindButtonWithAction();
loadKeyBind();
buttons.forEach(button -> {
button.setOnMouseEntered(event -> mouseEnter(button));
button.setOnMousePressed(event -> buttonPressed(button));
button.setOnMouseExited(event -> mouseExit(button));
button.setOnKeyPressed(event -> keyPressed(event, button));
});
turningToggle.setOnMouseClicked(event -> toggleTurningMode());
resetBtn.setOnMouseClicked(event -> {
gameKeyBind.setToDefault();
loadKeyBind();
});
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
keyBindingDialogHeader.setFocusTraversable(true);
keyBindingDialogHeader.requestFocus();
}
/**
* Set buttons' label according to GameKeyBind settings
*/
private void loadKeyBind() {
buttons.forEach(
button -> button
.setText(gameKeyBind.getKeyCode(buttonActionMap.get(button)).getName()));
turningToggle.setSelected(gameKeyBind.isContinuouslyTurning());
if (gameKeyBind.isContinuouslyTurning()) {
upwindLabel.setText("ClOCKWISE TURNING");
downwindLabel.setText("ANTICLOCKWISE TURNING");
} else {
upwindLabel.setText("UPWIND");
downwindLabel.setText("DOWNWIND");
}
}
/**
* Bind buttons with specific action in a map.
*/
private void bindButtonWithAction() {
buttonActionMap = new HashMap<>();
for (int i = 0; i < 7; i++) {
buttonActionMap.put(buttons.get(i), KeyAction.getType(i + 1));
}
}
/**
* Prompt success / failure message for reassigning key action
*/
private void showSnackBar(String message, Boolean isWarning) {
ViewManager.getInstance().showSnackbar(message, isWarning);
}
/**
* When a mouse enters the button, the color and font size should change to highlight
* @param button
*/
private void mouseEnter(Button button) {
button.setStyle(""
+ "-fx-background-color: -fx-pp-theme-color;"
+ "-fx-text-fill: -fx-pp-front-color;"
+ "-fx-font-size: 15;");
}
/**
* Prompt "press key..." to inform users assign a new key bind by pressing a key
* @param button
*/
private void buttonPressed(Button button) {
button.setText("PRESS KEY...");
}
/**
* When mouse leaves the button, return the button to the normal state in terms of text,
* color and font size
* @param button
*/
private void mouseExit(Button button) {
button.setText(GameKeyBind.getInstance().getKeyCode(buttonActionMap.get(button)).getName());
button.setStyle(""
+ "-fx-background-color: -fx-pp-front-color; "
+ "-fx-text-fill: -fx-pp-theme-color; "
+ "-fx-font-size: 13;");
}
/**
* When a key is pressed, check if the new binding conflicts to any existed settings, if not
* assign the selected action with the new key binding to GameKeyBind.
* @param event
* @param button
*/
private void keyPressed(KeyEvent event, Button button) {
event.consume();
KeyAction buttonAction = buttonActionMap.get(button);
if (gameKeyBind.bindKeyToAction(event.getCode(), buttonAction)) {
showSnackBar(button.getId() + " is set to " + event.getCode().getName(), false);
button.setText(gameKeyBind.getKeyCode(buttonAction).getName());
} else {
loadKeyBind();
showSnackBar(event.getCode().getName() + " is already in use", true);
}
}
/**
* When the turning mode is toggled, update gameKeyBind and send out packet to notify the server
*/
private void toggleTurningMode() {
gameKeyBind.toggleTurningMode();
gameClient.sendToggleTurningModePacket();
loadKeyBind();
}
public void setGameClient(GameClient gameClient) {
this.gameClient = gameClient;
}
}
@@ -2,21 +2,59 @@ package seng302.visualiser.fxObjects.assets_3D;
/** /**
* Enum for boat meshes. Enum values should be of the form : * Enum for boat meshes. Enum values should be of the form :
* ENUM_VALUE (hull file, mast file, Y offset of mast CoR from origin, sail file, Y offset of sail CoR from origin) * ENUM_VALUE (hull file, mast file, Y offset of mast CoR from origin, sail file, Y offset of sail CoR from origin, jib file, fixed sail)
* Files must be valid .stl files. * Files must be valid .stl files.
*/ */
public enum BoatMeshType { public enum BoatMeshType {
DINGHY ("dinghy_hull.stl", "dinghy_mast.stl", -1.36653, "dinghy_sail.stl", -1.36653); DINGHY("dinghy_hull.stl", "dinghy_mast.stl", 1.36653, "dinghy_sail.stl", 1.36653, null, false, 1.8, 1.0, 1.0),
CATAMARAN("catamaran_hull.stl", "catamaran_mast.stl", 0.997, "catamaran_sail.stl",
0.997, null, false, 1.0, 1.4, 2.0),
PIRATE_SHIP("pirateship_hull.stl", "pirateship_mast.stl", -0.5415, "pirateship_mainsail.stl",
-0.5415, "pirateship_frontsail.stl", true, 1.2, 1.6, 1.2);
final String hullFile, mastFile, sailFile; final String hullFile, mastFile, sailFile, jibFile;
final double mastOffset, sailOffset; final double mastOffset, sailOffset;
public final double maxSpeedMultiplier;
public final double accelerationMultiplier;
public final double turnStep;
final boolean fixedSail;
final static BoatMeshType[] boatTypes = new BoatMeshType[]{DINGHY, CATAMARAN, PIRATE_SHIP};
BoatMeshType(String hullFile, String mastFile, double mastOffset, String sailFile, double sailOffset) { BoatMeshType(String hullFile, String mastFile, double mastOffset, String sailFile,
double sailOffset, String jibFile, boolean fixedSail, double maxSpeedMultiplier, double accelerationMultiplier, double turnStep) {
this.hullFile = hullFile; this.hullFile = hullFile;
this.mastFile = mastFile; this.mastFile = mastFile;
this.mastOffset = mastOffset; this.mastOffset = mastOffset;
this.sailFile = sailFile; this.sailFile = sailFile;
this.sailOffset = sailOffset; this.sailOffset = sailOffset;
this.jibFile = jibFile;
this.fixedSail = fixedSail;
this.maxSpeedMultiplier = maxSpeedMultiplier;
this.accelerationMultiplier = accelerationMultiplier;
this.turnStep = turnStep;
}
public static BoatMeshType getNextBoatType(BoatMeshType boatType) {
for (int i = 0; i < boatTypes.length; i++) {
if (i == boatTypes.length -1) {
return boatTypes[0];
} else if (boatType == boatTypes[i]) {
return boatTypes[i+1];
}
}
return boatType;
}
public static BoatMeshType getPrevBoatType(BoatMeshType boatType) {
for (int i = 0; i < boatTypes.length; i++) {
if (i == 0 && boatType == boatTypes[i]) {
return boatTypes[boatTypes.length -1];
} else if (boatType == boatTypes[i]) {
return boatTypes[i-1];
}
}
return boatType;
} }
} }
@@ -34,14 +34,16 @@ public class BoatModel extends Model {
* @param degrees The rotation of the sail in degrees * @param degrees The rotation of the sail in degrees
*/ */
public void rotateSail(double degrees) { public void rotateSail(double degrees) {
MeshView mast = getMeshViewChild(MAST_INDEX); if (!meshType.fixedSail) {
MeshView sail = getMeshViewChild(SAIL_INDEX); MeshView mast = getMeshViewChild(MAST_INDEX);
mast.getTransforms().setAll( MeshView sail = getMeshViewChild(SAIL_INDEX);
new Rotate(degrees, -meshType.mastOffset, 0,0, new Point3D(0, 0, 1)) mast.getTransforms().setAll(
); new Rotate(degrees, 0, -meshType.mastOffset, 0, new Point3D(0, 0, 1))
sail.getTransforms().setAll( );
new Rotate(degrees, -meshType.sailOffset, 0,0, new Point3D(0, 0, 1)) sail.getTransforms().setAll(
); new Rotate(degrees, 0, -meshType.sailOffset,0, new Point3D(0, 0, 1))
);
}
} }
public void hideSail() { public void hideSail() {
@@ -69,4 +71,8 @@ public class BoatModel extends Model {
private MeshView getMeshViewChild(int index) { private MeshView getMeshViewChild(int index) {
return (MeshView) assets.getChildren().get(index); return (MeshView) assets.getChildren().get(index);
} }
public BoatMeshType getMeshType() {
return meshType;
}
} }
@@ -11,7 +11,7 @@ import javafx.scene.transform.Rotate;
/** /**
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 * BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path, * dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
* a wake object and two text labels to annotate the boat teams name and the boats velocity. The * a wake object and two text labels to annotate the boat teams name and the boatTypes velocity. The
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is * boat will update it's position onscreen everytime UpdatePosition is called unless the window is
* minimized in which case it attempts to store animations and apply them when the window is * minimized in which case it attempts to store animations and apply them when the window is
* maximised. * maximised.
@@ -28,15 +28,15 @@ public class BoatObject extends Group {
private Group wake; private Group wake;
private Color colour = Color.BLACK; private Color colour = Color.BLACK;
private Boolean isSelected = false; private Boolean isSelected = false;
private Rotate rotation = new Rotate(0,0,1); private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>(); private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
/** /**
* Creates a BoatGroup with the default triangular boat polygon. * Creates a BoatGroup with the default triangular boat polygon.
*/ */
public BoatObject() { public BoatObject(BoatMeshType boatMeshType) {
boatAssets = ModelFactory.boatGameView(BoatMeshType.DINGHY, colour); boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
boatAssets.hideSail(); boatAssets.hideSail();
boatAssets.getAssets().getTransforms().addAll( boatAssets.getAssets().getTransforms().addAll(
rotation rotation
@@ -66,8 +66,6 @@ public class BoatObject extends Group {
* @param windDir . * @param windDir .
*/ */
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) { public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
Double dx = Math.abs(boatAssets.getAssets().getLayoutX() - x);
Double dy = Math.abs(boatAssets.getAssets().getLayoutY() - y);
Platform.runLater(() -> { Platform.runLater(() -> {
rotateTo(rotation, sailIn, windDir); rotateTo(rotation, sailIn, windDir);
this.layoutXProperty().setValue(x); this.layoutXProperty().setValue(x);
@@ -7,6 +7,7 @@ import javafx.geometry.Point3D;
import javafx.scene.AmbientLight; import javafx.scene.AmbientLight;
import javafx.scene.CacheHint; import javafx.scene.CacheHint;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.PointLight;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial; import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Circle; import javafx.scene.shape.Circle;
@@ -18,7 +19,7 @@ import javafx.scene.transform.Translate;
/** /**
* Factory class for creating 3D models of boats. * Factory class for creating 3D models of boatTypes.
*/ */
public class ModelFactory { public class ModelFactory {
@@ -51,6 +52,35 @@ public class ModelFactory {
return bo; return bo;
} }
public static BoatModel boatCustomiseView(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
final Rotate animationRotate = new Rotate(0, new Point3D(0,0,1));
boatAssets.getTransforms().addAll(
new Scale(8.0, 8.0, 8.0),
new Rotate(-70, new Point3D(1,0,0)),
new Translate(16,50, 1),
animationRotate
);
boatAssets.getTransforms().add(animationRotate);
BoatModel bo = new BoatModel(boatAssets, null, boatType);
bo.rotateSail(45);
bo.setAnimation(new AnimationTimer() {
double boatAngle = 0;
Rotate rotate = animationRotate;
@Override
public void handle(long now) {
boatAngle += 0.5;
rotate.setAngle(boatAngle);
}
});
boatAssets.getChildren().addAll(
new AmbientLight()
);
return bo;
}
public static BoatModel boatRotatingView(BoatMeshType boatType, Color primaryColour) { public static BoatModel boatRotatingView(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour); Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
boatAssets.getTransforms().addAll( boatAssets.getTransforms().addAll(
@@ -84,20 +114,29 @@ public class ModelFactory {
} }
private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) { private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = new Group(); Group boatAssets = new Group();
MeshView hull = importFile(boatType.hullFile); MeshView hull = importSTL(boatType.hullFile);
hull.setMaterial(new PhongMaterial(primaryColour)); hull.setMaterial(new PhongMaterial(primaryColour));
MeshView mast = importFile(boatType.mastFile); MeshView mast = importSTL(boatType.mastFile);
mast.setMaterial(new PhongMaterial(primaryColour)); mast.setMaterial(new PhongMaterial(primaryColour));
MeshView sail = importFile(boatType.sailFile); MeshView sail = importSTL(boatType.sailFile);
sail.setMaterial(new PhongMaterial(Color.WHITE)); sail.setMaterial(new PhongMaterial(Color.WHITE));
boatAssets.getChildren().addAll(hull, mast, sail);
if (boatType.jibFile != null) {
MeshView jib = importSTL(boatType.jibFile);
sail.setMaterial(new PhongMaterial(Color.WHITE));
boatAssets.getChildren().addAll(hull, mast, sail, jib);
} else {
boatAssets.getChildren().addAll(hull, mast, sail);
}
return boatAssets; return boatAssets;
} }
private static MeshView importFile(String fileName) { private static MeshView importSTL(String fileName) {
StlMeshImporter importer = new StlMeshImporter(); StlMeshImporter importer = new StlMeshImporter();
importer.read(ModelFactory.class.getResource("/meshes/" + fileName)); importer.read(ModelFactory.class.getResource("/meshes/boatSTLs/" + fileName));
MeshView importedFile = new MeshView(importer.getImport()); MeshView importedFile = new MeshView(importer.getImport());
importedFile.setCache(true); importedFile.setCache(true);
importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE); importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 92 KiB

+17
View File
@@ -44,6 +44,11 @@
-fx-border-color: -fx-decorator-color; -fx-border-color: -fx-decorator-color;
-fx-border-width: 0 4 4 4; -fx-border-width: 0 4 4 4;
} }
.jfx-decorator-button {
-fx-focus-traversable: false; /* so decorator button will not be focused */
}
/********* customised scroll bar for scroll pane ***********/ /********* customised scroll bar for scroll pane ***********/
/* The main scrollbar **track** CSS class */ /* The main scrollbar **track** CSS class */
@@ -100,3 +105,15 @@
.slider .track { .slider .track {
-fx-background-color: -fx-pp-dark-text-color; -fx-background-color: -fx-pp-dark-text-color;
} }
.jfx-snackbar-content {
-fx-background-color: -fx-pp-front-color;
-fx-padding: 0 5 0 5;
-fx-spacing: 0 5 0 5;
-fx-font-size: 15;
}
.jfx-snackbar-toast {
-fx-text-fill: -fx-pp-theme-color;
-fx-font-size: 15;
}
+1
View File
@@ -48,6 +48,7 @@ GridPane .timer * {
-fx-text-fill: -fx-pp-theme-color; -fx-text-fill: -fx-pp-theme-color;
-fx-font-size: 13px; -fx-font-size: 13px;
-fx-pref-height: 35px; -fx-pref-height: 35px;
-fx-focus-traversable: false;
} }
#chatSend:hover { #chatSend:hover {
@@ -2,6 +2,7 @@
-fx-font-size: 20px; -fx-font-size: 20px;
-fx-text-fill: -fx-pp-light-text-color; -fx-text-fill: -fx-pp-light-text-color;
-fx-background-color: -fx-pp-theme-color; -fx-background-color: -fx-pp-theme-color;
-fx-focus-traversable: false;
} }
.jfx-rippler { .jfx-rippler {
@@ -0,0 +1,54 @@
#keyBindingDialogHeader {
-fx-font-size: 27px;
-fx-text-fill: -fx-pp-dark-text-color;
}
#closeLabel {
-fx-font-size: 30;
-fx-text-fill: -fx-pp-dark-text-color;
}
#closeLabel:hover {
-fx-text-fill: -fx-pp-theme-color;
-fx-font-size: 33;
}
JFXButton {
-fx-background-color: -fx-pp-light-text-color;
-fx-text-fill: -fx-pp-theme-color;
-fx-font-size: 13px;
}
Label {
-fx-font-size: 15px;
-fx-text-fill: -fx-pp-theme-color;
-fx-effect: -fx-pp-dropshadow-light;
}
JFXToggleButton {
-jfx-toggle-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-theme-color;
}
#resetBtn {
-fx-background-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-front-color;
-fx-effect: -fx-pp-dropshadow-light;
-fx-font-size: 18;
}
#resetBtn:hover {
-fx-font-size: 20;
}
.jfx-snackbar-content {
-fx-background-color: #323232;
}
.jfx-snackbar-toast {
-fx-text-fill: WHITE;
}
.jfx-snackbar-action {
-fx-text-fill: #ff4081;
}
@@ -0,0 +1,4 @@
/* a separate file to dynamically change snackbar's color */
.jfx-snackbar-toast {
-fx-text-fill: red !important;
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,7 +12,7 @@
</BoatShapes> </BoatShapes>
<Boats> <Boats>
<#list boats as boat> <#list boats as boat>
<Boat Type="Yacht" SourceID="${boat.sourceId}" ShapeID="4" HullNum="${boat.hullID}" StoweName="${boat.shortName}" ShortName="${boat.shortName}" <Boat Type="${boat.boatType}" SourceID="${boat.sourceId}" ShapeID="4" HullNum="${boat.hullID}" StoweName="${boat.shortName}" ShortName="${boat.shortName}"
BoatName="${boat.boatName}" Country="${boat.country}" Color="${boat.boatColor}"> BoatName="${boat.boatName}" Country="${boat.country}" Color="${boat.boatColor}">
<GPSposition Z="0" Y="3.7" X="0" /> <GPSposition Z="0" Y="3.7" X="0" />
<MastTop Z="0" Y="6.2" X="0" /> <MastTop Z="0" Y="6.2" X="0" />
+225 -227
View File
@@ -14,234 +14,232 @@
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<AnchorPane fx:id="rvAnchorPane" maxHeight="1.7976931348623157E308" <StackPane fx:id="contentStackPane" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity"
prefWidth="1200.0" style="-fx-background-color: lightblue;" xmlns="http://javafx.com/javafx/8" prefHeight="800.0" prefWidth="1200.0"
style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.RaceViewController"> fx:controller="seng302.visualiser.controllers.RaceViewController">
<children> <children>
<StackPane fx:id="contentAnchorPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="800.0" prefWidth="1200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
<children> prefHeight="800.0" prefWidth="1200.0">
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" <columnConstraints>
prefHeight="800.0" prefWidth="1200.0"> <ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0"
<columnConstraints> prefWidth="250.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
prefWidth="250.0"/> <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0"
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/> prefWidth="400.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0" </columnConstraints>
prefWidth="400.0"/> <rowConstraints>
</columnConstraints> <RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0"
<rowConstraints> vgrow="SOMETIMES"/>
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" <RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
vgrow="SOMETIMES"/> <RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0"
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/> valignment="BOTTOM" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0" </rowConstraints>
valignment="BOTTOM" vgrow="SOMETIMES"/> <children>
</rowConstraints> <GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0"
<children> styleClass="timer">
<GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0" <columnConstraints>
styleClass="timer"> <ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0"
<columnConstraints> prefWidth="50.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0"
prefWidth="50.0"/> minWidth="135.0" prefWidth="135.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0" </columnConstraints>
minWidth="135.0" prefWidth="135.0"/> <rowConstraints>
</columnConstraints> <RowConstraints minHeight="10.0" prefHeight="30.0"
<rowConstraints> vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" </rowConstraints>
vgrow="SOMETIMES"/> <opaqueInsets>
</rowConstraints> <Insets/>
<opaqueInsets> </opaqueInsets>
<Insets/> <GridPane.margin>
</opaqueInsets> <Insets left="10.0" right="200.0" top="10.0"/>
<GridPane.margin> </GridPane.margin>
<Insets left="10.0" right="200.0" top="10.0"/> <children>
</GridPane.margin> <ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true"
<children> preserveRatio="true" GridPane.halignment="CENTER"
<ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true" GridPane.valignment="CENTER">
preserveRatio="true" GridPane.halignment="CENTER" <image>
GridPane.valignment="CENTER"> <Image url="@../images/timer.png"/>
<image> </image>
<Image url="@../images/timer.png"/> <GridPane.margin>
</image> <Insets/>
<GridPane.margin> </GridPane.margin>
<Insets/> </ImageView>
</GridPane.margin> <Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1"
</ImageView> GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1" <font>
GridPane.halignment="CENTER" GridPane.valignment="CENTER"> <Font size="21.0"/>
<font> </font>
<Font size="21.0"/> <GridPane.margin>
</font> <Insets/>
<GridPane.margin> </GridPane.margin>
<Insets/> </Label>
</GridPane.margin> </children>
</Label> </GridPane>
</children> <GridPane GridPane.columnIndex="2">
</GridPane> <columnConstraints>
<GridPane GridPane.columnIndex="2"> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
<columnConstraints> prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/> prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" </columnConstraints>
prefWidth="100.0"/> <rowConstraints>
</columnConstraints> <RowConstraints minHeight="10.0" prefHeight="30.0"
<rowConstraints> vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" </rowConstraints>
vgrow="SOMETIMES"/> </GridPane>
</rowConstraints> <GridPane fx:id="chatGridPane" GridPane.columnIndex="2"
</GridPane> GridPane.rowIndex="2">
<GridPane fx:id="chatGridPane" GridPane.columnIndex="2" <columnConstraints>
GridPane.rowIndex="2"> <ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0"
<columnConstraints> minWidth="390.0" prefWidth="390.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" </columnConstraints>
minWidth="390.0" prefWidth="390.0"/> <rowConstraints>
</columnConstraints> <RowConstraints maxHeight="1.7976931348623157E308"
<rowConstraints> vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308" <RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" </rowConstraints>
vgrow="SOMETIMES"/> <children>
</rowConstraints> <Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0"
<children> GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM"
<Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0" GridPane.vgrow="ALWAYS">
GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM" <GridPane.margin>
GridPane.vgrow="ALWAYS"> <Insets/>
<GridPane.margin> </GridPane.margin>
<Insets/> <padding>
</GridPane.margin> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
<padding> </padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> </Pane>
</padding> <GridPane fx:id="chatInputHolder" GridPane.rowIndex="1">
</Pane> <columnConstraints>
<GridPane fx:id="chatInputHolder" GridPane.rowIndex="1"> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
<columnConstraints> prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
prefWidth="100.0"/> minWidth="90.0" prefWidth="90.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" </columnConstraints>
minWidth="90.0" prefWidth="90.0"/> <rowConstraints>
</columnConstraints> <RowConstraints maxHeight="50.0" minHeight="50.0"
<rowConstraints> prefHeight="50.0" valignment="CENTER" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" </rowConstraints>
prefHeight="50.0" valignment="CENTER" vgrow="SOMETIMES"/> <children>
</rowConstraints> <JFXButton fx:id="chatSend" alignment="CENTER"
<children> buttonType="RAISED" maxHeight="-Infinity"
<JFXButton fx:id="chatSend" alignment="CENTER" maxWidth="1.7976931348623157E308" minHeight="-Infinity"
buttonType="RAISED" maxHeight="-Infinity" minWidth="-Infinity" prefHeight="35.0" text="SEND"
maxWidth="1.7976931348623157E308" minHeight="-Infinity" GridPane.columnIndex="1">
minWidth="-Infinity" prefHeight="35.0" text="SEND" <GridPane.margin>
GridPane.columnIndex="1"> <Insets bottom="10.0" left="10.0" right="10.0"
<GridPane.margin> top="10.0"/>
<Insets bottom="10.0" left="10.0" right="10.0" </GridPane.margin>
top="10.0"/> </JFXButton>
</GridPane.margin> <JFXTextField fx:id="chatInput" maxHeight="35.0"
</JFXButton> minHeight="-Infinity" prefHeight="35.0">
<JFXTextField fx:id="chatInput" maxHeight="35.0" <GridPane.margin>
minHeight="-Infinity" prefHeight="35.0"> <Insets bottom="10.0" left="20.0" right="10.0"/>
<GridPane.margin> </GridPane.margin>
<Insets bottom="10.0" left="20.0" right="10.0"/> <padding>
</GridPane.margin> <Insets right="15.0"/>
<padding> </padding>
<Insets right="15.0"/> </JFXTextField>
</padding> </children>
</JFXTextField> <GridPane.margin>
</children> <Insets top="10.0"/>
<GridPane.margin> </GridPane.margin>
<Insets top="10.0"/> </GridPane>
</GridPane.margin> </children>
</GridPane> <GridPane.margin>
</children> <Insets bottom="10.0" right="10.0"/>
<GridPane.margin> </GridPane.margin>
<Insets bottom="10.0" right="10.0"/> </GridPane>
</GridPane.margin> <GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity"
</GridPane> prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER"
<GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity" GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER" <columnConstraints>
GridPane.rowIndex="2" GridPane.valignment="BOTTOM"> <ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0"
<columnConstraints> minWidth="110.0" prefWidth="110.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0"
minWidth="110.0" prefWidth="110.0"/> minWidth="10.0"
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0" prefWidth="132.0"/>
prefWidth="132.0"/> </columnConstraints>
</columnConstraints> <rowConstraints>
<rowConstraints> <RowConstraints maxHeight="120.0" minHeight="120.0"
<RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0" vgrow="SOMETIMES"/>
prefHeight="120.0" vgrow="SOMETIMES"/> <RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
vgrow="SOMETIMES"/> </rowConstraints>
</rowConstraints> <children>
<children> <Label fx:id="positionLabel" text="Position:"
<Label fx:id="positionLabel" text="Position:" GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="TOP">
GridPane.rowSpan="2" GridPane.valignment="TOP"> <padding>
<padding> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> </padding>
</padding> </Label>
</Label> <Label fx:id="boatSpeedLabel" text="Boat Speed:"
<Label fx:id="boatSpeedLabel" text="Boat Speed:" GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="CENTER">
GridPane.rowSpan="2" GridPane.valignment="CENTER"> <opaqueInsets>
<opaqueInsets> <Insets/>
<Insets/> </opaqueInsets>
</opaqueInsets> <padding>
<padding> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> </padding>
</padding> </Label>
</Label> <Label fx:id="boatHeadingLabel" text="Boat Heading:"
<Label fx:id="boatHeadingLabel" text="Boat Heading:" GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="BOTTOM">
GridPane.rowSpan="2" GridPane.valignment="BOTTOM"> <padding>
<padding> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> </padding>
</padding> </Label>
</Label> <GridPane fx:id="windHolder" GridPane.rowSpan="2">
<GridPane fx:id="windHolder" GridPane.rowSpan="2"> <columnConstraints>
<columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
prefWidth="100.0"/> </columnConstraints>
</columnConstraints> <rowConstraints>
<rowConstraints> <RowConstraints maxHeight="120.0" minHeight="120.0"
<RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0" vgrow="SOMETIMES"/>
prefHeight="120.0" vgrow="SOMETIMES"/> <RowConstraints maxHeight="30.0" minHeight="30.0"
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
prefHeight="30.0" vgrow="SOMETIMES"/> </rowConstraints>
</rowConstraints> <children>
<children> <ImageView fx:id="windImageView" fitHeight="92.0"
<ImageView fx:id="windImageView" fitHeight="92.0" fitWidth="109.0" pickOnBounds="true" preserveRatio="true"
fitWidth="109.0" pickOnBounds="true" preserveRatio="true" GridPane.halignment="CENTER" GridPane.rowSpan="2"
GridPane.halignment="CENTER" GridPane.rowSpan="2" GridPane.valignment="CENTER"/>
GridPane.valignment="CENTER"/> <Label fx:id="windSpeedLabel" text="0.0 Knots"
<Label fx:id="windSpeedLabel" text="0.0 Knots" GridPane.halignment="RIGHT" GridPane.rowIndex="1"
GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
GridPane.valignment="CENTER"> <GridPane.margin>
<GridPane.margin> <Insets right="5.0"/>
<Insets right="5.0"/> </GridPane.margin>
</GridPane.margin> </Label>
</Label> <Label fx:id="windDirectionLabel" text="180.0°"
<Label fx:id="windDirectionLabel" text="180.0°" GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.halignment="LEFT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
GridPane.valignment="CENTER"> <GridPane.margin>
<GridPane.margin> <Insets left="5.0"/>
<Insets left="5.0"/> </GridPane.margin>
</GridPane.margin> </Label>
</Label> </children>
</children> </GridPane>
</GridPane> </children>
</children> <opaqueInsets>
<opaqueInsets> <Insets/>
<Insets/> </opaqueInsets>
</opaqueInsets> <GridPane.margin>
<GridPane.margin> <Insets bottom="10.0" left="10.0" top="40.0"/>
<Insets bottom="10.0" left="10.0" top="40.0"/> </GridPane.margin>
</GridPane.margin> </GridPane>
</GridPane> </children>
</children> </GridPane>
</GridPane> </children>
</children>
</StackPane>
</children>
<stylesheets> <stylesheets>
<String fx:value="/css/Master.css" /> <String fx:value="/css/Master.css"/>
<String fx:value="/css/RaceView.css" /> <String fx:value="/css/RaceView.css"/>
</stylesheets> </stylesheets>
</AnchorPane> </StackPane>
@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXButton?> <?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXColorPicker?> <?import com.jfoenix.controls.JFXColorPicker?>
<?import com.jfoenix.controls.JFXDialogLayout?> <?import com.jfoenix.controls.JFXDialogLayout?>
@@ -10,54 +16,45 @@
<?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" <JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.dialogs.BoatCustomizeController">
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.dialogs.BoatCustomizeController">
<children> <children>
<GridPane> <GridPane>
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" /> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="90.0" minHeight="90.0" prefHeight="90.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="90.0" minHeight="48.0" prefHeight="48.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="100.0" minHeight="100.0" prefHeight="100.0" vgrow="SOMETIMES" /> <RowConstraints maxHeight="207.0" minHeight="93.0" prefHeight="181.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="125.0" minHeight="61.0" prefHeight="99.0" <RowConstraints maxHeight="207.0" minHeight="93.0" prefHeight="181.0" vgrow="SOMETIMES" />
vgrow="SOMETIMES"/> <RowConstraints maxHeight="145.0" minHeight="66.0" prefHeight="109.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="164.0" minHeight="100.0" prefHeight="126.0" <RowConstraints maxHeight="125.0" minHeight="24.0" prefHeight="72.0" vgrow="SOMETIMES" />
vgrow="SOMETIMES"/> <RowConstraints maxHeight="164.0" minHeight="100.0" prefHeight="105.0" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label fx:id="hostDialogHeader" text="Customize Boat" GridPane.halignment="CENTER" <Label fx:id="hostDialogHeader" text="Customize Boat" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
GridPane.valignment="CENTER"/> <JFXButton fx:id="submitBtn" prefHeight="45.0" prefWidth="220.0" text="Customize Boat" GridPane.halignment="CENTER" GridPane.rowIndex="5" GridPane.valignment="CENTER" />
<JFXButton fx:id="submitBtn" prefHeight="45.0" prefWidth="220.0" text="Customize Boat" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER" /> <JFXTextField fx:id="boatName" focusColor="#6c6c6c" promptText="Boat Name" unFocusColor="#6b6b6b" GridPane.rowIndex="3">
<JFXTextField fx:id="boatName" focusColor="#6c6c6c" promptText="Boat Name"
unFocusColor="#6b6b6b" GridPane.rowIndex="1">
<GridPane.margin> <GridPane.margin>
<Insets left="30.0" right="30.0" /> <Insets left="30.0" right="30.0" />
</GridPane.margin></JFXTextField> </GridPane.margin></JFXTextField>
<GridPane GridPane.halignment="CENTER" GridPane.rowIndex="2" <GridPane GridPane.halignment="CENTER" GridPane.rowIndex="4" GridPane.valignment="CENTER">
GridPane.valignment="CENTER">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="139.0" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="139.0" minWidth="10.0" prefWidth="94.0" />
prefWidth="94.0"/> <ColumnConstraints hgrow="SOMETIMES" maxWidth="203.0" minWidth="10.0" prefWidth="198.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="203.0" minWidth="10.0"
prefWidth="198.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints percentHeight="100.0" valignment="CENTER" vgrow="SOMETIMES"/> <RowConstraints percentHeight="100.0" valignment="CENTER" vgrow="SOMETIMES" />
</rowConstraints> </rowConstraints>
<children> <children>
<Label fx:id="boatColorLabel" prefHeight="25.0" prefWidth="96.0" <Label fx:id="boatColorLabel" prefHeight="25.0" prefWidth="96.0" text="Boat Color" GridPane.valignment="CENTER">
text="Boat Color" GridPane.valignment="CENTER">
<GridPane.margin> <GridPane.margin>
<Insets top="-10.0" /> <Insets top="-10.0" />
</GridPane.margin> </GridPane.margin>
</Label> </Label>
<JFXColorPicker fx:id="colorPicker" onAction="#colorChanged" <JFXColorPicker fx:id="colorPicker" onAction="#colorChanged" GridPane.columnIndex="1" GridPane.valignment="CENTER">
GridPane.columnIndex="1" GridPane.valignment="CENTER">
<GridPane.margin> <GridPane.margin>
<Insets left="30.0" top="-10.0"/> <Insets left="30.0" top="-10.0" />
</GridPane.margin> </GridPane.margin>
</JFXColorPicker> </JFXColorPicker>
</children> </children>
@@ -65,11 +62,45 @@
<Insets left="30.0" right="30.0" /> <Insets left="30.0" right="30.0" />
</GridPane.margin> </GridPane.margin>
</GridPane> </GridPane>
<GridPane GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="50.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="256.0" minWidth="10.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="50.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Pane fx:id="boatPane" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
<JFXButton buttonType="RAISED" onAction="#prevBoat" prefHeight="200.0" prefWidth="50.0" text="&lt;" />
<JFXButton buttonType="RAISED" onAction="#nextBoat" prefHeight="200.0" prefWidth="50.0" text="&gt;" GridPane.columnIndex="2" />
</children>
</GridPane>
<GridPane GridPane.rowIndex="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Max Speed:" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Acceleration:" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Handling:" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER" />
<ProgressBar fx:id="speedBar" focusTraversable="false" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" />
<ProgressBar fx:id="accelBar" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<ProgressBar fx:id="handleBar" prefWidth="200.0" progress="0.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
</children>
</GridPane>
</children> </children>
</GridPane> </GridPane>
</children> </children>
<stylesheets> <stylesheets>
<String fx:value="/css/dialogs/BoatCustomize.css"/> <String fx:value="/css/dialogs/BoatCustomize.css" />
<String fx:value="/css/Master.css"/> <String fx:value="/css/Master.css" />
</stylesheets> </stylesheets>
</JFXDialogLayout> </JFXDialogLayout>
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXDialogLayout?>
<?import com.jfoenix.controls.JFXToggleButton?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<JFXDialogLayout fx:id="keyBindDialog" maxHeight="-Infinity" maxWidth="-Infinity"
minHeight="-Infinity" minWidth="-Infinity" prefHeight="580.0" prefWidth="500.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.dialogs.KeyBindingDialogController">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="100.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="70.0"
vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Label fx:id="keyBindingDialogHeader" text="CUSTOM KEYBIND" GridPane.columnSpan="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
<Label text="ZOOM IN" GridPane.halignment="CENTER" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label text="ZOOM OUT" GridPane.halignment="CENTER" GridPane.rowIndex="2"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label text="VMG" GridPane.halignment="CENTER" GridPane.rowIndex="3"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label text="SAILS IN/OUT" GridPane.halignment="CENTER" GridPane.rowIndex="4"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label text="TACK/GYBE" GridPane.halignment="CENTER" GridPane.rowIndex="5"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label fx:id="upwindLabel" text="UPWIND" GridPane.halignment="CENTER"
GridPane.rowIndex="6" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<Label fx:id="downwindLabel" text="DOWNWIND" GridPane.halignment="CENTER"
GridPane.rowIndex="7" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin></Label>
<JFXButton id="ZOOM IN" fx:id="zoomInbtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0" text="Z"
GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1"
GridPane.valignment="CENTER"/>
<JFXButton id="ZOOM OUT" fx:id="zoomOutBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0" text="X"
GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2"
GridPane.valignment="CENTER"/>
<JFXButton id="VMG" fx:id="vmgBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
text="SPACE" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="3" GridPane.valignment="CENTER"/>
<JFXButton id="SAILS IN/OUT" fx:id="sailInOutBtn" buttonType="RAISED"
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity"
prefWidth="120.0" text="SHIFT" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="4" GridPane.valignment="CENTER"/>
<JFXButton id="TACK/GYBE" fx:id="tackGybeBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
text="ENTER" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="5" GridPane.valignment="CENTER"/>
<JFXButton id="UPWIND" fx:id="upwindBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
text="PAGE_UP" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="6" GridPane.valignment="CENTER"/>
<JFXButton id="DOWNWIND" fx:id="downwindBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="35.0" minWidth="-Infinity" prefWidth="120.0"
text="PAGE_DOWN" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="7" GridPane.valignment="CENTER"/>
<JFXToggleButton fx:id="turningToggle" minHeight="-Infinity" prefHeight="35.0"
text="OFF / ON" GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="8"/>
<Label text="CONTINUOUSLY TURNING" GridPane.halignment="CENTER" GridPane.rowIndex="8"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin>
</Label>
<JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0"
prefWidth="150.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="CENTER"
GridPane.rowIndex="9" GridPane.valignment="CENTER"/>
<Label fx:id="closeLabel" text="✖" translateY="-5.0" GridPane.columnIndex="1"
GridPane.halignment="RIGHT" GridPane.valignment="TOP"/>
</children>
</GridPane>
</children>
<stylesheets>
<URL value="@../../css/dialogs/KeyBindingDialog.css" />
<URL value="@../../css/Master.css" />
</stylesheets>
</JFXDialogLayout>
@@ -7,6 +7,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import seng302.gameServer.GameState; import seng302.gameServer.GameState;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* Test update function in Yacht.java to make sure yacht will not be collide each other within 25.0 * Test update function in Yacht.java to make sure yacht will not be collide each other within 25.0
@@ -14,8 +15,10 @@ import seng302.utilities.GeoUtility;
*/ */
public class UpdateYachtTest { public class UpdateYachtTest {
private ServerYacht yacht1 = new ServerYacht("Yacht", 1, "1", "Yacht" + 1, "Yacht" + 1, "Test1"); private ServerYacht yacht1 = new ServerYacht(BoatMeshType.DINGHY, 1, "1", "Yacht" + 1,
private ServerYacht yacht2 = new ServerYacht("Yacht", 2, "2", "Yacht" + 2, "Yacht" + 2, "Test2"); "Yacht" + 1, "Test1");
private ServerYacht yacht2 = new ServerYacht(BoatMeshType.DINGHY, 2, "2", "Yacht" + 2,
"Yacht" + 2, "Test2");
private GeoPoint geoPoint1 = new GeoPoint(50.0, 50.0); private GeoPoint geoPoint1 = new GeoPoint(50.0, 50.0);
private GeoPoint geoPoint2 = GeoUtility.getGeoCoordinate(geoPoint1, 90.0, 50.0); private GeoPoint geoPoint2 = GeoUtility.getGeoCoordinate(geoPoint1, 90.0, 50.0);
+3 -1
View File
@@ -4,6 +4,8 @@ import org.junit.AfterClass;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import seng302.gameServer.GameState; import seng302.gameServer.GameState;
import seng302.model.ServerYacht; import seng302.model.ServerYacht;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
public class YachtTest { public class YachtTest {
@@ -17,7 +19,7 @@ public class YachtTest {
@BeforeClass @BeforeClass
public static void setUp() { public static void setUp() {
new GameState(); new GameState();
y1 = new ServerYacht("Yacht", 1, "Y1", "Y1", "Yacht 1", "C1"); y1 = new ServerYacht(BoatMeshType.DINGHY, 1, "Y1", "Y1", "Yacht 1", "C1");
gs = new GameState(); gs = new GameState();
} }
@@ -0,0 +1,28 @@
package seng302.utilities;
import org.junit.Assert;
import org.junit.Test;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/**
* Basic tests for the next and previous methods
* Created by kre39 on 20/09/17.
*/
public class BoatMeshTypeTest {
@Test
public void testNextBoatMeshType() {
BoatMeshType currentBoat = BoatMeshType.DINGHY;
BoatMeshType nextBoat = BoatMeshType.getNextBoatType(currentBoat);
Assert.assertEquals(BoatMeshType.CATAMARAN, nextBoat);
}
@Test
public void testPreviousBoatMeshType() {
BoatMeshType currentBoat = BoatMeshType.CATAMARAN;
BoatMeshType prevBoat = BoatMeshType.getPrevBoatType(currentBoat);
Assert.assertEquals(BoatMeshType.DINGHY, prevBoat);
}
}
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/** /**
* Created by kre39 on 6/08/17. * Created by kre39 on 6/08/17.
@@ -16,7 +17,7 @@ public class BoatSailAnimationToggleTest {
@Before @Before
public void setup() throws Exception{ public void setup() throws Exception{
yacht = new ClientYacht("Yacht", 1, "YACHT", "YAC", "Test Yacht", "NZ"); yacht = new ClientYacht(BoatMeshType.DINGHY, 1, "YACHT", "YAC", "Test Yacht", "NZ");
} }
@Test @Test
+1
View File
@@ -13,6 +13,7 @@ import seng302.model.ServerYacht;
import seng302.visualiser.ClientToServerThread; import seng302.visualiser.ClientToServerThread;
/** /**
*
* Created by kre39 on 7/08/17. * Created by kre39 on 7/08/17.
*/ */
public class ToggleSailSteps { public class ToggleSailSteps {