mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Merge branch 'develop' into wind_arrow
# Conflicts: # src/main/java/seng302/visualiser/controllers/RaceViewController.java # src/main/resources/views/RaceView.fxml
This commit is contained in:
@@ -103,8 +103,7 @@ public class App extends Application {
|
|||||||
public void run() {
|
public void run() {
|
||||||
System.gc();
|
System.gc();
|
||||||
}
|
}
|
||||||
}, 0, 1200);
|
}, 0, 1_000);
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parseArgs(args);
|
parseArgs(args);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class DiscoveryServer {
|
|||||||
" .:;...'cxxxxxxxxxxxxoc;,::,..cdl;;l' \n" +
|
" .:;...'cxxxxxxxxxxxxoc;,::,..cdl;;l' \n" +
|
||||||
" .cl;':,'';oxxxxxxdxxxxxx:....,cooc,cO; \n" +
|
" .cl;':,'';oxxxxxxdxxxxxx:....,cooc,cO; \n" +
|
||||||
" .,,,::;,lxoc:,,:lxxxxxxxxxxxo:,,;lxxl;'oNc \n" +
|
" .,,,::;,lxoc:,,:lxxxxxxxxxxxo:,,;lxxl;'oNc \n" +
|
||||||
" .cdxo;':lxxxxxxc'';cccccoxxxxxxxxxxxxo,.;lc. " + ANSI_YELLOW + "Party-Parrots-At-Sea Discovery Server v0.1 " + selectedColor +"\n" +
|
" .cdxo;':lxxxxxxc'';cccccoxxxxxxxxxxxxo,.;lc. " + ANSI_YELLOW + "Party-Parrots-At-Sea Discovery Server v1.0.0 (Release) " + selectedColor +"\n" +
|
||||||
" .loc'.'lxxxxxxxxocc;''''';ccoxxxxxxxxx:..oc \n" +
|
" .loc'.'lxxxxxxxxocc;''''';ccoxxxxxxxxx:..oc \n" +
|
||||||
"olc,..',:cccccccccccc:;;;;;;;;:ccccccccc,.'c, \n" +
|
"olc,..',:cccccccccccc:;;;;;;;;:ccccccccc,.'c, \n" +
|
||||||
"Ol;......................................;l' ");
|
"Ol;......................................;l' ");
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
public class DiscoveryServerClient {
|
public class DiscoveryServerClient {
|
||||||
private final Integer UPDATE_INTERVAL_MS = 5000;
|
private final Integer UPDATE_INTERVAL_MS = 1000;
|
||||||
|
|
||||||
private static String roomCode = null;
|
private static String roomCode = null;
|
||||||
private Timer serverListingUpdateTimer;
|
private Timer serverListingUpdateTimer;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package seng302.discoveryServer.util;
|
package seng302.discoveryServer.util;
|
||||||
|
|
||||||
public class ServerListing {
|
public class ServerListing {
|
||||||
public final static int SERVER_TTL_DEFAULT = 10;
|
public final static int SERVER_TTL_DEFAULT = 5;
|
||||||
|
|
||||||
private String serverName = "";
|
private String serverName = "";
|
||||||
private String mapName = "";
|
private String mapName = "";
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ public class GameState implements Runnable {
|
|||||||
if (System.currentTimeMillis() > startTime) {
|
if (System.currentTimeMillis() > startTime) {
|
||||||
startSpawningTokens();
|
startSpawningTokens();
|
||||||
startUpdatingWind();
|
startUpdatingWind();
|
||||||
GameState.setCurrentStage(GameStages.RACING);
|
GameState.currentStage = GameStages.RACING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentStage == GameStages.RACING) {
|
if (currentStage == GameStages.RACING) {
|
||||||
@@ -303,8 +303,8 @@ public class GameState implements Runnable {
|
|||||||
windSpeed += random.nextInt(500);
|
windSpeed += random.nextInt(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameState.setWindSpeed(Double.valueOf(windSpeed));
|
GameState.windSpeed = Double.valueOf(windSpeed);
|
||||||
GameState.setWindDirection(direction.doubleValue());
|
GameState.windDirection = direction.doubleValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.net.ServerSocket;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -19,12 +18,6 @@ import seng302.model.stream.xml.parser.RaceXMLData;
|
|||||||
import seng302.model.stream.xml.parser.RegattaXMLData;
|
import seng302.model.stream.xml.parser.RegattaXMLData;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing the overall server, which creates and collects server threads for each client
|
* A class describing the overall server, which creates and collects server threads for each client
|
||||||
@@ -32,22 +25,32 @@ import java.util.TimerTask;
|
|||||||
*/
|
*/
|
||||||
public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(MainServerThread.class);
|
|
||||||
|
|
||||||
private static final int PORT = 4942;
|
private static final int PORT = 4942;
|
||||||
|
private static int selectedPort = PORT;
|
||||||
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
|
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
|
||||||
|
private Logger logger = LoggerFactory.getLogger(MainServerThread.class);
|
||||||
private boolean terminated;
|
private boolean terminated;
|
||||||
|
|
||||||
private Thread thread;
|
|
||||||
private boolean hasStarted = false;
|
private boolean hasStarted = false;
|
||||||
|
|
||||||
private ServerSocket serverSocket = null;
|
private ServerSocket serverSocket = null;
|
||||||
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
|
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
|
||||||
private static Integer capacity;
|
|
||||||
private RaceXMLData raceXMLData;
|
private RaceXMLData raceXMLData;
|
||||||
private RegattaXMLData regattaXMLData;
|
private RegattaXMLData regattaXMLData;
|
||||||
private boolean serverStarted = false;
|
|
||||||
|
public MainServerThread() {
|
||||||
|
new GameState();
|
||||||
|
try {
|
||||||
|
serverSocket = new ServerSocket(0);
|
||||||
|
selectedPort = serverSocket.getLocalPort();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.trace("IO error in server thread handler upon trying to make new server socket",
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
terminated = false;
|
||||||
|
Thread thread = new Thread(this, "MainServer");
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
private void startAdvertisingServer() {
|
private void startAdvertisingServer() {
|
||||||
Integer capacity = GameState.getCapacity();
|
Integer capacity = GameState.getCapacity();
|
||||||
@@ -65,25 +68,12 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
.setMapName(regattaXMLData.getCourseName())
|
.setMapName(regattaXMLData.getCourseName())
|
||||||
.setCapacity(capacity)
|
.setCapacity(capacity)
|
||||||
.setNumberOfPlayers(numPlayers - 1)
|
.setNumberOfPlayers(numPlayers - 1)
|
||||||
.registerGame(PORT, regattaXMLData.getRegattaName());
|
.registerGame(selectedPort, regattaXMLData.getRegattaName());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.warn("Could not register server");
|
logger.warn("Could not register server");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainServerThread() {
|
|
||||||
new GameState();
|
|
||||||
try {
|
|
||||||
serverSocket = new ServerSocket(PORT);
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.trace("IO error in server thread handler upon trying to make new server socket",
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
terminated = false;
|
|
||||||
thread = new Thread(this, "MainServer");
|
|
||||||
thread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startServer() {
|
private void startServer() {
|
||||||
PolarTable.parsePolarFile(getClass().getResourceAsStream("/server_config/acc_polars.csv"));
|
PolarTable.parsePolarFile(getClass().getResourceAsStream("/server_config/acc_polars.csv"));
|
||||||
MessageFactory.updateXMLGenerator(raceXMLData, regattaXMLData);
|
MessageFactory.updateXMLGenerator(raceXMLData, regattaXMLData);
|
||||||
@@ -122,7 +112,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
logger.trace("Interrupted exception in Main Server Thread thread sleep", 1);
|
logger.trace("Interrupted exception in Main Server Thread thread sleep", 1);
|
||||||
}
|
}
|
||||||
if (GameState.getCurrentStage() == GameStages.LOBBYING && GameState.getCustomizationFlag()) {
|
if (GameState.getCurrentStage() == GameStages.LOBBYING && GameState
|
||||||
|
.getCustomizationFlag()) {
|
||||||
MessageFactory.updateBoats(new ArrayList<>(GameState.getYachts().values()));
|
MessageFactory.updateBoats(new ArrayList<>(GameState.getYachts().values()));
|
||||||
sendSetupMessages();
|
sendSetupMessages();
|
||||||
GameState.resetCustomizationFlag();
|
GameState.resetCustomizationFlag();
|
||||||
@@ -141,7 +132,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
else if (GameState.getCurrentStage() == GameStages.FINISHED) {
|
else if (GameState.getCurrentStage() == GameStages.FINISHED) {
|
||||||
broadcastMessage(MessageFactory.getRaceStatusMessage());
|
broadcastMessage(MessageFactory.getRaceStatusMessage());
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000); //Hackish fix to make sure all threads have sent closing RaceStatus
|
Thread.sleep(
|
||||||
|
1000); //Hackish fix to make sure all threads have sent closing RaceStatus
|
||||||
terminate();
|
terminate();
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
logger.trace("Thread interrupted while waiting to terminate clients", 1);
|
logger.trace("Thread interrupted while waiting to terminate clients", 1);
|
||||||
@@ -205,9 +197,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
startServer();
|
startServer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
//serverToClientThread.addConnectionListener(this::sendSetupMessages);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serverToClientThreads.add(serverToClientThread);
|
serverToClientThreads.add(serverToClientThread);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -255,8 +246,10 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
logger.warn("Couldn't update advertisement");
|
logger.warn("Couldn't update advertisement");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closedConnection != null) {
|
||||||
closedConnection.terminate();
|
closedConnection.terminate();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void startGame() {
|
public void startGame() {
|
||||||
try {
|
try {
|
||||||
@@ -279,10 +272,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
}
|
}
|
||||||
}, 0, 500);
|
}, 0, 500);
|
||||||
|
|
||||||
|
|
||||||
// if (GameState.getCurrentStage() == GameStages.LOBBYING) {
|
|
||||||
// sendSetupMessages();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void terminate() {
|
public void terminate() {
|
||||||
@@ -293,108 +282,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
* Initialise boats to specific spaced out geopoints behind starting line.
|
* Initialise boats to specific spaced out geopoints behind starting line.
|
||||||
*/
|
*/
|
||||||
private void initialiseBoatPositions() {
|
private void initialiseBoatPositions() {
|
||||||
// CompoundMark cm = GameState.getMarkOrder().getMarkOrder().get(0);
|
|
||||||
// GeoPoint startMark1 = cm.getSubMark(1);
|
|
||||||
// GeoPoint startMark2 = cm.getSubMark(2);
|
|
||||||
//
|
|
||||||
// // Calculating midpoint
|
|
||||||
// Double perpendicularAngle = GeoUtility.getBearing(startMark1, startMark2);
|
|
||||||
// Double length = GeoUtility.getDistance(startMark1, startMark2);
|
|
||||||
// GeoPoint midpoint = GeoUtility.getGeoCoordinate(startMark1, perpendicularAngle, length / 2);
|
|
||||||
//
|
|
||||||
// // Setting each boats position side by side
|
|
||||||
// final double SEPARATION = 50.0; // distance apart in meters
|
|
||||||
//
|
|
||||||
// int boatIndex = 0;
|
|
||||||
// for (ServerYacht yacht : GameState.getYachts().values()) {
|
|
||||||
// int distanceApart = boatIndex / 2;
|
|
||||||
//
|
|
||||||
// if (boatIndex % 2 == 1 && boatIndex != 0) {
|
|
||||||
// distanceApart++;
|
|
||||||
// distanceApart *= -1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// GeoPoint spawnMark = GeoUtility
|
|
||||||
// .getGeoCoordinate(midpoint, perpendicularAngle, distanceApart * SEPARATION);
|
|
||||||
//
|
|
||||||
// if (yacht.getHeading() < perpendicularAngle) {
|
|
||||||
// spawnMark = GeoUtility
|
|
||||||
// .getGeoCoordinate(spawnMark, perpendicularAngle + 90, SEPARATION);
|
|
||||||
// } else {
|
|
||||||
// spawnMark = GeoUtility
|
|
||||||
// .getGeoCoordinate(spawnMark, perpendicularAngle + 270, SEPARATION);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// yacht.setLocation(spawnMark);
|
|
||||||
// boatIndex++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// final double SEPARATION = 50.0; // distance apart in meters
|
|
||||||
//
|
|
||||||
// //Reverse of the angle from start to first mark
|
|
||||||
// double angleToFirstMark = 360 - GeoUtility.getBearing(
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getMidPoint(),
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(1).getMidPoint()
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// //Length of start line
|
|
||||||
// double startLineLength = GeoUtility.getDistance(
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1),
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(2)
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// //Angle of start line
|
|
||||||
// double startMarkToMarkAngle = GeoUtility.getBearing(
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1),
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(2)
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// //How many yachts can fit along the start line
|
|
||||||
// int spacesAlongLine = (int) Math.round(startLineLength / SEPARATION);
|
|
||||||
// //The free space left by the boats.
|
|
||||||
// double buffer = (startLineLength % SEPARATION) / 2;
|
|
||||||
//
|
|
||||||
// //Randomize starting order.
|
|
||||||
// List<ServerYacht> serverYachtList = new ArrayList<>(GameState.getYachts().values());
|
|
||||||
// Collections.shuffle(serverYachtList);
|
|
||||||
//
|
|
||||||
// //set the starting point away from start line.
|
|
||||||
// GeoPoint startingPoint = GeoUtility.getGeoCoordinate(
|
|
||||||
// GameState.getMarkOrder().getMarkOrder().get(0).getSubMark(1),
|
|
||||||
// angleToFirstMark, SEPARATION
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// //Move it along the start line
|
|
||||||
// startingPoint = GeoUtility.getGeoCoordinate(
|
|
||||||
// startingPoint, startMarkToMarkAngle, buffer
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// int yachtCount = 0;
|
|
||||||
// int repeats = 0;
|
|
||||||
//
|
|
||||||
// GeoPoint yachtLocation;
|
|
||||||
//
|
|
||||||
// for (ServerYacht serverYacht : serverYachtList) {
|
|
||||||
//
|
|
||||||
// //Move away from start line
|
|
||||||
// yachtLocation = GeoUtility.getGeoCoordinate(
|
|
||||||
// startingPoint, angleToFirstMark,repeats * SEPARATION
|
|
||||||
// );
|
|
||||||
// //Move along start line
|
|
||||||
// yachtLocation = GeoUtility.getGeoCoordinate(
|
|
||||||
// yachtLocation, startMarkToMarkAngle, yachtCount * SEPARATION
|
|
||||||
// );
|
|
||||||
// serverYacht.setLocation(yachtLocation);
|
|
||||||
// serverYacht.setHeading(GeoUtility.getBearing(
|
|
||||||
// yachtLocation, GameState.getMarkOrder().getMarkOrder().get(1).getMidPoint()
|
|
||||||
// ));
|
|
||||||
// //Set location for next yacht
|
|
||||||
// yachtCount++;
|
|
||||||
// if (yachtCount > spacesAlongLine) {
|
|
||||||
// yachtCount = 0;
|
|
||||||
// repeats++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
final double DISTANCE_TO_START = 75d;
|
final double DISTANCE_TO_START = 75d;
|
||||||
final double YACHT_SEPARATION = 20d;
|
final double YACHT_SEPARATION = 20d;
|
||||||
@@ -434,7 +321,9 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
Collections.shuffle(randomisedYachts);
|
Collections.shuffle(randomisedYachts);
|
||||||
while (randomisedYachts.size() > 0) {
|
while (randomisedYachts.size() > 0) {
|
||||||
|
|
||||||
int numYachtsInLine = spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size() : spacesAlongLine;
|
int numYachtsInLine =
|
||||||
|
spacesAlongLine > randomisedYachts.size() ? randomisedYachts.size()
|
||||||
|
: spacesAlongLine;
|
||||||
double yachtSpace = numYachtsInLine * YACHT_SEPARATION / 2;
|
double yachtSpace = numYachtsInLine * YACHT_SEPARATION / 2;
|
||||||
|
|
||||||
GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate(
|
GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate(
|
||||||
@@ -459,4 +348,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
|
|||||||
public boolean hasStarted() {
|
public boolean hasStarted() {
|
||||||
return hasStarted;
|
return hasStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPortNumber() {
|
||||||
|
return selectedPort;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
import seng302.gameServer.messages.*;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import seng302.gameServer.messages.BoatLocationMessage;
|
import seng302.gameServer.messages.BoatLocationMessage;
|
||||||
@@ -25,9 +24,6 @@ import seng302.model.token.Token;
|
|||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.XMLGenerator;
|
import seng302.utilities.XMLGenerator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Class for interfacing between the data we have in the GameState to the messages we need to send
|
* A Class for interfacing between the data we have in the GameState to the messages we need to send
|
||||||
* through the MainServerThread.
|
* through the MainServerThread.
|
||||||
@@ -77,9 +73,6 @@ public class MessageFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBoats(List<ServerYacht> yachts) {
|
public static void updateBoats(List<ServerYacht> yachts) {
|
||||||
// for (ServerYacht serverYacht : yachts) {
|
|
||||||
// System.out.println(serverYacht);
|
|
||||||
// }
|
|
||||||
xmlGenerator.getRace().setBoats(yachts);
|
xmlGenerator.getRace().setBoats(yachts);
|
||||||
String xmlStr = xmlGenerator.getBoatsAsXml();
|
String xmlStr = xmlGenerator.getBoatsAsXml();
|
||||||
MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length());
|
MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length());
|
||||||
|
|||||||
@@ -146,6 +146,8 @@ public class ServerAdvertiser {
|
|||||||
public void unregister(){
|
public void unregister(){
|
||||||
if (serviceInfo != null)
|
if (serviceInfo != null)
|
||||||
jmdnsInstance.unregisterService(serviceInfo);
|
jmdnsInstance.unregisterService(serviceInfo);
|
||||||
|
|
||||||
|
repositoryClient.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,15 +13,11 @@ import javafx.beans.property.ReadOnlyIntegerProperty;
|
|||||||
import javafx.beans.property.ReadOnlyIntegerWrapper;
|
import javafx.beans.property.ReadOnlyIntegerWrapper;
|
||||||
import javafx.beans.property.ReadOnlyLongProperty;
|
import javafx.beans.property.ReadOnlyLongProperty;
|
||||||
import javafx.beans.property.ReadOnlyLongWrapper;
|
import javafx.beans.property.ReadOnlyLongWrapper;
|
||||||
import javafx.beans.value.ObservableObjectValue;
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import jdk.nashorn.internal.objects.annotations.Function;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
import seng302.model.token.TokenType;
|
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -286,6 +282,7 @@ public class ClientYacht extends Observable {
|
|||||||
|
|
||||||
public void setHeading(Double heading) {
|
public void setHeading(Double heading) {
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
|
System.out.println(heading);
|
||||||
setHeadingProperty();
|
setHeadingProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ public class CompoundMark {
|
|||||||
getSubMark(1).setRoundingSide(RoundingSide.STARBOARD);
|
getSubMark(1).setRoundingSide(RoundingSide.STARBOARD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.util.Pair;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import seng302.gameServer.messages.*;
|
|
||||||
import seng302.model.stream.packets.PacketType;
|
|
||||||
import seng302.model.stream.packets.StreamPacket;
|
|
||||||
import seng302.utilities.XMLParser;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@@ -43,7 +34,7 @@ import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
|||||||
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
|
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
|
||||||
import seng302.utilities.XMLGenerator;
|
import seng302.utilities.XMLGenerator;
|
||||||
import seng302.utilities.XMLParser;
|
import seng302.utilities.XMLParser;
|
||||||
import seng302.visualiser.controllers.ViewManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
||||||
@@ -180,10 +171,12 @@ public class ClientToServerThread implements Runnable {
|
|||||||
notifyDisconnectListeners("Connection to server was terminated");
|
notifyDisconnectListeners("Connection to server was terminated");
|
||||||
closeSocket();
|
closeSocket();
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
//thread.interrupt();
|
||||||
ViewManager.getInstance().showErrorSnackBar("Server rejected connection.");
|
|
||||||
ViewManager.getInstance().goToStartView();
|
// Platform.runLater(() -> {
|
||||||
});
|
// ViewManager.getInstance().showErrorSnackBar("Server rejected connection.");
|
||||||
|
// ViewManager.getInstance().goToStartView();
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendCustomizationRequest(CustomizeRequestType reqType, byte[] payload) {
|
public void sendCustomizationRequest(CustomizeRequestType reqType, byte[] payload) {
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
@@ -17,7 +15,6 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.input.KeyEvent;
|
import javafx.scene.input.KeyEvent;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import seng302.gameServer.GameStages;
|
import seng302.gameServer.GameStages;
|
||||||
@@ -49,19 +46,12 @@ import seng302.visualiser.controllers.RaceViewController;
|
|||||||
import seng302.visualiser.controllers.ViewManager;
|
import seng302.visualiser.controllers.ViewManager;
|
||||||
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.time.ZoneId;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
|
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
|
||||||
* with a JavaFX Pane to insert itself into.
|
* with a JavaFX Pane to insert itself into.
|
||||||
*/
|
*/
|
||||||
public class GameClient {
|
public class GameClient {
|
||||||
|
|
||||||
private Pane holderPane;
|
|
||||||
private ClientToServerThread socketThread;
|
private ClientToServerThread socketThread;
|
||||||
private MainServerThread server;
|
private MainServerThread server;
|
||||||
|
|
||||||
@@ -83,10 +73,8 @@ public class GameClient {
|
|||||||
/**
|
/**
|
||||||
* Create an instance of the game client. Does not do anything until run with runAsClient()
|
* Create an instance of the game client. Does not do anything until run with runAsClient()
|
||||||
* runAsHost().
|
* runAsHost().
|
||||||
* @param holder The JavaFX Pane that the visual elements for the race will be inserted into.
|
|
||||||
*/
|
*/
|
||||||
public GameClient(Pane holder) {
|
public GameClient() {
|
||||||
this.holderPane = holder;
|
|
||||||
this.gameKeyBind = GameKeyBind.getInstance();
|
this.gameKeyBind = GameKeyBind.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +83,7 @@ public class GameClient {
|
|||||||
* @param ipAddress IP to connect to.
|
* @param ipAddress IP to connect to.
|
||||||
* @param portNumber Port to connect to.
|
* @param portNumber Port to connect to.
|
||||||
*/
|
*/
|
||||||
public void runAsClient(String ipAddress, Integer portNumber) {
|
public boolean runAsClient(String ipAddress, Integer portNumber) {
|
||||||
try {
|
try {
|
||||||
startClientToServerThread(ipAddress, portNumber);
|
startClientToServerThread(ipAddress, portNumber);
|
||||||
socketThread.addDisconnectionListener((cause) -> {
|
socketThread.addDisconnectionListener((cause) -> {
|
||||||
@@ -106,41 +94,40 @@ public class GameClient {
|
|||||||
|
|
||||||
ViewManager.getInstance().setPlayerList(clientLobbyList);
|
ViewManager.getInstance().setPlayerList(clientLobbyList);
|
||||||
|
|
||||||
while (regattaData == null){
|
int triesLeft = 10;
|
||||||
|
|
||||||
|
while (regattaData == null && triesLeft >= 0){
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException ignored) {
|
||||||
e.printStackTrace();
|
;
|
||||||
}
|
}
|
||||||
|
triesLeft--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triesLeft < 1){
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName());
|
ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName());
|
||||||
ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName());
|
ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName());
|
||||||
|
|
||||||
getServerThread().setConnectionErrorListener((eMessage) -> {
|
getServerThread().setConnectionErrorListener((eMessage) -> ViewManager.getInstance().showErrorSnackBar(eMessage));
|
||||||
ViewManager.getInstance().showErrorSnackBar(eMessage);
|
|
||||||
//destroyClientToServerThread();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.lobbyController = ViewManager.getInstance().goToLobby(true);
|
this.lobbyController = ViewManager.getInstance().goToLobby(true);
|
||||||
|
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
ViewManager.getInstance().showErrorSnackBar("There are no servers currently available.");
|
ViewManager.getInstance().showErrorSnackBar("There are no servers currently available.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void destroyClientToServerThread() {
|
return true;
|
||||||
socketThread.closeSocket();
|
|
||||||
socketThread = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a game as the host at the given address and starts the visualiser.
|
* Connect to a game as the host at the given address and starts the visualiser.
|
||||||
* @param ipAddress IP to connect to.
|
|
||||||
* @param portNumber Port to connect to.
|
|
||||||
*/
|
*/
|
||||||
public ServerDescription runAsHost(
|
public ServerDescription runAsHost(
|
||||||
String ipAddress, Integer portNumber, String serverName, Integer maxPlayers, String race,
|
String serverName, Integer maxPlayers, String race,
|
||||||
Integer numLegs, Boolean tokensEnabled
|
Integer numLegs, Boolean tokensEnabled
|
||||||
) {
|
) {
|
||||||
XMLGenerator.setDefaultRaceName(serverName);
|
XMLGenerator.setDefaultRaceName(serverName);
|
||||||
@@ -156,7 +143,7 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
startClientToServerThread(ipAddress, 4942);
|
startClientToServerThread("localhost", server.getPortNumber());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
showConnectionError("Cannot connect to server as host");
|
showConnectionError("Cannot connect to server as host");
|
||||||
}
|
}
|
||||||
@@ -190,8 +177,11 @@ public class GameClient {
|
|||||||
|
|
||||||
this.lobbyController = ViewManager.getInstance().goToLobby(false);
|
this.lobbyController = ViewManager.getInstance().goToLobby(false);
|
||||||
|
|
||||||
|
lobbyController.setPortNumber(""+server.getPortNumber());
|
||||||
|
|
||||||
ViewManager.getInstance().setPlayerList(clientLobbyList);
|
ViewManager.getInstance().setPlayerList(clientLobbyList);
|
||||||
return new ServerDescription(serverName, regattaData.getCourseName(), GameState.getNumberOfPlayers(), GameState.getCapacity(), ipAddress, 4942);
|
return new ServerDescription(serverName, regattaData.getCourseName(), GameState.getNumberOfPlayers(), GameState.getCapacity(),
|
||||||
|
"localhost", server.getPortNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tearDownConnection() {
|
private void tearDownConnection() {
|
||||||
@@ -294,6 +284,7 @@ public class GameClient {
|
|||||||
case CHATTER_TEXT:
|
case CHATTER_TEXT:
|
||||||
Pair<Integer, String> playerIdMessagePair = StreamParser
|
Pair<Integer, String> playerIdMessagePair = StreamParser
|
||||||
.extractChatterText(packet);
|
.extractChatterText(packet);
|
||||||
|
if (playerIdMessagePair != null) {
|
||||||
raceView.updateChatHistory(
|
raceView.updateChatHistory(
|
||||||
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
|
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
|
||||||
playerIdMessagePair.getValue()
|
playerIdMessagePair.getValue()
|
||||||
@@ -301,6 +292,7 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void startRaceIfAllDataReceived() {
|
private void startRaceIfAllDataReceived() {
|
||||||
if (allXMLReceived() && raceView == null) {
|
if (allXMLReceived() && raceView == null) {
|
||||||
@@ -314,6 +306,7 @@ public class GameClient {
|
|||||||
formatAndSendChatMessage(raceView.readChatInput());
|
formatAndSendChatMessage(raceView.readChatInput());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
gameKeyBind.toggleTurningMode();
|
||||||
sendToggleTurningModePacket(); // notify the server about player's steering mode
|
sendToggleTurningModePacket(); // notify the server about player's steering mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,8 +326,6 @@ public class GameClient {
|
|||||||
positionData.getLon(), positionData.getHeading(),
|
positionData.getLon(), positionData.getHeading(),
|
||||||
positionData.getGroundSpeed());
|
positionData.getGroundSpeed());
|
||||||
}
|
}
|
||||||
} else if (positionData.getType() == DeviceType.MARK_TYPE) {
|
|
||||||
//CompoundMark mark = courseData.getCompoundMarks().get(positionData.getDeviceId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,21 +363,17 @@ public class GameClient {
|
|||||||
ClientYacht clientYacht = allBoatsMap.get((int) boatData[0]);
|
ClientYacht clientYacht = allBoatsMap.get((int) boatData[0]);
|
||||||
clientYacht.setEstimateTimeTillNextMark(raceState.getRaceTime() - boatData[1]);
|
clientYacht.setEstimateTimeTillNextMark(raceState.getRaceTime() - boatData[1]);
|
||||||
clientYacht.setEstimateTimeAtFinish(boatData[2]);
|
clientYacht.setEstimateTimeAtFinish(boatData[2]);
|
||||||
// int legNumber = (int) boatData[3];
|
|
||||||
clientYacht.setBoatStatus((int) boatData[4]);
|
clientYacht.setBoatStatus((int) boatData[4]);
|
||||||
// if (legNumber != clientYacht.getLegNumber()) {
|
|
||||||
// clientYacht.setLegNumber(legNumber);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raceFinished) {
|
if (raceFinished && !raceState.getRaceFinished()) {
|
||||||
raceViewController.showFinishDialog(finishedBoats);
|
raceState.setRaceFinished();
|
||||||
Sounds.playFinishSound();
|
Sounds.playFinishSound();
|
||||||
close();
|
raceViewController.showFinishDialog(finishedBoats);
|
||||||
ViewManager.getInstance().getGameClient().stopGame();
|
// close();
|
||||||
|
// ViewManager.getInstance().getGameClient().stopGame();
|
||||||
//loadFinishScreenView();
|
//loadFinishScreenView();
|
||||||
}
|
}
|
||||||
raceState.setRaceFinished();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,10 +384,6 @@ public class GameClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close() {
|
|
||||||
socketThread.setSocketToClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle the key-pressed event from the text field.
|
* Handle the key-pressed event from the text field.
|
||||||
* @param e The key event triggering this call
|
* @param e The key event triggering this call
|
||||||
@@ -527,10 +510,6 @@ public class GameClient {
|
|||||||
return socketThread;
|
return socketThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getPlayerNames(){
|
|
||||||
return Collections.unmodifiableList(clientLobbyList.sorted());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopGame() {
|
public void stopGame() {
|
||||||
GameState.setCurrentStage(GameStages.CANCELLED);
|
GameState.setCurrentStage(GameStages.CANCELLED);
|
||||||
if (server != null) server.terminate();
|
if (server != null) server.terminate();
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
|
import seng302.model.ClientYacht;
|
||||||
import seng302.model.Limit;
|
import seng302.model.Limit;
|
||||||
import seng302.model.ScaledPoint;
|
import seng302.model.ScaledPoint;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Corner;
|
import seng302.model.mark.Corner;
|
||||||
|
import seng302.model.mark.Mark;
|
||||||
|
import seng302.utilities.Sounds;
|
||||||
|
import seng302.visualiser.fxObjects.Marker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for keeping functionality common between race visualisation.
|
* Abstract class for keeping functionality common between race visualisation.
|
||||||
@@ -24,8 +29,36 @@ public abstract class GameView {
|
|||||||
List<CompoundMark> course = new ArrayList<>();
|
List<CompoundMark> course = new ArrayList<>();
|
||||||
List<CompoundMark> compoundMarks = new ArrayList<>();
|
List<CompoundMark> compoundMarks = new ArrayList<>();
|
||||||
List<Corner> courseOrder = new ArrayList<>();
|
List<Corner> courseOrder = new ArrayList<>();
|
||||||
|
HashMap<Mark, Marker> markerObjects = new HashMap<>();
|
||||||
|
|
||||||
public abstract Node getAssets();
|
public abstract Node getAssets();
|
||||||
public abstract void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence);
|
public abstract void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence);
|
||||||
public abstract void updateBorder(List<Limit> border);
|
public abstract void updateBorder(List<Limit> border);
|
||||||
|
|
||||||
|
void updateMarkArrows (ClientYacht yacht, int legNumber) {
|
||||||
|
CompoundMark compoundMark;
|
||||||
|
if (legNumber - 1 >= 0 && legNumber-1 < course.size()) {
|
||||||
|
Sounds.playMarkRoundingSound();
|
||||||
|
compoundMark = course.get(legNumber-1);
|
||||||
|
for (Mark mark : compoundMark.getMarks()) {
|
||||||
|
markerObjects.get(mark).showNextExitArrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CompoundMark nextMark = null;
|
||||||
|
if (legNumber < course.size()) {
|
||||||
|
Sounds.playMarkRoundingSound();
|
||||||
|
nextMark = course.get(legNumber);
|
||||||
|
for (Mark mark : nextMark.getMarks()) {
|
||||||
|
markerObjects.get(mark).showNextEnterArrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (legNumber - 2 >= 0) {
|
||||||
|
CompoundMark lastMark = course.get(Math.max(0, legNumber - 2));
|
||||||
|
if (lastMark != nextMark) {
|
||||||
|
for (Mark mark : lastMark.getMarks()) {
|
||||||
|
markerObjects.get(mark).hideAllArrows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import seng302.model.mark.Corner;
|
|||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.model.token.Token;
|
import seng302.model.token.Token;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
import seng302.utilities.Sounds;
|
|
||||||
import seng302.visualiser.cameras.ChaseCamera;
|
import seng302.visualiser.cameras.ChaseCamera;
|
||||||
import seng302.visualiser.cameras.IsometricCamera;
|
import seng302.visualiser.cameras.IsometricCamera;
|
||||||
import seng302.visualiser.cameras.RaceCamera;
|
import seng302.visualiser.cameras.RaceCamera;
|
||||||
@@ -55,7 +54,7 @@ public class GameView3D extends GameView{
|
|||||||
|
|
||||||
private final double FOV = 60;
|
private final double FOV = 60;
|
||||||
private final double DEFAULT_CAMERA_X = 0;
|
private final double DEFAULT_CAMERA_X = 0;
|
||||||
private final double DEFAULT_CAMERA_Y = 100;
|
private final double DEFAULT_CAMERA_Y = 160;
|
||||||
|
|
||||||
private Group root3D;
|
private Group root3D;
|
||||||
private SubScene view;
|
private SubScene view;
|
||||||
@@ -66,11 +65,6 @@ public class GameView3D extends GameView{
|
|||||||
private PerspectiveCamera isometricCam;
|
private PerspectiveCamera isometricCam;
|
||||||
private PerspectiveCamera topDownCam;
|
private PerspectiveCamera topDownCam;
|
||||||
private PerspectiveCamera chaseCam;
|
private PerspectiveCamera chaseCam;
|
||||||
|
|
||||||
/* Note that if either of these is null then values for it have not been added and the other
|
|
||||||
should be used as the limits of the map. */
|
|
||||||
private Map<Mark, Marker3D> markerObjects;
|
|
||||||
|
|
||||||
private BoatObject playerBoat;
|
private BoatObject playerBoat;
|
||||||
private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
|
private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
|
||||||
private Group wakesGroup = new Group();
|
private Group wakesGroup = new Group();
|
||||||
@@ -96,11 +90,11 @@ public class GameView3D extends GameView{
|
|||||||
}
|
}
|
||||||
|
|
||||||
gameObjects = new Group();
|
gameObjects = new Group();
|
||||||
root3D = new Group(isometricCam, gameObjects);
|
root3D = new Group(chaseCam, gameObjects);
|
||||||
view = new SubScene(
|
view = new SubScene(
|
||||||
root3D, 5000, 3000, true, SceneAntialiasing.BALANCED
|
root3D, 5000, 3000, true, SceneAntialiasing.BALANCED
|
||||||
);
|
);
|
||||||
view.setCamera(isometricCam);
|
view.setCamera(chaseCam);
|
||||||
|
|
||||||
skybox = new Skybox(new Image(getClass().getResourceAsStream("/images/skybox.jpg")), 100000, isometricCam);
|
skybox = new Skybox(new Image(getClass().getResourceAsStream("/images/skybox.jpg")), 100000, isometricCam);
|
||||||
skybox.getTransforms().addAll(new Rotate(90, Rotate.X_AXIS));
|
skybox.getTransforms().addAll(new Rotate(90, Rotate.X_AXIS));
|
||||||
@@ -351,7 +345,7 @@ public class GameView3D extends GameView{
|
|||||||
for (ObservableValue o : Arrays
|
for (ObservableValue o : Arrays
|
||||||
.asList(playerBoat.layoutXProperty(), playerBoat.layoutXProperty())) {
|
.asList(playerBoat.layoutXProperty(), playerBoat.layoutXProperty())) {
|
||||||
o.addListener((obs, oldVal, newVal) -> {
|
o.addListener((obs, oldVal, newVal) -> {
|
||||||
|
if (playerYacht.getLegNumber() < course.size()) {
|
||||||
List<Mark> marks = course.get(playerYacht.getLegNumber()).getMarks();
|
List<Mark> marks = course.get(playerYacht.getLegNumber()).getMarks();
|
||||||
Point2D midPoint = new Point2D(0, 0);
|
Point2D midPoint = new Point2D(0, 0);
|
||||||
if (marks.size() == 1) {
|
if (marks.size() == 1) {
|
||||||
@@ -364,6 +358,7 @@ public class GameView3D extends GameView{
|
|||||||
if (midPoint != null) {
|
if (midPoint != null) {
|
||||||
playerBoat.updateMarkIndicator(midPoint);
|
playerBoat.updateMarkIndicator(midPoint);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -506,6 +501,7 @@ public class GameView3D extends GameView{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setBoatAsPlayer (ClientYacht playerYacht) {
|
public void setBoatAsPlayer (ClientYacht playerYacht) {
|
||||||
|
playerBoat.updateMarkIndicator(scaledPoint.findScaledXY(course.get(0).getMidPoint()));
|
||||||
playerYacht.toggleSail();
|
playerYacht.toggleSail();
|
||||||
playerBoatAnimationTimer = new AnimationTimer() {
|
playerBoatAnimationTimer = new AnimationTimer() {
|
||||||
|
|
||||||
@@ -539,31 +535,4 @@ public class GameView3D extends GameView{
|
|||||||
public void setWindDir(double windDir) {
|
public void setWindDir(double windDir) {
|
||||||
this.windDir = windDir;
|
this.windDir = windDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateMarkArrows (ClientYacht yacht, int legNumber) {
|
|
||||||
CompoundMark compoundMark;
|
|
||||||
if (legNumber - 1 >= 0) {
|
|
||||||
Sounds.playMarkRoundingSound();
|
|
||||||
compoundMark = course.get(legNumber-1);
|
|
||||||
for (Mark mark : compoundMark.getMarks()) {
|
|
||||||
markerObjects.get(mark).showNextExitArrow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CompoundMark nextMark = null;
|
|
||||||
if (legNumber < course.size() - 1) {
|
|
||||||
Sounds.playMarkRoundingSound();
|
|
||||||
nextMark = course.get(legNumber);
|
|
||||||
for (Mark mark : nextMark.getMarks()) {
|
|
||||||
markerObjects.get(mark).showNextEnterArrow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (legNumber - 2 >= 0) {
|
|
||||||
CompoundMark lastMark = course.get(Math.max(0, legNumber - 2));
|
|
||||||
if (lastMark != nextMark) {
|
|
||||||
for (Mark mark : lastMark.getMarks()) {
|
|
||||||
markerObjects.get(mark).hideAllArrows();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -35,7 +34,8 @@ public class MapMaker {
|
|||||||
private int index = 0;
|
private int index = 0;
|
||||||
private XMLGenerator xmlGenerator = new XMLGenerator();
|
private XMLGenerator xmlGenerator = new XMLGenerator();
|
||||||
|
|
||||||
private List<String> maps = new ArrayList<>(Arrays.asList("default.xml", "horseshoe.xml", "loop.xml"));
|
private List<String> maps = new ArrayList<>(
|
||||||
|
Arrays.asList("default.xml", "horseshoe.xml", "loop.xml", "madagascar.xml", "waiheke.xml"));
|
||||||
|
|
||||||
public static MapMaker getInstance() {
|
public static MapMaker getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
@@ -108,10 +108,6 @@ public class MapMaker {
|
|||||||
return mapPreviews.get(index).getAssets();
|
return mapPreviews.get(index).getAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RaceXMLData getCurrentRace() {
|
|
||||||
return races.get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegattaXMLData getCurrentRegatta() {
|
public RegattaXMLData getCurrentRegatta() {
|
||||||
return regattas.get(index);
|
return regattas.get(index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package seng302.visualiser;
|
|||||||
import java.util.ArrayList;
|
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 javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
@@ -19,6 +18,7 @@ import seng302.model.mark.Corner;
|
|||||||
import seng302.model.mark.Mark;
|
import seng302.model.mark.Mark;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||||
|
import seng302.visualiser.fxObjects.Marker;
|
||||||
import seng302.visualiser.fxObjects.assets_2D.CourseBoundary;
|
import seng302.visualiser.fxObjects.assets_2D.CourseBoundary;
|
||||||
import seng302.visualiser.fxObjects.assets_2D.Gate;
|
import seng302.visualiser.fxObjects.assets_2D.Gate;
|
||||||
import seng302.visualiser.fxObjects.assets_2D.Marker2D;
|
import seng302.visualiser.fxObjects.assets_2D.Marker2D;
|
||||||
@@ -29,7 +29,6 @@ import seng302.visualiser.fxObjects.assets_2D.Marker2D;
|
|||||||
public class MapPreview extends GameView {
|
public class MapPreview extends GameView {
|
||||||
|
|
||||||
private Polygon raceBorder = new CourseBoundary();
|
private Polygon raceBorder = new CourseBoundary();
|
||||||
private Map<Mark, Marker2D> markerObjects;
|
|
||||||
|
|
||||||
public MapPreview(List<CompoundMark> marks, List<Corner> course, List<Limit> border) {
|
public MapPreview(List<CompoundMark> marks, List<Corner> course, List<Limit> border) {
|
||||||
this.compoundMarks = marks;
|
this.compoundMarks = marks;
|
||||||
@@ -240,7 +239,7 @@ public class MapPreview extends GameView {
|
|||||||
* @param colour The desired colour of the gate.
|
* @param colour The desired colour of the gate.
|
||||||
* @return the new gate.
|
* @return the new gate.
|
||||||
*/
|
*/
|
||||||
private Gate makeAndBindGate(Marker2D m1, Marker2D m2, Paint colour) {
|
private Gate makeAndBindGate(Marker m1, Marker m2, Paint colour) {
|
||||||
Gate gate = new Gate(colour);
|
Gate gate = new Gate(colour);
|
||||||
gate.startXProperty().bind(
|
gate.startXProperty().bind(
|
||||||
m1.layoutXProperty()
|
m1.layoutXProperty()
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package seng302.visualiser;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.geometry.Point2D;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Polygon;
|
||||||
|
import javafx.scene.transform.Rotate;
|
||||||
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.Limit;
|
||||||
|
import seng302.model.mark.CompoundMark;
|
||||||
|
import seng302.model.mark.Corner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class converts a map preview to a minimap by adding boats.
|
||||||
|
*/
|
||||||
|
public class MiniMap extends MapPreview {
|
||||||
|
|
||||||
|
private HashMap<ClientYacht, Polygon> boatIcons = new HashMap<>();
|
||||||
|
|
||||||
|
public MiniMap (List<CompoundMark> marks, List<Corner> course, List<Limit> border, List<ClientYacht> boats, ClientYacht player) {
|
||||||
|
super(marks, course, border);
|
||||||
|
setBoats(boats);
|
||||||
|
player.addMarkRoundingListener(this::updateMarkArrows);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBoats(List<ClientYacht> yachts) {
|
||||||
|
for (ClientYacht yacht : yachts) {
|
||||||
|
Polygon boatIcon = new Polygon(0, -3.5, 3.5, 3.5, -3.5, 3.5);
|
||||||
|
boatIcon.setStroke(Color.BLACK);
|
||||||
|
boatIcon.setFill(Color.GRAY);
|
||||||
|
boatIcon.setFill(yacht.getColour());
|
||||||
|
boatIcon.setFill(yacht.getColour());
|
||||||
|
boatIcons.put(yacht, boatIcon);
|
||||||
|
boatIcon.getTransforms().add(new Rotate(0));
|
||||||
|
yacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Polygon bi = boatIcons.get(boat);
|
||||||
|
Point2D p2d = scaledPoint.findScaledXY(lat, lon);
|
||||||
|
bi.setLayoutX(p2d.getX());
|
||||||
|
bi.setLayoutY(p2d.getY());
|
||||||
|
((Rotate) bi.getTransforms().get(0)).setAngle(heading);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
gameObjects.getChildren().addAll(boatIcons.values());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import seng302.gameServer.ServerAdvertiser;
|
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
||||||
import seng302.gameServer.ServerDescription;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import javax.jmdns.JmDNS;
|
import javax.jmdns.JmDNS;
|
||||||
import javax.jmdns.ServiceEvent;
|
import javax.jmdns.ServiceEvent;
|
||||||
import javax.jmdns.ServiceListener;
|
import javax.jmdns.ServiceListener;
|
||||||
import javax.jmdns.impl.JmDNSImpl;
|
import seng302.gameServer.ServerAdvertiser;
|
||||||
import java.io.IOException;
|
import seng302.gameServer.ServerDescription;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for servers on the local network
|
* Listens for servers on the local network
|
||||||
@@ -58,7 +58,7 @@ public class ServerListener{
|
|||||||
servers.remove(toRemove);
|
servers.remove(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate.serverRemoved(new ArrayList<ServerDescription>(servers));
|
delegate.serverRemoved(new ArrayList<>(servers));
|
||||||
|
|
||||||
// Get all other servers with the same name to respond if they are up
|
// Get all other servers with the same name to respond if they are up
|
||||||
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverName);
|
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverName);
|
||||||
@@ -94,13 +94,6 @@ public class ServerListener{
|
|||||||
|
|
||||||
listener = new GameServeMonitor();
|
listener = new GameServeMonitor();
|
||||||
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
jmdns.addServiceListener(ServerAdvertiser.SERVICE_TYPE, listener);
|
||||||
|
|
||||||
/*new Timer().schedule(new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
}, 50, SERVICE_REFRESH_INTERVAL);*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ServerListener getInstance() throws IOException {
|
public static ServerListener getInstance() throws IOException {
|
||||||
@@ -134,7 +127,7 @@ public class ServerListener{
|
|||||||
for (ServerDescription server : servers){
|
for (ServerDescription server : servers){
|
||||||
if (server.serverShouldBeRemoved()){
|
if (server.serverShouldBeRemoved()){
|
||||||
listener.servers.remove(server);
|
listener.servers.remove(server);
|
||||||
delegate.serverRemoved(new ArrayList<ServerDescription>(listener.servers));
|
delegate.serverRemoved(new ArrayList<>(listener.servers));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
|
|||||||
private final Double MAX_Y = 170.0;
|
private final Double MAX_Y = 170.0;
|
||||||
|
|
||||||
private final Double PAN_LIMIT = 160.0;
|
private final Double PAN_LIMIT = 160.0;
|
||||||
private final Double NEAR_ZOOM_LIMIT = -50.0;
|
private final Double NEAR_ZOOM_LIMIT = -30.0;
|
||||||
private final Double FAR_ZOOM_LIMIT = -160.0;
|
private final Double FAR_ZOOM_LIMIT = -180.0;
|
||||||
|
|
||||||
private Double horizontalPan;
|
private Double horizontalPan;
|
||||||
private Double verticalPan;
|
private Double verticalPan;
|
||||||
@@ -29,7 +29,7 @@ public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
|
|||||||
super(true);
|
super(true);
|
||||||
transforms = this.getTransforms();
|
transforms = this.getTransforms();
|
||||||
|
|
||||||
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
zoomFactor = FAR_ZOOM_LIMIT;
|
||||||
horizontalPan = cameraStartX;
|
horizontalPan = cameraStartX;
|
||||||
verticalPan = cameraStartY;
|
verticalPan = cameraStartY;
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
|||||||
|
|
||||||
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
||||||
|
|
||||||
private final Double PAN_LIMIT = 30.0;
|
private final Double PAN_LIMIT = 40d;
|
||||||
private final Double NEAR_ZOOM_LIMIT = -30.0;
|
private final Double NEAR_ZOOM_LIMIT = -20.0;
|
||||||
private final Double FAR_ZOOM_LIMIT = -130.0;
|
private final Double FAR_ZOOM_LIMIT = -200d;
|
||||||
private final Double ZOOM_STEP = 2.5;
|
private final Double ZOOM_STEP = 2.5;
|
||||||
|
|
||||||
private ObservableList<Transform> transforms;
|
private ObservableList<Transform> transforms;
|
||||||
@@ -27,7 +27,7 @@ public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
|||||||
super(true);
|
super(true);
|
||||||
transforms = this.getTransforms();
|
transforms = this.getTransforms();
|
||||||
|
|
||||||
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
zoomFactor = FAR_ZOOM_LIMIT;
|
||||||
horizontalPan = 0.0;
|
horizontalPan = 0.0;
|
||||||
verticalPan = 0.0;
|
verticalPan = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
package seng302.visualiser.controllers;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.fxml.FXMLLoader;
|
|
||||||
import javafx.fxml.Initializable;
|
|
||||||
import javafx.scene.control.TableColumn;
|
|
||||||
import javafx.scene.control.TableView;
|
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
|
||||||
import javafx.scene.input.MouseEvent;
|
|
||||||
import javafx.scene.layout.AnchorPane;
|
|
||||||
import javafx.scene.layout.GridPane;
|
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import seng302.model.ClientYacht;
|
|
||||||
import seng302.utilities.Sounds;
|
|
||||||
|
|
||||||
public class FinishScreenViewController implements Initializable {
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private GridPane finishScreenGridPane;
|
|
||||||
@FXML
|
|
||||||
private TableView<ClientYacht> finishOrderTable;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<ClientYacht, String> posCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<ClientYacht, String> boatNameCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<ClientYacht, String> shortNameCol;
|
|
||||||
@FXML
|
|
||||||
private TableColumn<ClientYacht, String> countryCol;
|
|
||||||
|
|
||||||
ObservableList<ClientYacht> data = FXCollections.observableArrayList();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
|
||||||
finishScreenGridPane.getStylesheets()
|
|
||||||
.add(getClass().getResource("/css/Master.css").toString());
|
|
||||||
finishOrderTable.getStylesheets().add(getClass().getResource("/css/Master.css").toString());
|
|
||||||
|
|
||||||
// set up data for table
|
|
||||||
finishOrderTable.setItems(data);
|
|
||||||
|
|
||||||
// setting table col data
|
|
||||||
posCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("position")
|
|
||||||
);
|
|
||||||
boatNameCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("boatName")
|
|
||||||
);
|
|
||||||
shortNameCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("shortName")
|
|
||||||
);
|
|
||||||
countryCol.setCellValueFactory(
|
|
||||||
new PropertyValueFactory<>("country")
|
|
||||||
);
|
|
||||||
finishOrderTable.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFinishers(Collection<ClientYacht> participants) {
|
|
||||||
List<ClientYacht> sorted = new ArrayList<>(participants);
|
|
||||||
sorted.sort(Comparator.comparingInt(ClientYacht::getPlacing));
|
|
||||||
finishOrderTable.getItems().setAll(sorted);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setContentPane(String jfxUrl) {
|
|
||||||
try {
|
|
||||||
// get the main controller anchor pane (FinishView -> MainView)
|
|
||||||
AnchorPane contentPane = (AnchorPane) finishScreenGridPane.getParent();
|
|
||||||
contentPane.getChildren().removeAll();
|
|
||||||
contentPane.getChildren().clear();
|
|
||||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
|
||||||
contentPane.getChildren()
|
|
||||||
.addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
|
|
||||||
} catch (javafx.fxml.LoadException e) {
|
|
||||||
System.out.println("[Controller] FXML load exception");
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("[Controller] IO exception");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void switchToStartScreenView() {
|
|
||||||
Sounds.playButtonClick();
|
|
||||||
setContentPane("/views/StartScreenView.fxml");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void playButtonHoverSound(MouseEvent mouseEvent) {
|
|
||||||
Sounds.playHoverSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -71,6 +71,8 @@ public class LobbyController implements Initializable {
|
|||||||
@FXML
|
@FXML
|
||||||
private Label roomLabel;
|
private Label roomLabel;
|
||||||
@FXML
|
@FXML
|
||||||
|
private Label portNumber;
|
||||||
|
@FXML
|
||||||
private Pane speedTokenPane, handlingTokenPane, windWalkerTokenPane, bumperTokenPane, randomTokenPane;
|
private Pane speedTokenPane, handlingTokenPane, windWalkerTokenPane, bumperTokenPane, randomTokenPane;
|
||||||
//---------FXML END---------//
|
//---------FXML END---------//
|
||||||
|
|
||||||
@@ -85,6 +87,8 @@ public class LobbyController implements Initializable {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
roomLabel.setText("");
|
roomLabel.setText("");
|
||||||
|
portNumber.setText("");
|
||||||
|
|
||||||
this.playerBoats = ViewManager.getInstance().getGameClient().getAllBoatsMap();
|
this.playerBoats = ViewManager.getInstance().getGameClient().getAllBoatsMap();
|
||||||
|
|
||||||
if (this.playersColor == null) {
|
if (this.playersColor == null) {
|
||||||
@@ -376,4 +380,8 @@ public class LobbyController implements Initializable {
|
|||||||
public void setRoomCode(String roomCode) {
|
public void setRoomCode(String roomCode) {
|
||||||
roomLabel.setText("Room: " + roomCode);
|
roomLabel.setText("Room: " + roomCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPortNumber(String p){
|
||||||
|
portNumber.setText("Port: " + p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,49 +4,33 @@ import com.jfoenix.controls.JFXButton;
|
|||||||
import com.jfoenix.controls.JFXDialog;
|
import com.jfoenix.controls.JFXDialog;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
|
import javafx.animation.RotateTransition;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||||
import javafx.collections.FXCollections;
|
|
||||||
import javafx.collections.ListChangeListener;
|
|
||||||
import javafx.collections.ObservableList;
|
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import javafx.scene.Scene;
|
|
||||||
import javafx.scene.SubScene;
|
import javafx.scene.SubScene;
|
||||||
import javafx.scene.chart.LineChart;
|
|
||||||
import javafx.scene.chart.NumberAxis;
|
|
||||||
import javafx.scene.chart.XYChart.Series;
|
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import javafx.scene.control.CheckBox;
|
|
||||||
import javafx.scene.control.ComboBox;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.Slider;
|
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.scene.layout.VBox;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
import javafx.scene.shape.Line;
|
import javafx.scene.shape.Line;
|
||||||
import javafx.scene.shape.Polyline;
|
import javafx.scene.shape.Polyline;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.stage.StageStyle;
|
import javafx.stage.StageStyle;
|
||||||
|
import javafx.util.Duration;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
import seng302.model.RaceState;
|
import seng302.model.RaceState;
|
||||||
import seng302.model.mark.CompoundMark;
|
|
||||||
import seng302.model.mark.Mark;
|
|
||||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||||
import seng302.model.token.TokenType;
|
import seng302.model.token.TokenType;
|
||||||
import seng302.utilities.Sounds;
|
import seng302.utilities.Sounds;
|
||||||
@@ -55,15 +39,14 @@ import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
|||||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
|
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
|
||||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
|
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
|
||||||
import seng302.visualiser.controllers.cells.WindCell;
|
import seng302.visualiser.controllers.cells.WindCell;
|
||||||
|
import seng302.visualiser.MiniMap;
|
||||||
import seng302.visualiser.controllers.dialogs.FinishDialogController;
|
import seng302.visualiser.controllers.dialogs.FinishDialogController;
|
||||||
import seng302.visualiser.fxObjects.ChatHistory;
|
import seng302.visualiser.fxObjects.ChatHistory;
|
||||||
import seng302.visualiser.fxObjects.assets_2D.WindArrow;
|
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller class that manages the display of a race
|
* Controller class that manages the display of a race
|
||||||
*/
|
*/
|
||||||
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
|
public class RaceViewController extends Thread {
|
||||||
|
|
||||||
private final int CHAT_LIMIT = 128;
|
private final int CHAT_LIMIT = 128;
|
||||||
private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6;
|
private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6;
|
||||||
@@ -74,27 +57,19 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private ImageView loadingScreen;
|
private ImageView loadingScreen;
|
||||||
@FXML
|
@FXML
|
||||||
private Pane basePane;
|
|
||||||
@FXML
|
|
||||||
private JFXButton chatSend;
|
private JFXButton chatSend;
|
||||||
@FXML
|
@FXML
|
||||||
private Pane chatHistoryHolder;
|
private Pane chatHistoryHolder;
|
||||||
@FXML
|
@FXML
|
||||||
private TextField chatInput;
|
private TextField chatInput;
|
||||||
@FXML
|
@FXML
|
||||||
private LineChart<String, Double> raceSparkLine;
|
|
||||||
@FXML
|
|
||||||
private NumberAxis sparklineYAxis;
|
|
||||||
@FXML
|
|
||||||
private VBox positionVbox;
|
|
||||||
@FXML
|
|
||||||
private CheckBox toggleFps;
|
|
||||||
@FXML
|
|
||||||
private Label timerLabel;
|
private Label timerLabel;
|
||||||
@FXML
|
@FXML
|
||||||
private StackPane contentStackPane;
|
private StackPane contentStackPane;
|
||||||
|
@FXML
|
||||||
private GridPane contentGridPane;
|
private Pane miniMapPane;
|
||||||
|
@FXML
|
||||||
|
private ImageView windImageView;
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane rvAnchorPane;
|
private AnchorPane rvAnchorPane;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -119,6 +94,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
|
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
|
||||||
@FXML
|
@FXML
|
||||||
private VBox windArrowVBox;
|
private VBox windArrowVBox;
|
||||||
|
@FXML
|
||||||
|
private JFXButton miniMapButton;
|
||||||
|
|
||||||
|
|
||||||
private WindCell windCell;
|
private WindCell windCell;
|
||||||
@@ -128,26 +105,19 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
private RaceXMLData courseData;
|
private RaceXMLData courseData;
|
||||||
private GameView3D gameView;
|
private GameView3D gameView;
|
||||||
private RaceState raceState;
|
private RaceState raceState;
|
||||||
|
|
||||||
private ChatHistory chatHistory;
|
private ChatHistory chatHistory;
|
||||||
|
|
||||||
private Timeline timerTimeline;
|
|
||||||
private Timer timer = new Timer();
|
private Timer timer = new Timer();
|
||||||
private List<Series<String, Double>> sparkLineData = new ArrayList<>();
|
|
||||||
private ImportantAnnotationsState importantAnnotations;
|
|
||||||
private Polyline windArrow = new WindArrow(Color.LIGHTGRAY);
|
|
||||||
private ObservableList<ClientYacht> selectionComboBoxList = FXCollections.observableArrayList();
|
|
||||||
private ClientYacht player;
|
private ClientYacht player;
|
||||||
private JFXDialog finishScreenDialog;
|
private JFXDialog finishScreenDialog;
|
||||||
private FinishDialogController finishDialogController;
|
private FinishDialogController finishDialogController;
|
||||||
|
|
||||||
//Icon stuff
|
|
||||||
private Timer blinkingTimer = new Timer();
|
private Timer blinkingTimer = new Timer();
|
||||||
private ImageView iconToDisplay;
|
private ImageView iconToDisplay;
|
||||||
|
|
||||||
private Double lastWindDirection;
|
private Double lastWindDirection;
|
||||||
|
private MiniMap miniMap;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
miniMapPane.setVisible(false);
|
||||||
|
miniMapButton.setVisible(false);
|
||||||
contentStackPane.setVisible(false);
|
contentStackPane.setVisible(false);
|
||||||
Image loadingImage = new Image("PP.png");
|
Image loadingImage = new Image("PP.png");
|
||||||
loadingScreen.setImage(loadingImage);
|
loadingScreen.setImage(loadingImage);
|
||||||
@@ -231,13 +201,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
public void showView(){
|
public void showView(){
|
||||||
loadingScreenPane.setVisible(false);
|
loadingScreenPane.setVisible(false);
|
||||||
contentStackPane.setVisible(true);
|
contentStackPane.setVisible(true);
|
||||||
|
miniMapPane.setVisible(true);
|
||||||
Platform.runLater(new Runnable() {
|
miniMapButton.setVisible(true);
|
||||||
@Override
|
Platform.runLater(() -> contentStackPane.requestFocus());
|
||||||
public void run() {
|
|
||||||
contentStackPane.requestFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -265,31 +231,36 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
|
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
|
||||||
ClientYacht player) {
|
ClientYacht player) {
|
||||||
|
|
||||||
this.participants = participants;
|
|
||||||
this.courseData = raceData;
|
|
||||||
this.markers = raceData.getCompoundMarks();
|
|
||||||
this.raceState = raceState;
|
this.raceState = raceState;
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
raceState.getPlayerPositions().addListener((ListChangeListener<ClientYacht>) c -> {
|
|
||||||
while (c.next()) {
|
|
||||||
if (c.wasPermutated()) {
|
|
||||||
updateOrder(raceState.getPlayerPositions());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
player.addPowerUpListener(this::displayPowerUpIcon);
|
player.addPowerUpListener(this::displayPowerUpIcon);
|
||||||
player.addPowerDownListener(this::removeIcon);
|
player.addPowerDownListener(this::removeIcon);
|
||||||
|
|
||||||
updateOrder(raceState.getPlayerPositions());
|
|
||||||
gameView = new GameView3D();
|
gameView = new GameView3D();
|
||||||
|
miniMap = new MiniMap(
|
||||||
|
new ArrayList<>(raceData.getCompoundMarks().values()),
|
||||||
|
raceData.getMarkSequence(), raceData.getCourseLimit(),
|
||||||
|
new ArrayList<>(participants.values()), player
|
||||||
|
);
|
||||||
|
|
||||||
|
miniMapButton.setOnMouseClicked((event) -> {
|
||||||
|
if (miniMapPane.visibleProperty().get()) {
|
||||||
|
miniMapPane.setVisible(false);
|
||||||
|
miniMapButton.setText("+");
|
||||||
|
} else {
|
||||||
|
miniMapPane.setVisible(true);
|
||||||
|
miniMapButton.setText("—");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
contentStackPane.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()
|
||||||
.bind(ViewManager.getInstance().getStage().heightProperty());
|
.bind(ViewManager.getInstance().getStage().heightProperty());
|
||||||
|
miniMapPane.getChildren().add(miniMap.getAssets());
|
||||||
});
|
});
|
||||||
gameView.setBoats(new ArrayList<>(participants.values()));
|
gameView.setBoats(new ArrayList<>(participants.values()));
|
||||||
gameView.updateBorder(raceData.getCourseLimit());
|
gameView.updateBorder(raceData.getCourseLimit());
|
||||||
@@ -375,7 +346,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeIcon(ClientYacht yacht) {
|
private void removeIcon(ClientYacht yacht) {
|
||||||
if (yacht == player) {
|
if (yacht == player) {
|
||||||
blinkingTimer.cancel();
|
blinkingTimer.cancel();
|
||||||
iconToDisplay.setVisible(false);
|
iconToDisplay.setVisible(false);
|
||||||
@@ -383,45 +354,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The important annotations have been changed, update this view
|
|
||||||
*
|
|
||||||
* @param importantAnnotationsState The current state of the selected annotations
|
|
||||||
*/
|
|
||||||
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) {
|
|
||||||
this.importantAnnotations = importantAnnotationsState;
|
|
||||||
setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the "select annotations" view in a new window
|
|
||||||
*/
|
|
||||||
private void loadSelectAnnotationView() {
|
|
||||||
try {
|
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader();
|
|
||||||
Stage stage = new Stage();
|
|
||||||
// Set controller
|
|
||||||
ImportantAnnotationController controller = new ImportantAnnotationController(
|
|
||||||
this, stage
|
|
||||||
);
|
|
||||||
fxmlLoader.setController(controller);
|
|
||||||
// Load FXML and set CSS
|
|
||||||
fxmlLoader.setLocation(
|
|
||||||
getClass().getResource("/views/importantAnnotationSelectView.fxml")
|
|
||||||
);
|
|
||||||
Scene scene = new Scene(fxmlLoader.load(), 469, 298);
|
|
||||||
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
|
||||||
stage.initStyle(StageStyle.UNDECORATED);
|
|
||||||
stage.setScene(scene);
|
|
||||||
stage.show();
|
|
||||||
controller.loadState(importantAnnotations);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialises a timer which updates elements of the RaceView such as wind direction, yacht
|
* Initialises a timer which updates elements of the RaceView such as wind direction, yacht
|
||||||
* orderings etc.. which are dependent on the info from the stream parser constantly.
|
* orderings etc.. which are dependent on the info from the stream parser constantly.
|
||||||
@@ -439,35 +371,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}, 0, 1000);
|
}, 0, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Iterates over all corners until ones SeqID matches with the yachts current leg number.
|
|
||||||
* Then it gets the compoundMarkID of that corner and uses it to fetch the appropriate mark
|
|
||||||
* Returns null if no next mark found.
|
|
||||||
* @param bg The BoatGroup to find the next mark of
|
|
||||||
* @return The next Mark or null if none found
|
|
||||||
*/
|
|
||||||
private Mark getNextMark(BoatObject bg) {
|
|
||||||
// TODO: 1/08/17 Move to GameView
|
|
||||||
//
|
|
||||||
// Integer legNumber = bg.getClientYacht().getLegNumber();
|
|
||||||
// List<Corner> markSequence = courseData.getMarkSequence();
|
|
||||||
//
|
|
||||||
// if (legNumber == 0) {
|
|
||||||
// return null;
|
|
||||||
// } else if (legNumber == markSequence.size() - 1) {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for (Corner corner : markSequence) {
|
|
||||||
// if (legNumber + 2 == corner.getSeqID()) {
|
|
||||||
// return courseData.getCompoundMarks().get(corner.getCompoundMarkID());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the wind direction arrow and text as from info from the StreamParser
|
* Updates the wind direction arrow and text as from info from the StreamParser
|
||||||
* @param direction the from north angle of the wind.
|
* @param direction the from north angle of the wind.
|
||||||
@@ -549,226 +452,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
boatHeadingLabel.setText(String.format("Boat Heading:\n%.1f°", player.getHeading()));
|
boatHeadingLabel.setText(String.format("Boat Heading:\n%.1f°", player.getHeading()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the order of the yachts as from the StreamParser and sets them in the yacht order
|
|
||||||
* section
|
|
||||||
*/
|
|
||||||
private void updateOrder(ObservableList<ClientYacht> yachts) {
|
|
||||||
// List<Text> vboxEntries = new ArrayList<>();
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < yachts.size(); i++) {
|
|
||||||
//// System.out.println("yacht == null " + String.valueOf(yacht == null));
|
|
||||||
// if (yachts.get(i).getBoatStatus() == BoatStatus.FINISHED
|
|
||||||
// .getCode()) { // 3 is finish status
|
|
||||||
// Text textToAdd = new Text(i + 1 + ". " +
|
|
||||||
// yachts.get(i).getShortName() + " (Finished)");
|
|
||||||
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
|
||||||
// vboxEntries.add(textToAdd);
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// Text textToAdd = new Text(i + 1 + ". " +
|
|
||||||
// yachts.get(i).getShortName() + " ");
|
|
||||||
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
|
||||||
// textToAdd.setStyle("");
|
|
||||||
// vboxEntries.add(textToAdd);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Platform.runLater(() ->
|
|
||||||
// positionVbox.getChildren().setAll(vboxEntries)
|
|
||||||
// );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateLaylines(BoatObject bg) {
|
|
||||||
// TODO: 1/08/17 move to GameView
|
|
||||||
//
|
|
||||||
// Mark nextMark = getNextMark(bg);
|
|
||||||
// Boolean isUpwind = null;
|
|
||||||
// // Can only calc leg direction if there is a next mark and it is a gate mark
|
|
||||||
// if (nextMark != null) {
|
|
||||||
// if (nextMark instanceof GateMark) {
|
|
||||||
// if (bg.isUpwindLeg(gameViewController, nextMark)) {
|
|
||||||
// isUpwind = true;
|
|
||||||
// } else {
|
|
||||||
// isUpwind = false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for(MarkObject mg : gameViewController.getMarkGroups()) {
|
|
||||||
//
|
|
||||||
// mg.removeLaylines();
|
|
||||||
//
|
|
||||||
// if (mg.getMainMark().getId() == nextMark.getId()) {
|
|
||||||
//
|
|
||||||
// SingleMark singleMark1 = ((GateMark) nextMark).getSingleMark1();
|
|
||||||
// SingleMark singleMark2 = ((GateMark) nextMark).getSingleMark2();
|
|
||||||
// Point2D markPoint1 = gameViewController
|
|
||||||
// .findScaledXY(singleMark1.getLatitude(), singleMark1.getLongitude());
|
|
||||||
// Point2D markPoint2 = gameViewController
|
|
||||||
// .findScaledXY(singleMark2.getLatitude(), singleMark2.getLongitude());
|
|
||||||
// HashMap<Double, Double> angleAndSpeed;
|
|
||||||
// if (isUpwind) {
|
|
||||||
// angleAndSpeed = PolarTable.getOptimalUpwindVMG(StreamParser.getWindSpeed());
|
|
||||||
// } else {
|
|
||||||
// angleAndSpeed = PolarTable.getOptimalDownwindVMG(StreamParser.getWindSpeed());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Double resultingAngle = angleAndSpeed.keySet().iterator().next();
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Point2D yachtCurrentPos = new Point2D(bg.getBoatLayoutX(), bg.getBoatLayoutY());
|
|
||||||
// Point2D gateMidPoint = markPoint1.midpoint(markPoint2);
|
|
||||||
// Integer lineFuncResult = GeoUtility.lineFunction(yachtCurrentPos, gateMidPoint, markPoint2);
|
|
||||||
// Line rightLayline = new Line();
|
|
||||||
// Line leftLayline = new Line();
|
|
||||||
// if (lineFuncResult == 1) {
|
|
||||||
// rightLayline = makeRightLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
|
|
||||||
// leftLayline = makeLeftLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
|
|
||||||
// } else if (lineFuncResult == -1) {
|
|
||||||
// rightLayline = makeRightLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
|
|
||||||
// leftLayline = makeLeftLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// leftLayline.setStrokeWidth(0.5);
|
|
||||||
// leftLayline.setStroke(bg.getBoat().getColour());
|
|
||||||
//
|
|
||||||
// rightLayline.setStrokeWidth(0.5);
|
|
||||||
// rightLayline.setStroke(bg.getBoat().getColour());
|
|
||||||
//
|
|
||||||
// bg.setLaylines(leftLayline, rightLayline);
|
|
||||||
// mg.addLaylines(leftLayline, rightLayline);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private Point2D getPointRotation(Point2D ref, Double distance, Double angle) {
|
|
||||||
Double newX = ref.getX() + (ref.getX() + distance - ref.getX()) * Math.cos(angle)
|
|
||||||
- (ref.getY() + distance - ref.getY()) * Math.sin(angle);
|
|
||||||
Double newY = ref.getY() + (ref.getX() + distance - ref.getX()) * Math.sin(angle)
|
|
||||||
+ (ref.getY() + distance - ref.getY()) * Math.cos(angle);
|
|
||||||
|
|
||||||
return new Point2D(newX, newY);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Line makeLeftLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) {
|
|
||||||
Point2D ep = getPointRotation(startPoint, 50.0, baseAngle + layLineAngle);
|
|
||||||
Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY());
|
|
||||||
return line;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Line makeRightLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) {
|
|
||||||
|
|
||||||
Point2D ep = getPointRotation(startPoint, 50.0, baseAngle - layLineAngle);
|
|
||||||
Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY());
|
|
||||||
return line;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialised the combo box with any yachts currently in the race and adds the required listener
|
|
||||||
* for the combobox to take action upon selection
|
|
||||||
*/
|
|
||||||
private void initialiseBoatSelectionComboBox() {
|
|
||||||
// yachtSelectionComboBox.setItems(
|
|
||||||
// FXCollections.observableArrayList(participants.values())
|
|
||||||
// );
|
|
||||||
// //Null check is if the listener is fired but nothing selected
|
|
||||||
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
|
|
||||||
// if (selectedBoat != null) {
|
|
||||||
// gameView.selectBoat(selectedBoat);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
//TODO uncomment out
|
|
||||||
// selectionComboBoxList.setAll(participants.values());
|
|
||||||
// yachtSelectionComboBox.setItems(selectionComboBoxList);
|
|
||||||
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
|
|
||||||
// if (selectedBoat != null) {
|
|
||||||
// gameView.selectBoat(selectedBoat);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the list of yachts in the order they finished the race
|
|
||||||
*/
|
|
||||||
private void loadRaceResultView() {
|
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml"));
|
|
||||||
|
|
||||||
try {
|
|
||||||
contentGridPane.getChildren().removeAll();
|
|
||||||
contentGridPane.getChildren().clear();
|
|
||||||
contentGridPane.getChildren().addAll((Pane) loader.load());
|
|
||||||
|
|
||||||
} catch (javafx.fxml.LoadException e) {
|
|
||||||
System.err.println(e.getCause().toString());
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println(e.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getMillisToFormattedTime(long milliseconds) {
|
|
||||||
return String.format("%02d:%02d:%02d",
|
|
||||||
TimeUnit.MILLISECONDS.toHours(milliseconds),
|
|
||||||
TimeUnit.MILLISECONDS.toMinutes(milliseconds) % 60, //Modulus 60 minutes per hour
|
|
||||||
TimeUnit.MILLISECONDS.toSeconds(milliseconds) % 60 //Modulus 60 seconds per minute
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setAnnotations(Integer annotationLevel) {
|
|
||||||
// switch (annotationLevel) {
|
|
||||||
// // No Annotations
|
|
||||||
// case 0:
|
|
||||||
// gameView.setAnnotationVisibilities(
|
|
||||||
// false, false, false, false, false, false
|
|
||||||
// );
|
|
||||||
// break;
|
|
||||||
// // Important Annotations
|
|
||||||
// case 1:
|
|
||||||
// gameView.setAnnotationVisibilities(
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.NAME),
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.SPEED),
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.LEGTIME),
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.TRACK),
|
|
||||||
// importantAnnotations.getAnnotationState(Annotation.WAKE)
|
|
||||||
// );
|
|
||||||
// break;
|
|
||||||
// // All Annotations
|
|
||||||
// case 2:
|
|
||||||
// gameView.setAnnotationVisibilities(
|
|
||||||
// true, true, true, true, true, true
|
|
||||||
// );
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets all the annotations of the selected yacht to be visible and all others to be hidden
|
|
||||||
*
|
|
||||||
* @param yacht The yacht for which we want to view all annotations
|
|
||||||
*/
|
|
||||||
private void setSelectedBoat(ClientYacht yacht) {
|
|
||||||
// for (BoatObject bg : gameViewController.getBoatGroups()) {
|
|
||||||
// //We need to iterate over all race groups to get the matching yacht group belonging to this yacht if we
|
|
||||||
// //are to toggle its annotations, there is no other backwards knowledge of a yacht to its yachtgroup.
|
|
||||||
// if (bg.getBoat().getHullID().equals(yacht.getHullID())) {
|
|
||||||
//// updateLaylines(bg);
|
|
||||||
// bg.setIsSelected(true);
|
|
||||||
//// selectedBoat = yacht;
|
|
||||||
// } else {
|
|
||||||
// bg.setIsSelected(false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateTokens(RaceXMLData raceData) {
|
public void updateTokens(RaceXMLData raceData) {
|
||||||
gameView.updateTokens(raceData.getTokens());
|
gameView.updateTokens(raceData.getTokens());
|
||||||
|
|||||||
@@ -140,7 +140,9 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewManager.getInstance().getGameClient().runAsClient(listing.getAddress(), listing.getPortNumber());
|
if (!ViewManager.getInstance().getGameClient().runAsClient(listing.getAddress(), listing.getPortNumber())){
|
||||||
|
ViewManager.getInstance().showErrorSnackBar("Could not connect to server");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import javafx.scene.layout.StackPane;
|
|||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* The pre loading screen before launch the start view
|
||||||
* Created by Kusal on 26-Sep-17.
|
* Created by Kusal on 26-Sep-17.
|
||||||
*/
|
*/
|
||||||
public class SplashScreenController implements Initializable{
|
public class SplashScreenController implements Initializable{
|
||||||
@@ -26,9 +27,7 @@ public class SplashScreenController implements Initializable{
|
|||||||
public void run(){
|
public void run(){
|
||||||
try {
|
try {
|
||||||
Thread.sleep(3000);
|
Thread.sleep(3000);
|
||||||
Platform.runLater(new Runnable() {
|
Platform.runLater(() -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
try {
|
||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
ViewManager.getInstance().initialStartView(stage);
|
ViewManager.getInstance().initialStartView(stage);
|
||||||
@@ -36,7 +35,6 @@ public class SplashScreenController implements Initializable{
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
rootPane.getScene().getWindow().hide();
|
rootPane.getScene().getWindow().hide();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class ViewManager {
|
|||||||
decorator.applyCss();
|
decorator.applyCss();
|
||||||
decorator.getStylesheets()
|
decorator.getStylesheets()
|
||||||
.add(getClass().getResource("/css/Master.css").toExternalForm());
|
.add(getClass().getResource("/css/Master.css").toExternalForm());
|
||||||
gameClient = new GameClient(decorator);
|
gameClient = new GameClient();
|
||||||
setDecorator(decorator);
|
setDecorator(decorator);
|
||||||
|
|
||||||
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
|
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
|
||||||
@@ -404,7 +404,9 @@ public class ViewManager {
|
|||||||
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
|
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
|
||||||
|
|
||||||
JFXSnackbar bar = new JFXSnackbar(decorator);
|
JFXSnackbar bar = new JFXSnackbar(decorator);
|
||||||
|
Platform.runLater(() -> {
|
||||||
bar.enqueue(new JFXSnackbar.SnackbarEvent(msg));
|
bar.enqueue(new JFXSnackbar.SnackbarEvent(msg));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stage getStage() {
|
public Stage getStage() {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class ServerCreationController implements Initializable {
|
|||||||
*/
|
*/
|
||||||
private void createServer() {
|
private void createServer() {
|
||||||
ServerDescription serverDescription = ViewManager.getInstance().getGameClient()
|
ServerDescription serverDescription = ViewManager.getInstance().getGameClient()
|
||||||
.runAsHost("localhost", 4941, serverName.getText(), (int) maxPlayersSlider
|
.runAsHost(serverName.getText(), (int) maxPlayersSlider
|
||||||
.getValue(), mapMaker.getCurrentRacePath(), (int) legsSlider.getValue(), pickupsCheckBox.isSelected());
|
.getValue(), mapMaker.getCurrentRacePath(), (int) legsSlider.getValue(), pickupsCheckBox.isSelected());
|
||||||
|
|
||||||
if (serverDescription == null){
|
if (serverDescription == null){
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ public class MarkArrowFactory {
|
|||||||
STARBOARD,
|
STARBOARD,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final double MARK_ARROW_SEPARATION = 15;
|
public static final double MARK_ARROW_SEPARATION = 8;
|
||||||
public static final double ARROW_LENGTH = 75;
|
public static final double ARROW_LENGTH = 20;
|
||||||
public static final double ARROW_HEAD_DEPTH = 10;
|
public static final double ARROW_HEAD_DEPTH = 5;
|
||||||
public static final double ARROW_HEAD_WIDTH = 6;
|
public static final double ARROW_HEAD_WIDTH = 3;
|
||||||
public static final double STROKE_WIDTH = 3;
|
public static final double STROKE_WIDTH = 1;
|
||||||
|
|
||||||
public static Model constructEntryArrow3D (
|
public static Model constructEntryArrow3D (
|
||||||
RoundingSide roundingSide, double angle, ModelType type) {
|
RoundingSide roundingSide, double angle, ModelType type) {
|
||||||
@@ -106,7 +106,7 @@ public class MarkArrowFactory {
|
|||||||
Arc roundSection = new Arc(
|
Arc roundSection = new Arc(
|
||||||
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
|
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
|
||||||
//Where to start drawing arc from
|
//Where to start drawing arc from
|
||||||
(roundingSide == RoundingSide.PORT ? 0 : angleOfEntry),
|
(roundingSide == RoundingSide.PORT ? 180 + angleOfEntry : angleOfEntry),
|
||||||
//Which way to go around the mark. (clockwise vs anticlockwise)
|
//Which way to go around the mark. (clockwise vs anticlockwise)
|
||||||
roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit)
|
roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package seng302.visualiser.fxObjects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javafx.scene.Group;
|
||||||
|
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by cir27 on 28/09/17.
|
||||||
|
*/
|
||||||
|
public abstract class Marker extends Group{
|
||||||
|
|
||||||
|
protected List<Group> enterArrows = new ArrayList<>();
|
||||||
|
protected List<Group> exitArrows = new ArrayList<>();
|
||||||
|
protected int enterArrowIndex = 0;
|
||||||
|
protected int exitArrowIndex = 0;
|
||||||
|
|
||||||
|
public abstract void addArrows(RoundingSide roundingSide, double entryAngle, double exitAngle);
|
||||||
|
/**
|
||||||
|
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
|
||||||
|
*/
|
||||||
|
public void showNextEnterArrow() {
|
||||||
|
showArrow(enterArrows, enterArrowIndex);
|
||||||
|
enterArrowIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the next ExitArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
|
||||||
|
*/
|
||||||
|
public void showNextExitArrow() {
|
||||||
|
showArrow(exitArrows, exitArrowIndex);
|
||||||
|
exitArrowIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void showArrow(List<Group> arrowList, int arrowListIndex);
|
||||||
|
|
||||||
|
public abstract void hideAllArrows();
|
||||||
|
}
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_2D;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.beans.value.ObservableValue;
|
|
||||||
import javafx.scene.CacheHint;
|
|
||||||
import javafx.scene.Group;
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.scene.paint.Paint;
|
|
||||||
import javafx.scene.shape.Rectangle;
|
|
||||||
import javafx.scene.text.Text;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Grouping of string objects over a semi transparent background.
|
|
||||||
*/
|
|
||||||
public class AnnotationBox extends Group {
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface AnnotationFormatter<T> {
|
|
||||||
String transformString (T input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class stores a text object and relationship for updating the text object if needed
|
|
||||||
*
|
|
||||||
* @param <T> The type of observable value passed to the annotation, if there is one.
|
|
||||||
*/
|
|
||||||
public class Annotation<T> {
|
|
||||||
private Text text;
|
|
||||||
private ObservableValue<T> source;
|
|
||||||
private AnnotationFormatter<T> format;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for observing annotation
|
|
||||||
* @param textObject the javaFX text object the annotation is displayed in
|
|
||||||
* @param source observable value that the annotation is taken from
|
|
||||||
* @param formatter interface describing how to format the source data if needed
|
|
||||||
*/
|
|
||||||
public Annotation (Text textObject, ObservableValue<T> source, AnnotationFormatter<T> formatter) {
|
|
||||||
this.text = textObject;
|
|
||||||
this.source = source;
|
|
||||||
this.format = formatter;
|
|
||||||
source.addListener((obs, oldVal, newVal) ->
|
|
||||||
Platform.runLater(() -> text.setText(format.transformString(newVal)))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for a static annotation
|
|
||||||
* @param textObject the javaFX text object the annotation is displayed in
|
|
||||||
* @param annotationText the static value of the test object
|
|
||||||
*/
|
|
||||||
public Annotation (Text textObject, String annotationText) {
|
|
||||||
textObject.setText(annotationText);
|
|
||||||
text = textObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Text getText () {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Text offset constants
|
|
||||||
private static final double X_OFFSET_TEXT = 20d;
|
|
||||||
private static final double Y_OFFSET_TEXT_INIT = -35d;
|
|
||||||
private static final double Y_OFFSET_PER_TEXT = 12d;
|
|
||||||
//Background constants
|
|
||||||
private static final double TEXT_BUFFER = 3;
|
|
||||||
private static final double BACKGROUND_X = X_OFFSET_TEXT - TEXT_BUFFER;
|
|
||||||
private static final double BACKGROUND_Y = Y_OFFSET_TEXT_INIT - TEXT_BUFFER;
|
|
||||||
private static final double BACKGROUND_H_PER_TEXT = 9.5d;
|
|
||||||
private static final double BACKGROUND_ARC_SIZE = 10;
|
|
||||||
|
|
||||||
private int visibleAnnotations = 0;
|
|
||||||
private double backgroundWidth = 145d;
|
|
||||||
|
|
||||||
private Rectangle background = new Rectangle();
|
|
||||||
private Paint theme = Color.BLACK;
|
|
||||||
|
|
||||||
private Map<String, Annotation> annotationsByName = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an empty annotation box. The box is offset from (0,0) by (17, -38).
|
|
||||||
*/
|
|
||||||
public AnnotationBox() {
|
|
||||||
this.setCache(true);
|
|
||||||
background.setX(BACKGROUND_X);
|
|
||||||
background.setY(BACKGROUND_Y);
|
|
||||||
background.setWidth(backgroundWidth);
|
|
||||||
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * 4);
|
|
||||||
background.setArcHeight(BACKGROUND_ARC_SIZE);
|
|
||||||
background.setArcWidth(BACKGROUND_ARC_SIZE);
|
|
||||||
background.setFill(new Color(1, 1, 1, 0.75));
|
|
||||||
background.setStroke(theme);
|
|
||||||
background.setStrokeWidth(2);
|
|
||||||
background.setCache(true);
|
|
||||||
background.setCacheHint(CacheHint.SCALE);
|
|
||||||
this.getChildren().add(background);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation to the box. Use the name to reference the annotation for removal or\
|
|
||||||
* changing visibility.
|
|
||||||
* @param annotationName the name of the annotation.
|
|
||||||
* @param annotation the annotation.
|
|
||||||
*/
|
|
||||||
public void addAnnotation (String annotationName, Annotation annotation) {
|
|
||||||
annotationsByName.put(annotationName, annotation);
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
this.getChildren().add(annotation.getText());
|
|
||||||
visibleAnnotations++;
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation with a constant text.
|
|
||||||
* @param annotationName The name of the annotation. Will be used to reference it later.
|
|
||||||
* @param annotationText The desired text.
|
|
||||||
*/
|
|
||||||
public void addAnnotation (String annotationName, String annotationText) {
|
|
||||||
Text text = getTextObject();
|
|
||||||
addAnnotation(annotationName, new Annotation(text, annotationText));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an annotation with the given name. The annotation will contain the value of the given
|
|
||||||
* ObservableValue. The formatter should return a String and takes an object of the same type as
|
|
||||||
* the ObservableValue as a parameter. The String is how you want the annotation to look.
|
|
||||||
* @param annotationName The annotation name.
|
|
||||||
* @param observable The observable value the annotation will display.
|
|
||||||
* @param formatter A formatting function for the observable value.
|
|
||||||
* @param <E> The type of ObservableValue.
|
|
||||||
*/
|
|
||||||
public <E> void addAnnotation (String annotationName, ObservableValue<E> observable,
|
|
||||||
AnnotationFormatter<E> formatter) {
|
|
||||||
Text newText = getTextObject();
|
|
||||||
addAnnotation(annotationName, new Annotation<>(newText, observable, formatter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the visibility of the annotation with the given name if it exists.
|
|
||||||
* @param annotationName The name of the annotation
|
|
||||||
* @param visibility the desired visibility
|
|
||||||
*/
|
|
||||||
public void setAnnotationVisibility (String annotationName, boolean visibility) {
|
|
||||||
if (annotationsByName.containsKey(annotationName)) {
|
|
||||||
Text textField = annotationsByName.get(annotationName).text;
|
|
||||||
boolean currentState = textField.visibleProperty().get();
|
|
||||||
if (visibility != currentState) {
|
|
||||||
if (visibility)
|
|
||||||
visibleAnnotations++;
|
|
||||||
else
|
|
||||||
visibleAnnotations--;
|
|
||||||
}
|
|
||||||
textField.setVisible(visibility);
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the annotation with the given name if it exits.
|
|
||||||
* @param annotationName The name given when the annotation was created.
|
|
||||||
*/
|
|
||||||
public void removeAnnotation (String annotationName) {
|
|
||||||
if (annotationName.contains(annotationName)) {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
this.getChildren().remove(annotationsByName.remove(annotationName).getText());
|
|
||||||
visibleAnnotations--;
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
annotationsByName.remove(annotationName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the annotation.
|
|
||||||
* @param x x location
|
|
||||||
* @param y y location
|
|
||||||
*/
|
|
||||||
public void setLocation (double x, double y) {
|
|
||||||
Platform.runLater(()-> this.relocate(x + BACKGROUND_X, y + BACKGROUND_Y));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the width of the annotation box. Default is 145.
|
|
||||||
* @param width new width.
|
|
||||||
*/
|
|
||||||
public void setWidth (double width) {
|
|
||||||
backgroundWidth = width;
|
|
||||||
Platform.runLater(() -> background.setWidth(backgroundWidth));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update () {
|
|
||||||
background.setVisible(visibleAnnotations != 0);
|
|
||||||
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * visibleAnnotations);
|
|
||||||
for (int i = 1; i <= visibleAnnotations; i++) {
|
|
||||||
Text text = (Text) this.getChildren().get(i);
|
|
||||||
if (text.visibleProperty().get()) {
|
|
||||||
text.setX(X_OFFSET_TEXT);
|
|
||||||
text.setY(Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * i);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a text object for an annotation.
|
|
||||||
* @return The text object
|
|
||||||
*/
|
|
||||||
private Text getTextObject() {
|
|
||||||
Text text = new Text();
|
|
||||||
text.setFill(theme);
|
|
||||||
text.setStrokeWidth(2);
|
|
||||||
// text.setCacheHint(CacheHint.QUALITY);
|
|
||||||
text.setCache(true);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the colour of the annotation box's border and text colour.
|
|
||||||
* @param value desired colour.
|
|
||||||
*/
|
|
||||||
public void setFill (Paint value) {
|
|
||||||
theme = value;
|
|
||||||
background.setStroke(theme);
|
|
||||||
annotationsByName.forEach((name, annotation) -> annotation.getText().setFill(theme));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_2D;
|
package seng302.visualiser.fxObjects.assets_2D;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
@@ -8,18 +7,15 @@ import javafx.scene.paint.Color;
|
|||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
import javafx.scene.shape.Circle;
|
import javafx.scene.shape.Circle;
|
||||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||||
|
import seng302.visualiser.fxObjects.Marker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
||||||
*/
|
*/
|
||||||
public class Marker2D extends Group {
|
public class Marker2D extends Marker {
|
||||||
|
|
||||||
private Circle mark = new Circle();
|
private Circle mark = new Circle();
|
||||||
private Paint colour = Color.BLACK;
|
private Paint colour = Color.BLACK;
|
||||||
private List<Group> enterArrows = new ArrayList<>();
|
|
||||||
private List<Group> exitArrows = new ArrayList<>();
|
|
||||||
private int enterArrowIndex = 0;
|
|
||||||
private int exitArrowIndex = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Marker containing only a circle. The default colour is black.
|
* Creates a new Marker containing only a circle. The default colour is black.
|
||||||
@@ -28,8 +24,7 @@ public class Marker2D extends Group {
|
|||||||
mark.setRadius(5);
|
mark.setRadius(5);
|
||||||
mark.setCenterX(0);
|
mark.setCenterX(0);
|
||||||
mark.setCenterY(0);
|
mark.setCenterY(0);
|
||||||
Platform.runLater(() -> this.getChildren()
|
Platform.runLater(() -> this.getChildren().add(mark));
|
||||||
.addAll(mark, new Group())); //Empty group placeholder or arrows.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,15 +75,12 @@ public class Marker2D extends Group {
|
|||||||
exitArrowIndex++;
|
exitArrowIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showArrow(List<Group> arrowList, int arrowListIndex) {
|
@Override
|
||||||
|
protected void showArrow(List<Group> arrowList, int arrowListIndex) {
|
||||||
if (arrowListIndex < arrowList.size()) {
|
if (arrowListIndex < arrowList.size()) {
|
||||||
if (arrowListIndex == 1) {
|
Platform.runLater(() ->
|
||||||
;
|
this.getChildren().setAll(mark, arrowList.get(arrowListIndex))
|
||||||
}
|
);
|
||||||
Platform.runLater(() -> {
|
|
||||||
this.getChildren().remove(1);
|
|
||||||
this.getChildren().add(arrowList.get(arrowListIndex));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ public class Wake extends Group {
|
|||||||
|
|
||||||
//The number of wakes
|
//The number of wakes
|
||||||
private int numWakes = 8;
|
private int numWakes = 8;
|
||||||
//The total possible difference between the first wake and the last. Increasing/Decreasing this will make wakes fan out more/less.
|
|
||||||
private final double MAX_DIFF = 75;
|
|
||||||
//Increasing/decreasing this will alter the speed that wakes converge when the heading stop changing. Anything over about 1500 may cause oscillation.
|
|
||||||
private final int UNIFICATION_SPEED = 45;
|
|
||||||
|
|
||||||
|
|
||||||
private Arc[] arcs = new Arc[numWakes];
|
private Arc[] arcs = new Arc[numWakes];
|
||||||
@@ -69,34 +65,6 @@ public class Wake extends Group {
|
|||||||
rad += (14 / numWakes) + (velocity / 2.5);
|
rad += (14 / numWakes) + (velocity / 2.5);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// } else {
|
|
||||||
// rotations[0] = rotation;
|
|
||||||
// ((Rotate) arcs[0].getTransforms().get(0)).setAngle(rotation);
|
|
||||||
// for (int i = 1; i < numWakes; i++) {
|
|
||||||
// double wakeSeparationRad = Math.toRadians(rotations[i - 1] - rotations[i]);
|
|
||||||
// double shortestDistance = Math.atan2(
|
|
||||||
// Math.sin(wakeSeparationRad),
|
|
||||||
// Math.cos(wakeSeparationRad)
|
|
||||||
// );
|
|
||||||
// double distDeg = Math.toDegrees(shortestDistance);
|
|
||||||
// if (rotationalVelocities[i - 1] < 0.01 && rotationalVelocities[i - 1] > -0.01) {
|
|
||||||
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * 2 * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// if (distDeg < (MAX_DIFF / numWakes)) {
|
|
||||||
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
|
||||||
// } else
|
|
||||||
// rotationalVelocities[i] = rotationalVelocities[i - 1];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// double rad = (14 / numWakes) + velocity;
|
|
||||||
// for (Arc arc : arcs) {
|
|
||||||
// arc.setRadiusX(rad);
|
|
||||||
// arc.setRadiusY(rad);
|
|
||||||
// rad += (14 / numWakes) + (velocity / 2.5);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_2D;
|
|
||||||
|
|
||||||
import javafx.scene.paint.Paint;
|
|
||||||
import javafx.scene.shape.Polyline;
|
|
||||||
import javafx.scene.shape.StrokeLineCap;
|
|
||||||
import javafx.scene.shape.StrokeLineJoin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by cir27 on 5/09/17.
|
|
||||||
*/
|
|
||||||
public class WindArrow extends Polyline {
|
|
||||||
public WindArrow(Paint fill) {
|
|
||||||
this.getPoints().addAll(
|
|
||||||
-10d, 15d,
|
|
||||||
0d, 25d,
|
|
||||||
0d, -25d,
|
|
||||||
0d, 25d,
|
|
||||||
10d, 15d
|
|
||||||
);
|
|
||||||
this.setStrokeLineCap(StrokeLineCap.ROUND);
|
|
||||||
this.setStroke(fill);
|
|
||||||
this.setStrokeWidth(5);
|
|
||||||
this.setStrokeLineJoin(StrokeLineJoin.ROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,7 @@ public enum BoatMeshType {
|
|||||||
PIRATE_SHIP("pirateship_hull.stl", "pirateship_mast.stl", -0.5415, "pirateship_mainsail.stl",
|
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),
|
-0.5415, "pirateship_frontsail.stl", true, 1.2, 1.6, 1.2),
|
||||||
DUCKY("ducky_hull.stl", "ducky_mast.stl", -2.18539, "ducky_sail.stl", -2.18539, "ducky_eyes.stl", false, 1.2, 1.1, 1.4),
|
DUCKY("ducky_hull.stl", "ducky_mast.stl", -2.18539, "ducky_sail.stl", -2.18539, "ducky_eyes.stl", false, 1.2, 1.1, 1.4),
|
||||||
PARROT("parrot_hull.stl", null, 0, "parrot_sail.stl", 0, "parrot_features.stl", true, 1, 1, 1),
|
PARROT("parrot_hull.stl", null, 0, "parrot_features.stl", 0, "parrot_sail.stl", true, 1, 1, 1),
|
||||||
WAKA("waka_hull.stl", "waka_mast.stl", 0, "waka_sail.stl", 0, null, true, 1.7, 0.5, 1.5);
|
WAKA("waka_hull.stl", "waka_mast.stl", 0, "waka_sail.stl", 0, null, true, 1.7, 0.5, 1.5);
|
||||||
|
|
||||||
final String hullFile, mastFile, sailFile, jibFile;
|
final String hullFile, mastFile, sailFile, jibFile;
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ public class BoatModel extends Model {
|
|||||||
*/
|
*/
|
||||||
public void changeColour(Color newColour) {
|
public void changeColour(Color newColour) {
|
||||||
changeColourChild(HULL_INDEX, newColour);
|
changeColourChild(HULL_INDEX, newColour);
|
||||||
|
if (meshType != BoatMeshType.PARROT) {
|
||||||
changeColourChild(MAST_INDEX, newColour);
|
changeColourChild(MAST_INDEX, newColour);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void changeColourChild(int index, Color newColour) {
|
private void changeColourChild(int index, Color newColour) {
|
||||||
MeshView meshView = getMeshViewChild(index);
|
MeshView meshView = getMeshViewChild(index);
|
||||||
|
|||||||
@@ -1,22 +1,17 @@
|
|||||||
package seng302.visualiser.fxObjects.assets_3D;
|
package seng302.visualiser.fxObjects.assets_3D;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||||
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
|
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
|
||||||
|
import seng302.visualiser.fxObjects.Marker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
||||||
*/
|
*/
|
||||||
public class Marker3D extends Group {
|
public class Marker3D extends Marker {
|
||||||
|
|
||||||
private Model mark;
|
private Model mark;
|
||||||
private List<Group> enterArrows = new ArrayList<>();
|
|
||||||
private List<Group> exitArrows = new ArrayList<>();
|
|
||||||
private int enterArrowIndex = 0;
|
|
||||||
private int exitArrowIndex = 0;
|
|
||||||
private ModelType markType;
|
private ModelType markType;
|
||||||
private ModelType arrowType;
|
private ModelType arrowType;
|
||||||
|
|
||||||
@@ -60,23 +55,8 @@ public class Marker3D extends Group {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
|
protected void showArrow(List<Group> arrowList, int arrowListIndex) {
|
||||||
*/
|
|
||||||
public void showNextEnterArrow() {
|
|
||||||
showArrow(enterArrows, enterArrowIndex);
|
|
||||||
enterArrowIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the next ExitArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
|
|
||||||
*/
|
|
||||||
public void showNextExitArrow() {
|
|
||||||
showArrow(exitArrows, exitArrowIndex);
|
|
||||||
exitArrowIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showArrow(List<Group> arrowList, int arrowListIndex) {
|
|
||||||
if (arrowListIndex < arrowList.size()) {
|
if (arrowListIndex < arrowList.size()) {
|
||||||
Platform.runLater(() ->
|
Platform.runLater(() ->
|
||||||
this.getChildren().setAll(mark.getAssets(), arrowList.get(arrowListIndex))
|
this.getChildren().setAll(mark.getAssets(), arrowList.get(arrowListIndex))
|
||||||
|
|||||||
@@ -99,19 +99,19 @@ public class ModelFactory {
|
|||||||
mast.setMaterial(new PhongMaterial(primaryColour));
|
mast.setMaterial(new PhongMaterial(primaryColour));
|
||||||
boatAssets.getChildren().add(mast);
|
boatAssets.getChildren().add(mast);
|
||||||
} else {
|
} else {
|
||||||
boatAssets.getChildren().add(new Group());
|
boatAssets.getChildren().add(new MeshView());
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshView sail = importBoatSTL(boatType.sailFile);
|
MeshView sail = importBoatSTL(boatType.sailFile);
|
||||||
sail.setMaterial(
|
sail.setMaterial(
|
||||||
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE)
|
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE)
|
||||||
);
|
);
|
||||||
boatAssets.getChildren().add(sail);
|
boatAssets.getChildren().add(sail);
|
||||||
|
|
||||||
if (boatType.jibFile != null) {
|
if (boatType.jibFile != null) {
|
||||||
MeshView jib = importBoatSTL(boatType.jibFile);
|
MeshView jib = importBoatSTL(boatType.jibFile);
|
||||||
jib.setMaterial(
|
jib.setMaterial(
|
||||||
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE)
|
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE)
|
||||||
);
|
);
|
||||||
boatAssets.getChildren().add(jib);
|
boatAssets.getChildren().add(jib);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Boundary class represents a rectangle territorial boundary on a map. It
|
|
||||||
* contains four extremity double values(N, E, S, W). N and S are represented as
|
|
||||||
* latitudes in radians. E and W are represented as longitudes in radians.
|
|
||||||
*
|
|
||||||
* Created by Haoming on 10/5/17
|
|
||||||
*/
|
|
||||||
public class Boundary {
|
|
||||||
|
|
||||||
private double northLat, eastLng, southLat, westLng;
|
|
||||||
|
|
||||||
public Boundary(double northLat, double eastLng, double southLat, double westLng) {
|
|
||||||
this.northLat = northLat;
|
|
||||||
this.eastLng = eastLng;
|
|
||||||
this.southLat = southLat;
|
|
||||||
this.westLng = westLng;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getCentreLat() {
|
|
||||||
return (northLat + southLat) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getCentreLng() {
|
|
||||||
return (eastLng + westLng) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getNorthLat() {
|
|
||||||
return northLat;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getEastLng() {
|
|
||||||
return eastLng;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getSouthLat() {
|
|
||||||
return southLat;
|
|
||||||
}
|
|
||||||
|
|
||||||
double getWestLng() {
|
|
||||||
return westLng;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import javafx.scene.image.Image;
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CanvasMap retrieves a map image with given geo boundary from Google Map server.
|
|
||||||
* By passing a rectangle like geo boundary, it returns a map image with the
|
|
||||||
* highest resolution. However, due to free quote account usage limit, the maximum
|
|
||||||
* resolution is only 1280 * 1280.
|
|
||||||
*
|
|
||||||
* Created by Haoming on 15/5/2017
|
|
||||||
*/
|
|
||||||
public class CanvasMap {
|
|
||||||
|
|
||||||
private Boundary boundary;
|
|
||||||
private long width, height; // desired image size
|
|
||||||
private int zoom;
|
|
||||||
|
|
||||||
private String KEY = "AIzaSyC-5oOShMCY5Oy_9L7guYMPUPFHDMr37wE";
|
|
||||||
|
|
||||||
public CanvasMap(Boundary boundary) {
|
|
||||||
this.boundary = boundary;
|
|
||||||
calculateOptimalMapSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Image getMapImage() {
|
|
||||||
try {
|
|
||||||
URL url = new URL(getRequest());
|
|
||||||
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
|
|
||||||
|
|
||||||
return new Image(connection.getInputStream());
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.out.println("[CanvasMap] Exception");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getRequest() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("https://maps.googleapis.com/maps/api/staticmap?");
|
|
||||||
sb.append(String.format("center=%f,%f", boundary.getCentreLat(), boundary.getCentreLng()));
|
|
||||||
sb.append(String.format("&zoom=%d", zoom));
|
|
||||||
sb.append(String.format("&size=%dx%d&scale=2", width, height));
|
|
||||||
sb.append("&style=feature:all|element:labels|visibility:off"); // hide all labels on map
|
|
||||||
// sb.append(String.format("&markers=%f,%f", boundary.getSouthLat(), boundary.getWestLng()));
|
|
||||||
// sb.append(String.format("&key=%s", KEY));
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void calculateOptimalMapSize() {
|
|
||||||
for (int z = 20; z > 0; z--) {
|
|
||||||
MapSize mapSize = getMapSize(z, boundary);
|
|
||||||
zoom = z;
|
|
||||||
width = mapSize.width;
|
|
||||||
height = mapSize.height;
|
|
||||||
// if map size is valid, exit the loop as we have the highest resolution
|
|
||||||
if (mapSize.isValid()) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MapSize getMapSize(int zoom, Boundary boundary) {
|
|
||||||
double scale = Math.pow(2, zoom);
|
|
||||||
GeoPoint geoSW = new GeoPoint(boundary.getSouthLat(), boundary.getWestLng());
|
|
||||||
GeoPoint geoNE = new GeoPoint(boundary.getNorthLat(), boundary.getEastLng());
|
|
||||||
Point2D pointSW = MercatorProjection.toMapPoint(geoSW);
|
|
||||||
Point2D pointNE = MercatorProjection.toMapPoint(geoNE);
|
|
||||||
return new MapSize(Math.abs(pointNE.getX() - pointSW.getX()) * scale,
|
|
||||||
Math.abs(pointNE.getY() - pointSW.getY()) * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapSize {
|
|
||||||
long width, height;
|
|
||||||
|
|
||||||
MapSize(double width, double height) {
|
|
||||||
this.width = Math.round(width);
|
|
||||||
this.height = Math.round(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map size is valid when width and height are both less than 640 pixels
|
|
||||||
* @return true if both dimensions are less than 640px
|
|
||||||
*/
|
|
||||||
boolean isValid() {
|
|
||||||
return Math.max(width, height) <= 640;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getWidth() {
|
|
||||||
return width;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getHeight() {
|
|
||||||
return height;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getZoom() {
|
|
||||||
return zoom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import javafx.geometry.Point2D;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An utility class useful to convert between Geo locations and Mercator projection
|
|
||||||
* planar coordinates.
|
|
||||||
* Created by Haoming on 15/5/2017
|
|
||||||
*/
|
|
||||||
public class MercatorProjection {
|
|
||||||
|
|
||||||
private static final double MERCATOR_RANGE = 256;
|
|
||||||
private static final double pixelsPerLngDegree = MERCATOR_RANGE / 360.0;
|
|
||||||
private static final double pixelsPerLngRadian = MERCATOR_RANGE / (2 * Math.PI);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A help function keeps the value in bound between -0.9999 and 0.9999.
|
|
||||||
* @param value in bound value
|
|
||||||
* @return the value in bound
|
|
||||||
*/
|
|
||||||
private static double bound(double value) {
|
|
||||||
return Math.min(Math.max(value, -0.9999), 0.9999);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Projects a Geo Location (lat, lng) on a planar
|
|
||||||
* @param geo GeoPoint (lat, lng) location to be projected
|
|
||||||
* @return the projection Point2D (x, y) on planar
|
|
||||||
*/
|
|
||||||
public static Point2D toMapPoint(GeoPoint geo) {
|
|
||||||
double x, y;
|
|
||||||
Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0);
|
|
||||||
x = (origin.getX() + geo.getLng() * pixelsPerLngDegree);
|
|
||||||
|
|
||||||
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
|
|
||||||
// 89.189. This is about a third of a tile past the edge of the world tile.
|
|
||||||
double sinY = bound(Math.sin(Math.toRadians(geo.getLat())));
|
|
||||||
y = origin.getY() + 0.5 * Math.log((1 + sinY) / (1 - sinY)) * (-pixelsPerLngRadian);
|
|
||||||
return new Point2D(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the planar projection (x, y) back to Geo Location (lat, lng)
|
|
||||||
* @param point Point2D (x, y) to be converted back
|
|
||||||
* @return the original Geo location converted from the given projection point
|
|
||||||
*/
|
|
||||||
public static GeoPoint toMapGeo(Point2D point) {
|
|
||||||
Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0);
|
|
||||||
double lng = (point.getX() - origin.getX()) / pixelsPerLngDegree;
|
|
||||||
double latRadians = (point.getY() - origin.getY()) / (-pixelsPerLngRadian);
|
|
||||||
double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2.0);
|
|
||||||
return new GeoPoint(lat, lng);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import javafx.fxml.FXML;
|
|
||||||
import javafx.fxml.Initializable;
|
|
||||||
import javafx.scene.canvas.Canvas;
|
|
||||||
import javafx.scene.canvas.GraphicsContext;
|
|
||||||
|
|
||||||
public class TestMapController implements Initializable{
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Canvas mapCanvas;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
|
||||||
GraphicsContext gc = mapCanvas.getGraphicsContext2D();
|
|
||||||
Boundary bound = new Boundary(57.662943, 11.848501, 57.673945, 11.824966);
|
|
||||||
CanvasMap canvasMap = new CanvasMap(bound);
|
|
||||||
gc.drawImage(canvasMap.getMapImage(), 0, 0, canvasMap.getWidth(), canvasMap.getHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
<Marks>
|
<Marks>
|
||||||
<CompoundMark CompoundMarkID="1">
|
<CompoundMark CompoundMarkID="1">
|
||||||
<Mark Lat="-14.071412" Lng="47.05756"/>
|
<Mark Lat="-14.070412" Lng="47.05746"/>
|
||||||
<Mark Lat="-14.069914" Lng="47.058541"/>
|
<Mark Lat="-14.068014" Lng="47.057541"/>
|
||||||
</CompoundMark>
|
</CompoundMark>
|
||||||
<CompoundMark CompoundMarkID="2">
|
<CompoundMark CompoundMarkID="2">
|
||||||
<Mark Lat="-14.067194" Lng="47.053818" />
|
<Mark Lat="-14.067194" Lng="47.053818" />
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<CourseLimit>
|
<CourseLimit>
|
||||||
<Limit Lat="-14.073371" Lng="47.058213" />
|
<Limit Lat="-14.073371" Lng="47.058213" />
|
||||||
<Limit Lat="-14.06453" Lng="47.050003" />
|
<Limit Lat="-14.06453" Lng="47.050003" />
|
||||||
<Limit Lat="-14.059022" Lng="47.057286" />
|
<Limit Lat="-14.057022" Lng="47.057286" />
|
||||||
<Limit Lat="-14.058723" Lng="47.064358" />
|
<Limit Lat="-14.058723" Lng="47.064358" />
|
||||||
<Limit Lat="-14.06261" Lng="47.071293" />
|
<Limit Lat="-14.06261" Lng="47.071293" />
|
||||||
<Limit Lat="-14.070814" Lng="47.06762" />
|
<Limit Lat="-14.070814" Lng="47.06762" />
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
</CompoundMark>
|
</CompoundMark>
|
||||||
<CompoundMark CompoundMarkID="2">
|
<CompoundMark CompoundMarkID="2">
|
||||||
<Mark Lat="57.670914" Lng="11.835263"/>
|
<Mark Lat="57.670914" Lng="11.835263"/>
|
||||||
<Mark Lat="57.6699024" Lng="11.8353195"/>
|
|
||||||
</CompoundMark>
|
</CompoundMark>
|
||||||
<CompoundMark CompoundMarkID="3">
|
<CompoundMark CompoundMarkID="3">
|
||||||
<Mark Lat="57.6674596" Lng="11.8417500"/>
|
<Mark Lat="57.6674596" Lng="11.8417500"/>
|
||||||
@@ -29,21 +28,27 @@
|
|||||||
<Mark Lat="57.667311" Lng="11.828857"/>
|
<Mark Lat="57.667311" Lng="11.828857"/>
|
||||||
<Mark Lat="57.667334" Lng="11.825853"/>
|
<Mark Lat="57.667334" Lng="11.825853"/>
|
||||||
</CompoundMark>
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="6">
|
||||||
|
<Mark Lat="57.6675700" Lng="11.8359880"/>
|
||||||
|
<Mark Lat="57.667610" Lng="11.833473"/>
|
||||||
|
</CompoundMark>
|
||||||
</Marks>
|
</Marks>
|
||||||
|
|
||||||
<Course>
|
<Course>
|
||||||
<OpeningSegment>
|
<OpeningSegment>
|
||||||
<Corner CompoundMarkID="1" Rounding="PS"/>
|
<Corner CompoundMarkID="1" Rounding="PS"/>
|
||||||
<Corner CompoundMarkID="2" Rounding="P"/>
|
<Corner CompoundMarkID="2" Rounding="S"/>
|
||||||
</OpeningSegment>
|
</OpeningSegment>
|
||||||
|
|
||||||
<RepeatingSegment>
|
<RepeatingSegment>
|
||||||
<Corner CompoundMarkID="3" Rounding="SP"/>
|
<Corner CompoundMarkID="3" Rounding="SP"/>
|
||||||
<Corner CompoundMarkID="4" Rounding="PS"/>
|
<Corner CompoundMarkID="4" Rounding="PS"/>
|
||||||
|
<Corner CompoundMarkID="5" Rounding="PS"/>
|
||||||
|
<Corner CompoundMarkID="2" Rounding="S"/>
|
||||||
</RepeatingSegment>
|
</RepeatingSegment>
|
||||||
|
|
||||||
<ClosingSegment>
|
<ClosingSegment>
|
||||||
<Corner CompoundMarkID="5" Rounding="PS"/>
|
<Corner CompoundMarkID="6" Rounding="PS"/>
|
||||||
</ClosingSegment>
|
</ClosingSegment>
|
||||||
</Course>
|
</Course>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RaceDefinition>
|
||||||
|
|
||||||
|
<CourseName>Madagascar</CourseName>
|
||||||
|
|
||||||
|
<CentralLat>-15.67707</CentralLat>
|
||||||
|
<CentralLng>49.79338</CentralLng>
|
||||||
|
|
||||||
|
<MaxPlayers>10</MaxPlayers>
|
||||||
|
|
||||||
|
<Marks>
|
||||||
|
<CompoundMark CompoundMarkID="1">
|
||||||
|
<Mark Lat="-15.67466" Lng="49.79104"/>
|
||||||
|
<Mark Lat="-15.67408" Lng="49.79224"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2">
|
||||||
|
<Mark Lat="-15.67548" Lng="49.79271"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3">
|
||||||
|
<Mark Lat="-15.67744" Lng="49.79235"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4">
|
||||||
|
<Mark Lat="-15.67691" Lng="49.79501"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5">
|
||||||
|
<Mark Lat="-15.67775" Lng="49.79619"/>
|
||||||
|
<Mark Lat="-15.67827" Lng="49.79713"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="6">
|
||||||
|
<Mark Lat="-15.67922" Lng="49.79318"/>
|
||||||
|
<Mark Lat="-15.67972" Lng="49.79393"/>
|
||||||
|
</CompoundMark>
|
||||||
|
</Marks>
|
||||||
|
|
||||||
|
<Course>
|
||||||
|
<OpeningSegment>
|
||||||
|
<Corner CompoundMarkID="1" Rounding="PS"/>
|
||||||
|
</OpeningSegment>
|
||||||
|
|
||||||
|
<RepeatingSegment>
|
||||||
|
<Corner CompoundMarkID="2" Rounding="P"/>
|
||||||
|
<Corner CompoundMarkID="3" Rounding="S"/>
|
||||||
|
<Corner CompoundMarkID="4" Rounding="S"/>
|
||||||
|
<Corner CompoundMarkID="3" Rounding="P"/>
|
||||||
|
</RepeatingSegment>
|
||||||
|
|
||||||
|
<ClosingSegment>
|
||||||
|
<Corner CompoundMarkID="5" Rounding="PS"/>
|
||||||
|
<Corner CompoundMarkID="6" Rounding="PS"/>
|
||||||
|
</ClosingSegment>
|
||||||
|
</Course>
|
||||||
|
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit Lat="-15.67571" Lng="49.78984"/>
|
||||||
|
<Limit Lat="-15.6787" Lng="49.79024"/>
|
||||||
|
<Limit Lat="-15.68046" Lng="49.79247"/>
|
||||||
|
<Limit Lat="-15.68073" Lng="49.79599"/>
|
||||||
|
<Limit Lat="-15.67939" Lng="49.79855"/>
|
||||||
|
<Limit Lat="-15.67662" Lng="49.79855"/>
|
||||||
|
<Limit Lat="-15.67474" Lng="49.79694"/>
|
||||||
|
<Limit Lat="-15.67271" Lng="49.79355"/>
|
||||||
|
<Limit Lat="-15.67333" Lng="49.79071"/>
|
||||||
|
</CourseLimit>
|
||||||
|
|
||||||
|
</RaceDefinition>
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RaceDefinition>
|
||||||
|
|
||||||
|
<CourseName>Waiheke</CourseName>
|
||||||
|
|
||||||
|
<CentralLat>-36.80008</CentralLat>
|
||||||
|
<CentralLng>175.012225</CentralLng>
|
||||||
|
|
||||||
|
<MaxPlayers>10</MaxPlayers>
|
||||||
|
|
||||||
|
<Marks>
|
||||||
|
<CompoundMark CompoundMarkID="1">
|
||||||
|
<Mark Lat="-36.79512" Lng="175.0116"/>
|
||||||
|
<Mark Lat="-36.79468" Lng="175.01312"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2">
|
||||||
|
<Mark Lat="-36.80069" Lng="175.01495"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3">
|
||||||
|
<Mark Lat="-36.79892" Lng="175.01832"/>
|
||||||
|
<Mark Lat="-36.79988" Lng="175.01913"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4">
|
||||||
|
<Mark Lat="-36.80064" Lng="175.01171"/>
|
||||||
|
<Mark Lat="-36.80186" Lng="175.0124"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5">
|
||||||
|
<Mark Lat="-36.79579" Lng="175.01194"/>
|
||||||
|
<Mark Lat="-36.79545" Lng="175.01349"/>
|
||||||
|
</CompoundMark>
|
||||||
|
</Marks>
|
||||||
|
|
||||||
|
<Course>
|
||||||
|
<OpeningSegment>
|
||||||
|
<Corner CompoundMarkID="1" Rounding="PS"/>
|
||||||
|
<Corner CompoundMarkID="2" Rounding="P"/>
|
||||||
|
</OpeningSegment>
|
||||||
|
|
||||||
|
<RepeatingSegment>
|
||||||
|
<Corner CompoundMarkID="3" Rounding="SP"/>
|
||||||
|
<Corner CompoundMarkID="4" Rounding="PS"/>
|
||||||
|
</RepeatingSegment>
|
||||||
|
|
||||||
|
<ClosingSegment>
|
||||||
|
<Corner CompoundMarkID="5" Rounding="PS"/>
|
||||||
|
</ClosingSegment>
|
||||||
|
</Course>
|
||||||
|
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit Lat="-36.7938" Lng="175.01194"/>
|
||||||
|
<Limit Lat="-36.79411" Lng="175.01555"/>
|
||||||
|
<Limit Lat="-36.79765" Lng="175.01898"/>
|
||||||
|
<Limit Lat="-36.79909" Lng="175.02149"/>
|
||||||
|
<Limit Lat="-36.80163" Lng="175.02014"/>
|
||||||
|
<Limit Lat="-36.80292" Lng="175.0175"/>
|
||||||
|
<Limit Lat="-36.80325" Lng="175.01008"/>
|
||||||
|
<Limit Lat="-36.80107" Lng="175.0089"/>
|
||||||
|
<Limit Lat="-36.79567" Lng="175.00961"/>
|
||||||
|
</CourseLimit>
|
||||||
|
|
||||||
|
</RaceDefinition>
|
||||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<?import java.lang.*?>
|
|
||||||
<?import javafx.geometry.*?>
|
|
||||||
<?import javafx.scene.control.*?>
|
|
||||||
<?import javafx.scene.layout.*?>
|
|
||||||
<?import javafx.scene.text.*?>
|
|
||||||
<?import javafx.geometry.Insets?>
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import javafx.scene.control.Label?>
|
|
||||||
<?import javafx.scene.control.TableColumn?>
|
|
||||||
<?import javafx.scene.control.TableView?>
|
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
|
||||||
<?import javafx.scene.layout.GridPane?>
|
|
||||||
<?import javafx.scene.layout.RowConstraints?>
|
|
||||||
<?import javafx.scene.text.Font?>
|
|
||||||
|
|
||||||
<GridPane fx:id="finishScreenGridPane" maxHeight="837.0" maxWidth="837.0" minHeight="837.0" minWidth="837.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="837.0" prefWidth="837.0" style="-fx-background-color: #2C2c36;" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.FinishScreenViewController">
|
|
||||||
<columnConstraints>
|
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
|
||||||
</columnConstraints>
|
|
||||||
<rowConstraints>
|
|
||||||
<RowConstraints maxHeight="259.0" minHeight="259.0" prefHeight="259.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="64.0" minHeight="64.0" prefHeight="64.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="257.0" minHeight="257.0" prefHeight="257.0" vgrow="SOMETIMES" />
|
|
||||||
<RowConstraints maxHeight="257.0" minHeight="257.0" prefHeight="257.0" vgrow="SOMETIMES" />
|
|
||||||
</rowConstraints>
|
|
||||||
<children>
|
|
||||||
<Label alignment="CENTER" text="Race Finished!" textFill="WHITE" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
|
||||||
<font>
|
|
||||||
<Font size="40.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<Label alignment="CENTER" text="Race Result:" textFill="WHITE" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
|
||||||
<font>
|
|
||||||
<Font size="28.0" />
|
|
||||||
</font>
|
|
||||||
</Label>
|
|
||||||
<TableView fx:id="finishOrderTable" maxWidth="661.0" prefHeight="324.0" prefWidth="629.0" styleClass="ui-table" GridPane.halignment="CENTER" GridPane.rowIndex="2">
|
|
||||||
<columns>
|
|
||||||
<TableColumn fx:id="posCol" editable="false" maxWidth="74.0" minWidth="74.0" prefWidth="74.0" resizable="false" sortable="false" text="Position" />
|
|
||||||
<TableColumn fx:id="boatNameCol" editable="false" maxWidth="171.0" minWidth="171.0" prefWidth="171.0" resizable="false" sortable="false" text="Boat Name" />
|
|
||||||
<TableColumn fx:id="shortNameCol" editable="false" maxWidth="155.18472290039062" minWidth="107.0" prefWidth="155.18472290039062" resizable="false" sortable="false" text="Short Name" />
|
|
||||||
<TableColumn fx:id="countryCol" editable="false" maxWidth="258.9999694824219" minWidth="147.0" prefWidth="258.9999694824219" resizable="false" sortable="false" text="Country" />
|
|
||||||
</columns>
|
|
||||||
<GridPane.margin>
|
|
||||||
<Insets bottom="50.0" />
|
|
||||||
</GridPane.margin>
|
|
||||||
</TableView>
|
|
||||||
<Button mnemonicParsing="false" onAction="#switchToStartScreenView" onMouseEntered="#playButtonHoverSound" styleClass="blue-ui-btn" text="Return to Start Screen" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="TOP" />
|
|
||||||
</children>
|
|
||||||
</GridPane>
|
|
||||||
@@ -66,6 +66,11 @@
|
|||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets right="20.0" top="10.0" />
|
<Insets right="20.0" top="10.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="portNumber" text="Port: 4191" GridPane.columnIndex="2" GridPane.halignment="RIGHT" GridPane.rowIndex="1">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets right="20.0" top="-15.0" />
|
||||||
|
</GridPane.margin>
|
||||||
</Label>
|
</Label>
|
||||||
</children>
|
</children>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
@@ -80,12 +85,9 @@
|
|||||||
</GridPane>
|
</GridPane>
|
||||||
<GridPane GridPane.rowIndex="1">
|
<GridPane GridPane.rowIndex="1">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity"
|
<ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="115.0" />
|
||||||
prefWidth="115.0"/>
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="337.0" prefWidth="430.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"
|
<ColumnConstraints hgrow="NEVER" maxWidth="350.0" minWidth="350.0" prefWidth="350.0" />
|
||||||
minWidth="337.0" prefWidth="430.0"/>
|
|
||||||
<ColumnConstraints hgrow="NEVER" maxWidth="350.0" minWidth="350.0"
|
|
||||||
prefWidth="350.0"/>
|
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints vgrow="SOMETIMES" />
|
<RowConstraints vgrow="SOMETIMES" />
|
||||||
@@ -110,20 +112,16 @@
|
|||||||
<Insets bottom="15.0" left="7.0" right="7.0" top="15.0" />
|
<Insets bottom="15.0" left="7.0" right="7.0" top="15.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<GridPane prefHeight="370.0" prefWidth="189.0" styleClass="tokenGridView"
|
<GridPane prefHeight="370.0" prefWidth="189.0" styleClass="tokenGridView" vgap="5.0">
|
||||||
vgap="5.0">
|
|
||||||
<children>
|
<children>
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Tokens"
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Tokens" GridPane.halignment="CENTER">
|
||||||
GridPane.halignment="CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="18.0" />
|
<Font name="System Bold" size="18.0" />
|
||||||
</font>
|
</font>
|
||||||
</Text>
|
</Text>
|
||||||
<StackPane prefHeight="150.0" prefWidth="200.0"
|
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="1">
|
||||||
GridPane.rowIndex="1">
|
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="BOTTOM_CENTER" text="Speed"
|
<Label alignment="BOTTOM_CENTER" text="Speed" StackPane.alignment="BOTTOM_CENTER">
|
||||||
StackPane.alignment="BOTTOM_CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="12.0" />
|
<Font size="12.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -131,15 +129,12 @@
|
|||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Pane fx:id="speedTokenPane" prefHeight="999.0"
|
<Pane fx:id="speedTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
|
||||||
prefWidth="200.0" styleClass="tokenView"/>
|
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<StackPane prefHeight="150.0" prefWidth="200.0"
|
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="2">
|
||||||
GridPane.rowIndex="2">
|
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="BOTTOM_CENTER" text="Handling"
|
<Label alignment="BOTTOM_CENTER" text="Handling" StackPane.alignment="BOTTOM_CENTER">
|
||||||
StackPane.alignment="BOTTOM_CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="12.0" />
|
<Font size="12.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -147,15 +142,12 @@
|
|||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Pane fx:id="handlingTokenPane" prefHeight="999.0"
|
<Pane fx:id="handlingTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
|
||||||
prefWidth="200.0" styleClass="tokenView"/>
|
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<StackPane prefHeight="150.0" prefWidth="200.0"
|
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="3">
|
||||||
GridPane.rowIndex="3">
|
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="BOTTOM_CENTER" text="Wind Walker"
|
<Label alignment="BOTTOM_CENTER" text="Wind Walker" StackPane.alignment="BOTTOM_CENTER">
|
||||||
StackPane.alignment="BOTTOM_CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="12.0" />
|
<Font size="12.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -163,15 +155,12 @@
|
|||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Pane fx:id="windWalkerTokenPane" prefHeight="999.0"
|
<Pane fx:id="windWalkerTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
|
||||||
prefWidth="200.0" styleClass="tokenView"/>
|
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<StackPane prefHeight="150.0" prefWidth="200.0"
|
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="4">
|
||||||
GridPane.rowIndex="4">
|
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="BOTTOM_CENTER" text="Bumper"
|
<Label alignment="BOTTOM_CENTER" text="Bumper" StackPane.alignment="BOTTOM_CENTER">
|
||||||
StackPane.alignment="BOTTOM_CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="12.0" />
|
<Font size="12.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -179,15 +168,12 @@
|
|||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Pane fx:id="bumperTokenPane" prefHeight="999.0"
|
<Pane fx:id="bumperTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
|
||||||
prefWidth="200.0" styleClass="tokenView"/>
|
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
<StackPane prefHeight="150.0" prefWidth="200.0"
|
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="5">
|
||||||
GridPane.rowIndex="5">
|
|
||||||
<children>
|
<children>
|
||||||
<Label alignment="BOTTOM_CENTER" text="Random"
|
<Label alignment="BOTTOM_CENTER" text="Random" StackPane.alignment="BOTTOM_CENTER">
|
||||||
StackPane.alignment="BOTTOM_CENTER">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="12.0" />
|
<Font size="12.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -195,31 +181,23 @@
|
|||||||
<Insets bottom="5.0" />
|
<Insets bottom="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</Label>
|
</Label>
|
||||||
<Pane fx:id="randomTokenPane" prefHeight="999.0"
|
<Pane fx:id="randomTokenPane" prefHeight="999.0" prefWidth="60.0" styleClass="tokenView" />
|
||||||
prefWidth="60.0" styleClass="tokenView"/>
|
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
</children>
|
</children>
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="80.0"
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="80.0" prefWidth="80.0" />
|
||||||
prefWidth="80.0"/>
|
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="15.0" left="15.0" right="7.0" top="15.0" />
|
<Insets bottom="15.0" left="15.0" right="7.0" top="15.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="116.0" minHeight="0.0" prefHeight="40.0"
|
<RowConstraints maxHeight="116.0" minHeight="0.0" prefHeight="40.0" vgrow="NEVER" />
|
||||||
vgrow="NEVER"/>
|
<RowConstraints maxHeight="285.0" minHeight="-Infinity" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="285.0" minHeight="-Infinity"
|
<RowConstraints maxHeight="285.0" minHeight="-Infinity" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
prefHeight="60.0" vgrow="SOMETIMES"/>
|
<RowConstraints maxHeight="141.0" minHeight="-Infinity" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="285.0" minHeight="-Infinity"
|
<RowConstraints maxHeight="285.0" minHeight="-Infinity" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
prefHeight="60.0" vgrow="SOMETIMES"/>
|
<RowConstraints maxHeight="285.0" minHeight="-Infinity" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="141.0" minHeight="-Infinity"
|
|
||||||
prefHeight="60.0" vgrow="SOMETIMES"/>
|
|
||||||
<RowConstraints maxHeight="285.0" minHeight="-Infinity"
|
|
||||||
prefHeight="60.0" vgrow="SOMETIMES"/>
|
|
||||||
<RowConstraints maxHeight="285.0" minHeight="-Infinity"
|
|
||||||
prefHeight="60.0" vgrow="SOMETIMES"/>
|
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.*?>
|
|
||||||
<?import javafx.scene.shape.*?>
|
|
||||||
<?import com.jfoenix.controls.*?>
|
<?import com.jfoenix.controls.*?>
|
||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
<?import javafx.geometry.*?>
|
<?import javafx.geometry.*?>
|
||||||
@@ -292,6 +290,19 @@
|
|||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
|
<Pane fx:id="miniMapPane" maxHeight="200.0" maxWidth="200.0" minHeight="200.0" minWidth="200.0" prefHeight="200.0" prefWidth="200.0" style="-fx-background-color: white; -fx-opacity: 0.45; -fx-background-radius: 10;" StackPane.alignment="TOP_RIGHT">
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets right="15.0" top="15.0" />
|
||||||
|
</StackPane.margin>
|
||||||
|
</Pane>
|
||||||
|
<JFXButton fx:id="miniMapButton" style="-fx-background-color: white; -fx-opacity: 0.45; -fx-background-radius: 10;" text="—" StackPane.alignment="TOP_RIGHT">
|
||||||
|
<font>
|
||||||
|
<Font size="15.0" />
|
||||||
|
</font>
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets right="15.0" top="15.0" />
|
||||||
|
</StackPane.margin>
|
||||||
|
</JFXButton>
|
||||||
<AnchorPane fx:id="loadingScreenPane">
|
<AnchorPane fx:id="loadingScreenPane">
|
||||||
<ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0" pickOnBounds="true" preserveRatio="true" />
|
<ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0" pickOnBounds="true" preserveRatio="true" />
|
||||||
<JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0" />
|
<JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0" />
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import com.jfoenix.controls.*?>
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import java.net.*?>
|
||||||
|
<?import javafx.geometry.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import com.jfoenix.controls.JFXDialogLayout?>
|
||||||
|
<?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 maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
|
||||||
|
minWidth="-Infinity" prefHeight="273.0" prefWidth="436.0" xmlns="http://javafx.com/javafx/8"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="seng302.visualiser.controllers.dialogs.TokenInfoDialogController">
|
||||||
|
<children>
|
||||||
|
<GridPane>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints maxHeight="40.0" minHeight="30.0" prefHeight="40.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="80.0"
|
||||||
|
prefHeight="115.0" vgrow="SOMETIMES"/>
|
||||||
|
<RowConstraints maxHeight="141.0" minHeight="34.0" prefHeight="73.0"
|
||||||
|
vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<JFXButton fx:id="optionButton" buttonType="RAISED" prefHeight="55.0"
|
||||||
|
prefWidth="150.0" text="Ok" GridPane.halignment="CENTER" GridPane.rowIndex="2"
|
||||||
|
GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets/>
|
||||||
|
</GridPane.margin>
|
||||||
|
</JFXButton>
|
||||||
|
<Label fx:id="headerLabel" text="Popup header" GridPane.halignment="CENTER">
|
||||||
|
<font>
|
||||||
|
<Font size="15.0"/>
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<GridPane GridPane.rowIndex="1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="270.0" minWidth="10.0"
|
||||||
|
prefWidth="270.0"/>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="225.0" minWidth="-Infinity"
|
||||||
|
prefWidth="138.0"/>
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="100.0" vgrow="SOMETIMES"/>
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<Pane fx:id="tokenPane" prefHeight="200.0" prefWidth="200.0"
|
||||||
|
GridPane.columnIndex="1"/>
|
||||||
|
<TextArea fx:id="contentText" nodeOrientation="RIGHT_TO_LEFT"
|
||||||
|
prefHeight="200.0" prefWidth="200.0" promptText="This is some text"
|
||||||
|
stylesheets="@../../css/TokenInfoDialog.css" wrapText="true">
|
||||||
|
<font>
|
||||||
|
<Font size="16.0"/>
|
||||||
|
</font>
|
||||||
|
</TextArea>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
</children>
|
||||||
|
<stylesheets>
|
||||||
|
<URL value="@../../css/dialogs/Popup.css"/>
|
||||||
|
<URL value="@../../css/Master.css"/>
|
||||||
|
</stylesheets>
|
||||||
|
</JFXDialogLayout>
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
|
|
||||||
<?import java.lang.String?>
|
|
||||||
<?import javafx.scene.control.Button?>
|
|
||||||
<?import javafx.scene.control.CheckBox?>
|
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
|
||||||
<?import javafx.scene.text.Font?>
|
|
||||||
<?import javafx.scene.text.Text?>
|
|
||||||
<AnchorPane fx:id="annotationSelectWindow" maxHeight="270.0" maxWidth="469.0" minHeight="270.0" minWidth="469.0" prefHeight="270.0" prefWidth="469.0" styleClass="background-blue" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<children>
|
|
||||||
<Text fill="WHITE" layoutX="26.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Select important annotations">
|
|
||||||
<font>
|
|
||||||
<Font size="24.0" />
|
|
||||||
</font>
|
|
||||||
</Text>
|
|
||||||
<CheckBox fx:id="boatWakeSelect" layoutX="26.0" layoutY="80.0" mnemonicParsing="false" style="-fx-border-width: 0; -fx-background-insets: 0;" text="Boat Wakes" textFill="#e7e7e7" />
|
|
||||||
<CheckBox fx:id="boatSpeedSelect" layoutX="26.0" layoutY="111.0" mnemonicParsing="false" text="Boat Speed" textFill="#e7e7e7" />
|
|
||||||
<CheckBox fx:id="boatTrackSelect" layoutX="26.0" layoutY="142.0" mnemonicParsing="false" text="Boat Tracks" textFill="#e7e7e7" />
|
|
||||||
<CheckBox fx:id="boatNameSelect" layoutX="26.0" layoutY="173.0" mnemonicParsing="false" text="Boat Name" textFill="#e7e7e7" />
|
|
||||||
<CheckBox fx:id="boatEstTimeToNextMarkSelect" layoutX="26.0" layoutY="204.0" mnemonicParsing="false" text="Boat Estimated Time To Next Mark" textFill="#e7e7e7" />
|
|
||||||
<Button fx:id="closeButton" layoutX="424.0" layoutY="-1.0" mnemonicParsing="false" prefHeight="11.0" prefWidth="49.0" style=": 0;" text="X" textFill="#ffffff4e">
|
|
||||||
<font>
|
|
||||||
<Font size="24.0" />
|
|
||||||
</font>
|
|
||||||
<styleClass>
|
|
||||||
<String fx:value="background-blue" />
|
|
||||||
<String fx:value="clearExitButton" />
|
|
||||||
</styleClass>
|
|
||||||
</Button>
|
|
||||||
<CheckBox fx:id="boatElapsedTimeSelect" layoutX="26.0" layoutY="235.0" mnemonicParsing="false" text="Boat Elapsed Time Since Last Mark" textFill="#e7e7e7" />
|
|
||||||
</children>
|
|
||||||
</AnchorPane>
|
|
||||||
@@ -48,9 +48,10 @@ public class ServerTableTest {
|
|||||||
|
|
||||||
serverTable.addServer(listing);
|
serverTable.addServer(listing);
|
||||||
|
|
||||||
|
listing.decrementTtl();
|
||||||
listing.decrementTtl();
|
listing.decrementTtl();
|
||||||
|
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1500);
|
||||||
|
|
||||||
assertTrue(!serverTable.getAllServers().contains(listing));
|
assertTrue(!serverTable.getAllServers().contains(listing));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package seng302.utilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by cir27 on 28/09/17.
|
||||||
|
*/
|
||||||
|
public class MapMakerTest {
|
||||||
|
// @Test
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,7 +12,7 @@ public class DisconnectionTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testServerDisconnection () throws Exception {
|
public void testServerDisconnection () throws Exception {
|
||||||
MainServerThread serverThread = new MainServerThread();
|
MainServerThread serverThread = new MainServerThread();
|
||||||
ClientToServerThread clientThread = new ClientToServerThread("localhost", 4942);
|
ClientToServerThread clientThread = new ClientToServerThread("localhost", serverThread.getPortNumber());
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
clientThread.addDisconnectionListener(message -> Assert.assertTrue(message != null));
|
clientThread.addDisconnectionListener(message -> Assert.assertTrue(message != null));
|
||||||
serverThread.terminate();
|
serverThread.terminate();
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class RegularPacketsTest {
|
|||||||
public void setup() throws Exception {
|
public void setup() throws Exception {
|
||||||
new GameState();
|
new GameState();
|
||||||
serverThread = new MainServerThread();
|
serverThread = new MainServerThread();
|
||||||
clientThread = new ClientToServerThread("localhost", 4942);
|
clientThread = new ClientToServerThread("localhost", serverThread.getPortNumber());
|
||||||
GameState.setCurrentStage(GameStages.RACING);
|
GameState.setCurrentStage(GameStages.RACING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
package seng302.visualiser.map;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import seng302.model.GeoPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit test for Mercator Project class.
|
|
||||||
* Created by hyi25 on 15/05/17.
|
|
||||||
*/
|
|
||||||
public class MercatorProjectionTest {
|
|
||||||
@Test
|
|
||||||
public void toMapPoint() throws Exception {
|
|
||||||
GeoPoint geo1 = new GeoPoint(12.485394, 19.38947);
|
|
||||||
javafx.geometry.Point2D actualPoint1 = MercatorProjection.toMapPoint(geo1);
|
|
||||||
javafx.geometry.Point2D expectedPoint1 = new javafx.geometry.Point2D(141.78806755555556, 119.0503853635612);
|
|
||||||
assertEquals(expectedPoint1.getX(), actualPoint1.getX(), 0.0001);
|
|
||||||
assertEquals(expectedPoint1.getY(), actualPoint1.getY(), 0.0001);
|
|
||||||
|
|
||||||
GeoPoint geo2 = new GeoPoint(77.456432, -23.456462);
|
|
||||||
javafx.geometry.Point2D actualPoint2 = MercatorProjection.toMapPoint(geo2);
|
|
||||||
javafx.geometry.Point2D expectedPoint2 = new javafx.geometry.Point2D(111.31984924444444, 38.03143323746788);
|
|
||||||
assertEquals(expectedPoint2.getX(), actualPoint2.getX(), 0.0001);
|
|
||||||
assertEquals(expectedPoint2.getY(), actualPoint2.getY(), 0.0001);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void toMapGeo() throws Exception {
|
|
||||||
javafx.geometry.Point2D point1 = new javafx.geometry.Point2D(123.1234, 25.4565);
|
|
||||||
GeoPoint actualGeo1 = MercatorProjection.toMapGeo(point1);
|
|
||||||
GeoPoint expectedGeo1 = new GeoPoint(80.77043127275441, -6.857718749999995);
|
|
||||||
assertEquals(expectedGeo1.getLat(), actualGeo1.getLat(), 0.0001);
|
|
||||||
assertEquals(expectedGeo1.getLng(), actualGeo1.getLng(), 0.0001);
|
|
||||||
|
|
||||||
javafx.geometry.Point2D point2 = new javafx.geometry.Point2D(1.235, 255.4565);
|
|
||||||
GeoPoint actualGeo2 = MercatorProjection.toMapGeo(point2);
|
|
||||||
GeoPoint expectedGeo2 = new GeoPoint(-84.98475532898011, -178.26328125);
|
|
||||||
assertEquals(expectedGeo2.getLat(), actualGeo2.getLat(), 0.0001);
|
|
||||||
assertEquals(expectedGeo2.getLng(), actualGeo2.getLng(), 0.0001);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,9 @@ package steps;
|
|||||||
import cucumber.api.java.en.Given;
|
import cucumber.api.java.en.Given;
|
||||||
import cucumber.api.java.en.Then;
|
import cucumber.api.java.en.Then;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import seng302.visualiser.MapMaker;
|
import seng302.visualiser.MapMaker;
|
||||||
|
|
||||||
@@ -16,26 +19,26 @@ public class CustomMapsSteps {
|
|||||||
|
|
||||||
@Given("^that the game has multiple race xml files$")
|
@Given("^that the game has multiple race xml files$")
|
||||||
public void that_the_game_has_multiple_race_xml_files() throws Throwable {
|
public void that_the_game_has_multiple_race_xml_files() throws Throwable {
|
||||||
// mapMaker = MapMaker.getInstance();
|
mapMaker = MapMaker.getInstance();
|
||||||
// String firstMap = mapMaker.getCurrentRacePath();
|
String firstMap = mapMaker.getCurrentRacePath();
|
||||||
// int numMaps = 0;
|
int numMaps = 0;
|
||||||
// do {
|
do {
|
||||||
// mapMaker.next();
|
mapMaker.next();
|
||||||
// numMaps++;
|
numMaps++;
|
||||||
// } while (!mapMaker.getCurrentRacePath().equals(firstMap));
|
} while (!mapMaker.getCurrentRacePath().equals(firstMap));
|
||||||
// Assert.assertTrue(numMaps >= 2);
|
Assert.assertTrue(numMaps >= 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Then("^all of them can be seen$")
|
@Then("^all of them can be seen$")
|
||||||
public void all_of_them_can_be_seen() throws Throwable {
|
public void all_of_them_can_be_seen() throws Throwable {
|
||||||
// File[] files = new File(this.getClass().getResource("/maps/").getPath()).listFiles();
|
File[] files = new File(this.getClass().getResource("/maps/").getPath()).listFiles();
|
||||||
// for (File file : files) {
|
Arrays.sort(files);
|
||||||
// if (file.isFile()) {
|
for (File file : files) {
|
||||||
// Assert.assertTrue(file.getAbsolutePath().equals(mapMaker.getCurrentRacePath()));
|
if (file.isFile()) {
|
||||||
// mapMaker.next();
|
Assert.assertTrue(file.getAbsolutePath().endsWith(mapMaker.getCurrentRacePath()));
|
||||||
// System.out.println(file.getAbsolutePath());
|
mapMaker.next();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Given("^that I choose a race$")
|
@Given("^that I choose a race$")
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class SendChatSteps {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
host = new ClientToServerThread("localhost", 4942);
|
host = new ClientToServerThread("localhost", mst.getPortNumber());
|
||||||
host.addStreamObserver(() -> {
|
host.addStreamObserver(() -> {
|
||||||
while (host.getPacketQueue().peek() != null) {
|
while (host.getPacketQueue().peek() != null) {
|
||||||
StreamPacket packet = host.getPacketQueue().poll();
|
StreamPacket packet = host.getPacketQueue().poll();
|
||||||
@@ -68,7 +68,7 @@ public class SendChatSteps {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
client = new ClientToServerThread("localhost", 4942);
|
client = new ClientToServerThread("localhost", mst.getPortNumber());
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class ToggleSailSteps {
|
|||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
client = new ClientToServerThread("localhost", 4942);
|
client = new ClientToServerThread("localhost", mst.getPortNumber());
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(100);
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
|
|||||||
Reference in New Issue
Block a user