Merge branch 'story1275_host_customization' into 1273_Skybox

# Conflicts:
#	src/main/java/seng302/visualiser/GameView3D.java
#	src/main/java/seng302/visualiser/controllers/LobbyController.java
#	src/main/java/seng302/visualiser/controllers/ViewManager.java
#	src/main/resources/views/LobbyView.fxml
#	src/main/resources/views/RaceView.fxml
This commit is contained in:
Calum
2017-09-26 01:19:47 +13:00
71 changed files with 2156 additions and 1847 deletions
@@ -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;
}
}
+5
View File
@@ -15,4 +15,9 @@ public class Limit extends GeoPoint {
public Integer getSeqID() {
return seqID;
}
@Override
public String toString(){
return "Limit = {seqID=" + seqID + ", lat=" + getLat() + ", lng=" + getLng() + "}";
}
}
@@ -0,0 +1,122 @@
package seng302.model;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javafx.geometry.Point2D;
import seng302.utilities.GeoUtility;
/**
* Contains information on a scaled lat lon point for use with mapping geographical elements to a 2d plane.
*/
public class ScaledPoint extends GeoPoint {
public enum ScaleDirection {
HORIZONTAL,
VERTICAL
}
private double x, y, scaleFactor;
private ScaleDirection scaleDirection;
private ScaledPoint(double lat, double lng, double x, double y, double scaleFactor, ScaleDirection direction) {
super(lat, lng);
this.x = x;
this.y = y;
this.scaleFactor = scaleFactor;
this.scaleDirection = direction;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getScaleFactor() {
return scaleFactor;
}
public ScaleDirection getScaleDirection() {
return scaleDirection;
}
public Point2D findScaledXY(GeoPoint unscaled) {
return findScaledXY(unscaled.getLat(), unscaled.getLng());
}
public Point2D findScaledXY(double unscaledLat, double unscaledLon) {
double distanceFromReference;
double angleFromReference;
double xReference = this.getX();
double yReference = this.getY();
angleFromReference = GeoUtility.getBearingRad(
this, new GeoPoint(unscaledLat, unscaledLon)
);
distanceFromReference = GeoUtility.getDistance(
this, new GeoPoint(unscaledLat, unscaledLon)
);
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
xReference += scaleFactor * Math.sin(angleFromReference) * distanceFromReference;
yReference -= scaleFactor * Math.cos(angleFromReference) * distanceFromReference;
} else if (angleFromReference >= 0) {
angleFromReference = angleFromReference - Math.PI / 2;
xReference += scaleFactor * Math.cos(angleFromReference) * distanceFromReference;
yReference += scaleFactor * Math.sin(angleFromReference) * distanceFromReference;
} else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) {
angleFromReference = Math.abs(angleFromReference);
xReference -= scaleFactor * Math.sin(angleFromReference) * distanceFromReference;
yReference -= scaleFactor * Math.cos(angleFromReference) * distanceFromReference;
} else {
angleFromReference = Math.abs(angleFromReference) - Math.PI / 2;
xReference -= scaleFactor * Math.cos(angleFromReference) * distanceFromReference;
yReference += scaleFactor * Math.sin(angleFromReference) * distanceFromReference;
}
return new Point2D(xReference, yReference);
}
public static ScaledPoint makeScaledPoint(double width, double height,
List<? extends GeoPoint> points, boolean centered) {
double referencePointX, referencePointY, scaleFactor, lat, lng;
ScaleDirection scaleDirection;
points = new ArrayList<>(points);
points.sort(Comparator.comparingDouble(GeoPoint::getLat));
GeoPoint minLatPoint = points.get(0);
GeoPoint maxLatPoint = points.get(points.size() - 1);
points.sort(Comparator.comparingDouble(GeoPoint::getLng));
GeoPoint minLonPoint = points.get(0);
GeoPoint maxLonPoint = points.get(points.size() - 1);
referencePointX = centered ? 0 : width / 2;
referencePointY = centered ? 0 : height / 2;
lat = (maxLatPoint.getLat() - minLatPoint.getLat()) / 2 + minLatPoint.getLat();
lng = (maxLonPoint.getLng() - minLonPoint.getLng()) / 2 + minLonPoint.getLng();
GeoPoint ref = new GeoPoint(lat, lng);
double vertDistance = GeoUtility.getDistance(
ref, new GeoPoint(ref.getLat(), maxLonPoint.getLng())
) * 2.1;
double horiDistance = GeoUtility.getDistance(
ref, new GeoPoint(maxLatPoint.getLat(), ref.getLng())
) * 2.1;
double vertScale = height / vertDistance;
if (horiDistance * vertScale > width) {
scaleFactor = width / horiDistance;
scaleDirection = ScaleDirection.HORIZONTAL;
} else {
scaleFactor = vertScale;
scaleDirection = ScaleDirection.VERTICAL;
}
return new ScaledPoint(lat, lng, referencePointX, referencePointY, scaleFactor, scaleDirection);
}
}
+47 -36
View File
@@ -1,5 +1,6 @@
package seng302.model;
import java.util.HashMap;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,12 +11,6 @@ import seng302.model.token.TokenType;
import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import java.util.HashMap;
import java.util.Objects;
import java.util.Observable;
import java.util.Observer;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
/**
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
* compared to the XMLParser boat class, also done outside Boat class because some old variables are
@@ -61,6 +56,8 @@ public class ServerYacht {
private TokenType powerUp;
private Long powerUpStartTime;
//turning mode
private Boolean continuouslyTurning;
public ServerYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
String boatName, String country) {
@@ -85,6 +82,8 @@ public class ServerYacht {
this.hasEnteredRoundingZone = false;
this.hasPassedLine = false;
this.hasPassedThroughGate = false;
this.continuouslyTurning = false;
}
@@ -192,44 +191,52 @@ public class ServerYacht {
public void turnUpwind() {
disableAutoPilot();
Double normalizedHeading = normalizeHeading();
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 {
if (continuouslyTurning) {
adjustHeading(turnStep);
} else {
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() {
disableAutoPilot();
Double normalizedHeading = normalizeHeading();
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 {
if (continuouslyTurning) {
adjustHeading(-turnStep);
} else {
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);
}
}
}
@@ -445,4 +452,8 @@ public class ServerYacht {
public BoatMeshType getBoatType() {
return boatType;
}
public void setContinuouslyTurning(Boolean continuouslyTurning) {
this.continuouslyTurning = continuouslyTurning;
}
}
@@ -1,6 +1,6 @@
package seng302.model.mark;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import seng302.gameServer.messages.RoundingSide;
import seng302.model.GeoPoint;
@@ -10,13 +10,13 @@ public class CompoundMark {
private int compoundMarkId;
private String name;
private List<Mark> marks = new ArrayList<>();
private List<Mark> marks;
private GeoPoint midPoint;
public CompoundMark(int markID, String name, List<Mark> marks) {
this.compoundMarkId = markID;
this.name = name;
this.marks.addAll(marks);
this.marks = Collections.unmodifiableList(marks);
if (marks.size() > 1) {
this.midPoint = GeoUtility.getDirtyMidPoint(marks.get(0), marks.get(1));
} else {
@@ -32,4 +32,10 @@ public class Corner {
public Integer getZoneSize() {
return zoneSize;
}
@Override
public String toString() {
return "Corner = {seqID=" + seqID + ", compoundMarkID=" + compoundMarkID + ", rounding="
+ rounding +", zoneSize=" + zoneSize + "}";
}
}
+13 -84
View File
@@ -1,23 +1,12 @@
package seng302.model.mark;
import java.io.IOException;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import seng302.gameServer.messages.RoundingSide;
import seng302.model.ServerYacht;
import seng302.model.stream.xml.generator.RaceXMLTemplate;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.token.Token;
import seng302.utilities.XMLGenerator;
import seng302.utilities.XMLParser;
import java.util.*;
/**
* Class to hold the order of the marks in the race.
@@ -25,10 +14,17 @@ import java.util.*;
public class MarkOrder {
private List<CompoundMark> raceMarkOrder;
private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
private Set<Mark> allMarks;
public MarkOrder(){
loadRaceProperties();
public MarkOrder(RaceXMLData raceXMLData){
raceMarkOrder = new ArrayList<>();
for (Corner corner : raceXMLData.getMarkSequence()){
CompoundMark compoundMark = raceXMLData.getCompoundMarks().get(corner.getCompoundMarkID());
compoundMark.setRoundingSide(
RoundingSide.getRoundingSide(corner.getRounding())
);
raceMarkOrder.add(compoundMark);
}
}
/**
@@ -40,7 +36,6 @@ public class MarkOrder {
logger.warn("Race order accessed but not instantiated");
return null;
}
return Collections.unmodifiableList(raceMarkOrder);
}
@@ -74,70 +69,4 @@ public class MarkOrder {
public CompoundMark getNextMark(Integer currentSeqID) throws IndexOutOfBoundsException {
return raceMarkOrder.get(currentSeqID + 1);
}
public Set<Mark> getAllMarks(){
return Collections.unmodifiableSet(allMarks);
}
/**
* Loads the race order from an XML string
* @param xml An AC35 RaceXML
* @return An ordered list of marks in the race
*/
private List<CompoundMark> loadRaceOrderFromXML(String xml) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
Document doc;
allMarks = new HashSet<>();
try {
db = dbf.newDocumentBuilder();
doc = db.parse(new InputSource(new StringReader(xml)));
} catch (ParserConfigurationException | IOException | SAXException e) {
logger.error("Failed to read generated race XML");
return null;
}
RaceXMLData data = XMLParser.parseRace(doc);
if (data != null){
logger.debug("Loaded RaceXML for mark order");
List<Corner> corners = data.getMarkSequence();
Map<Integer, CompoundMark> marks = data.getCompoundMarks();
List<CompoundMark> course = new ArrayList<>();
for (Corner corner : corners){
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
compoundMark.setRoundingSide(
RoundingSide.getRoundingSide(corner.getRounding())
);
course.add(compoundMark);
allMarks.addAll(compoundMark.getMarks());
}
return course;
}
return null;
}
/**
* Load the raceXML and mark order
*/
private void loadRaceProperties(){
XMLGenerator generator = new XMLGenerator();
// TODO: 29/08/17 wmu16 - This is terrible, having to make a template just to receive constant data
generator.setRaceTemplate(new RaceXMLTemplate(
new ArrayList<>(),
new ArrayList<>()));
String raceXML = generator.getRaceAsXml();
if (raceXML == null){
logger.error("Failed to generate raceXML (for race properties)");
return;
}
raceMarkOrder = loadRaceOrderFromXML(raceXML);
}
}
@@ -1,10 +1,12 @@
package seng302.model.stream.xml.generator;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import seng302.model.Limit;
import seng302.model.ServerYacht;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner;
import seng302.model.token.Token;
/**
@@ -15,10 +17,17 @@ public class RaceXMLTemplate {
private List<ServerYacht> yachts;
private LocalDateTime startTime;
private List<Token> tokens;
private List<Corner> roundings;
private List<Limit> courseLimit;
private List<CompoundMark> course;
public RaceXMLTemplate(List<ServerYacht> yachts, List<Token> tokens) {
public RaceXMLTemplate(List<ServerYacht> yachts, List<Token> tokens, List<Corner> roundings,
List<Limit> limit, List<CompoundMark> course) {
this.yachts = yachts;
this.tokens = tokens;
this.roundings = roundings;
this.courseLimit = limit;
this.course = course;
startTime = LocalDateTime.now();
}
@@ -39,6 +48,18 @@ public class RaceXMLTemplate {
return Collections.unmodifiableList(tokens);
}
public List<CompoundMark> getCompoundMarks() {
return Collections.unmodifiableList(course);
}
public List<Limit> getCourseLimit() {
return Collections.unmodifiableList(courseLimit);
}
public List<Corner> getRoundings() {
return Collections.unmodifiableList(roundings);
}
/**
* Set the time until the race starts
* @param seconds The time in seconds until the race starts
@@ -54,4 +75,12 @@ public class RaceXMLTemplate {
public String getRaceStartTime(){
return startTime.toString();
}
public void setBoats(List<ServerYacht> boats) {
yachts = boats;
}
public void setTokens(List<Token> tokens) {
this.tokens = tokens;
}
}