Compare commits

...

48 Commits

Author SHA1 Message Date
William Muir 057af2799a Added toggle button css settings
#story[1274]
2017-09-28 16:47:55 +13:00
Zhi You Tan 45669c333a Merge remote-tracking branch 'origin/develop' into wind_arrow
# Conflicts:
#	src/main/resources/css/RaceView.css
#	src/main/resources/views/RaceView.fxml
2017-09-28 16:43:38 +13:00
Zhi You Tan f7fd5494ef merged Dev in
Fixed concurrency exception

#story[1276] #pair[zyt10, ajm412]
2017-09-28 16:40:50 +13:00
William Muir a1d468c689 Added toggle button for the chat history
#story[1274]
2017-09-28 16:39:59 +13:00
Zhi You Tan 6fafb02a8f Merge branch 'develop' into wind_arrow
# Conflicts:
#	src/main/java/seng302/visualiser/controllers/RaceViewController.java
#	src/main/resources/views/RaceView.fxml
2017-09-28 16:36:34 +13:00
Haoming Yin 4f80640718 Polished raceview UI elements
- changed javaFx css style into Css file

tags: #story[1273]
2017-09-28 16:33:16 +13:00
Zhi You Tan d436d2a6e4 Wind arrow now follows on every camera
Follows correctly

#story[1276] #pair[zyt10, ajm412]
2017-09-28 16:31:10 +13:00
Kusal Ekanayake 27379ae96d Fixed fatal bug to do with mark arrow on boat. 2017-09-28 16:27:57 +13:00
Kusal Ekanayake ce3e08abfc Changed minimise and maximise icons for minimap 2017-09-28 16:18:44 +13:00
Calum 923c381797 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 16:17:27 +13:00
Calum ece45ff967 Fixed map, parrot and camera. 2017-09-28 16:17:19 +13:00
William Muir 02dc1dbd3d Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 16:04:29 +13:00
Michael Rausch d9b9c2f808 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 16:04:07 +13:00
William Muir 4e3de02a93 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 16:04:04 +13:00
Michael Rausch 261f68f143 Added port number randomization
- Servers all run on different ports, so multiple servers can run on one host
- Port is displayed in lobby

Tags: #story[1281]
2017-09-28 16:03:59 +13:00
William Muir ed9b7acc62 New Map! Waiheke
#story[1274]
2017-09-28 16:03:56 +13:00
Michael Rausch 74c1219e0d Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	src/main/java/seng302/gameServer/MainServerThread.java
#	src/main/java/seng302/visualiser/GameClient.java
#	src/main/java/seng302/visualiser/controllers/dialogs/ServerCreationController.java
2017-09-28 16:02:04 +13:00
Calum 83218ae0a0 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 16:01:32 +13:00
Calum 0231c43a2c Arrows work. mark arrow thinner. refactored marker class.
#fix
2017-09-28 16:01:24 +13:00
Michael Rausch a05a41d5ec Added port number randomization
- Servers all run on different ports, so multiple servers can run on one host
- Port is displayed in lobby

Tags: #story[1281]
2017-09-28 15:57:59 +13:00
Haoming Yin 06bc3644bc Removed dead code in MeesageFactory and redundant classes
tags: #story[1273]
2017-09-28 15:54:09 +13:00
Haoming Yin 7620f0023e Removed dead code in MainServerThread
tags: #story[1273]
2017-09-28 15:43:35 +13:00
Kusal Ekanayake 77ee1ebbc0 Fixed faulty tests. 2017-09-28 15:35:58 +13:00
William Muir 6d0835b0cf Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	src/main/java/seng302/visualiser/controllers/RaceViewController.java
2017-09-28 15:29:00 +13:00
William Muir 54410efa12 Changed garbage collection to once every second, Changed wind walker icon to white
#story[1273]
2017-09-28 15:24:45 +13:00
William Muir 74241ee819 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 15:23:50 +13:00
Kusal Ekanayake a9ce8901f5 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 15:17:06 +13:00
Michael Rausch 8810554ce9 Fixed bug where server wasn't being unregistered from discovery server
- Added missing unregister() method call

Tags: #story[1281]
2017-09-28 15:16:37 +13:00
Kusal Ekanayake 7e3ed872ed Merge remote-tracking branch 'origin/develop' into develop
# Conflicts:
#	src/main/java/seng302/visualiser/ClientToServerThread.java
2017-09-28 15:08:53 +13:00
Kusal Ekanayake 21ce34dda2 Fixed finish screen and cleaned up dead code 2017-09-28 15:08:34 +13:00
William Muir 2bf318a122 Merge branch 'story1273_minimap' into develop 2017-09-28 15:08:32 +13:00
Michael Rausch e56d284792 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 15:00:24 +13:00
Michael Rausch 80c26a9e4a Fixed bug where server could connect to an expired server
- Increased update interval

Tags: #story[1281]
2017-09-28 15:00:00 +13:00
Calum c4a3df32c8 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 14:47:00 +13:00
Calum 1e19dd5ab6 Fixed parrot again. 2017-09-28 14:46:55 +13:00
Alistair McIntyre 1aedcaddf5 removed an added print statement
tags : #story[1275]
2017-09-28 14:42:34 +13:00
Alistair McIntyre d7fc339ad5 - Added Madagascar Map
tags : #story[1275]
2017-09-28 14:41:35 +13:00
Zhi You Tan 51078c82a0 Merge remote-tracking branch 'origin/develop' into wind_arrow
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelType.java
2017-09-28 14:38:31 +13:00
Zhi You Tan 22fbb529ef Wind arrow follows wind data
#story[1276]
2017-09-28 14:37:46 +13:00
Kusal Ekanayake 02aabc3162 Removing dead code in race view controller and fixed mark rounding bug 2017-09-28 14:35:40 +13:00
Alistair McIntyre d2a05de25a Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 14:34:39 +13:00
Zhi You Tan d3e8a21d2f Made the windView observer the gameView camera
#story[1276] #pair[ajm412, zyt10]
2017-09-28 13:18:19 +13:00
Alistair McIntyre c72c4929ff Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 12:15:44 +13:00
Alistair McIntyre 265b20ad61 - Created Madagascar Map Initial
tags : #story[1275]
2017-09-28 12:12:22 +13:00
Zhi You Tan 852575c9e7 Merge remote-tracking branch 'origin/develop' into wind_arrow
# Conflicts:
#	src/main/java/seng302/visualiser/controllers/RaceViewController.java
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelType.java
#	src/main/resources/views/RaceView.fxml
2017-09-28 11:57:12 +13:00
Zhi You Tan 567e351c7f Updated wind arrow 3D model
#story[1276]
2017-09-28 11:02:47 +13:00
Zhi You Tan 72fe8c4881 - Removed 2D wind and replaced with 3D wind arrow.
#story[1276]
2017-09-28 04:13:44 +13:00
Zhi You Tan 270326ea77 Created prototype compass arrow mesh
#story[1276]
2017-09-27 16:03:59 +13:00
72 changed files with 1913 additions and 1542 deletions
+1 -2
View File
@@ -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 = "";
@@ -11,6 +11,7 @@ import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -68,7 +69,7 @@ public class GameState implements Runnable {
//Collision constants //Collision constants
private static final Double MARK_COLLISION_DISTANCE = 15d; private static final Double MARK_COLLISION_DISTANCE = 15d;
public static final Double YACHT_COLLISION_DISTANCE = 25.0; public static final Double YACHT_COLLISION_DISTANCE = 15.0;
private static final Double BOUNCE_DISTANCE_MARK = 20.0; private static final Double BOUNCE_DISTANCE_MARK = 20.0;
public static final Double BOUNCE_DISTANCE_YACHT = 30.0; public static final Double BOUNCE_DISTANCE_YACHT = 30.0;
private static final Double COLLISION_VELOCITY_PENALTY = 0.3; private static final Double COLLISION_VELOCITY_PENALTY = 0.3;
@@ -82,6 +83,7 @@ public class GameState implements Runnable {
private static Long previousUpdateTime; private static Long previousUpdateTime;
public static Double windDirection; public static Double windDirection;
public static ReadOnlyDoubleWrapper windDirectionProperty = new ReadOnlyDoubleWrapper();
private static Double windSpeed; private static Double windSpeed;
private static Double serverSpeedMultiplier; private static Double serverSpeedMultiplier;
@@ -108,6 +110,7 @@ public class GameState implements Runnable {
public GameState() { public GameState() {
windDirection = 180d; windDirection = 180d;
windDirectionProperty.set(windDirection);
windSpeed = 10000d; windSpeed = 10000d;
yachts = new HashMap<>(); yachts = new HashMap<>();
tokensInPlay = new ArrayList<>(); tokensInPlay = new ArrayList<>();
@@ -191,6 +194,7 @@ public class GameState implements Runnable {
public static void setWindDirection(Double newWindDirection) { public static void setWindDirection(Double newWindDirection) {
windDirection = newWindDirection; windDirection = newWindDirection;
windDirectionProperty.set(newWindDirection);
} }
public static void setWindSpeed(Double newWindSpeed) { public static void setWindSpeed(Double newWindSpeed) {
@@ -509,6 +513,7 @@ public class GameState implements Runnable {
Double optimalAngle = PolarTable.getOptimalAngle(); Double optimalAngle = PolarTable.getOptimalAngle();
Double heading = yacht.getHeading(); Double heading = yacht.getHeading();
windDirection = (double) Math.floorMod(Math.round(heading + optimalAngle), 360L); windDirection = (double) Math.floorMod(Math.round(heading + optimalAngle), 360L);
windDirectionProperty.set(windDirection);
} }
@@ -1058,4 +1063,8 @@ public class GameState implements Runnable {
public static void setTokensEnabled (boolean tokensEnabled) { public static void setTokensEnabled (boolean tokensEnabled) {
GameState.tokensEnabled = tokensEnabled; GameState.tokensEnabled = tokensEnabled;
} }
public static ReadOnlyDoubleWrapper getWindDirectionProperty() {
return windDirectionProperty;
}
} }
@@ -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);
@@ -149,7 +141,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
} }
} }
try { try {
synchronized (this){ synchronized (this) {
for (ServerToClientThread serverToClientThread : serverToClientThreads) { for (ServerToClientThread serverToClientThread : serverToClientThreads) {
serverToClientThread.terminate(); serverToClientThread.terminate();
} }
@@ -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 {
@@ -216,7 +207,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
logger.warn("Couldn't update advertisement"); logger.warn("Couldn't update advertisement");
} }
while (regattaXMLData == null && raceXMLData == null){ while (regattaXMLData == null && raceXMLData == null) {
try { try {
Thread.sleep(50); Thread.sleep(50);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@@ -242,7 +233,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
for (ServerToClientThread serverToClientThread : serverToClientThreads) { for (ServerToClientThread serverToClientThread : serverToClientThreads) {
if (serverToClientThread.getSocket() == player.getSocket()) { if (serverToClientThread.getSocket() == player.getSocket()) {
closedConnection = serverToClientThread; closedConnection = serverToClientThread;
} else if (GameState.getCurrentStage() != GameStages.RACING){ } else if (GameState.getCurrentStage() != GameStages.RACING) {
serverToClientThread.sendSetupMessages(); serverToClientThread.sendSetupMessages();
} }
} }
@@ -255,7 +246,9 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
logger.warn("Couldn't update advertisement"); logger.warn("Couldn't update advertisement");
} }
closedConnection.terminate(); if (closedConnection != null) {
closedConnection.terminate();
}
} }
public void startGame() { public void startGame() {
@@ -273,16 +266,12 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
public void run() { public void run() {
broadcastMessage(MessageFactory.getRaceStatusMessage()); broadcastMessage(MessageFactory.getRaceStatusMessage());
if (GameState.getCurrentStage() == GameStages.PRE_RACE if (GameState.getCurrentStage() == GameStages.PRE_RACE
|| GameState.getCurrentStage() == GameStages.LOBBYING) { || GameState.getCurrentStage() == GameStages.LOBBYING) {
broadcastMessage(MessageFactory.getRaceStartStatusMessage()); broadcastMessage(MessageFactory.getRaceStartStatusMessage());
} }
} }
}, 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,14 +321,16 @@ 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(
startingPoint, startMarkToMarkAngle + 180, yachtSpace startingPoint, startMarkToMarkAngle + 180, yachtSpace
); );
for (int i=0; i<numYachtsInLine; i++){ for (int i = 0; i < numYachtsInLine; i++) {
randomisedYachts.get(0).setHeading(angleFromStart); randomisedYachts.get(0).setHeading(angleFromStart);
randomisedYachts.get(0).setLocation(firstYachtPoint); randomisedYachts.get(0).setLocation(firstYachtPoint);
firstYachtPoint = GeoUtility.getGeoCoordinate( 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();
} }
/** /**
+1 -4
View File
@@ -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();
} }
@@ -134,4 +134,8 @@ public class RaceState {
public Boolean getRaceFinished() { public Boolean getRaceFinished() {
return raceFinished; return raceFinished;
} }
public ReadOnlyDoubleWrapper getWindDirection() {
return windDirection;
}
} }
@@ -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;
@@ -55,7 +52,6 @@ import seng302.visualiser.controllers.dialogs.PopupDialogController;
*/ */
public class GameClient { public class GameClient {
private Pane holderPane;
private ClientToServerThread socketThread; private ClientToServerThread socketThread;
private MainServerThread server; private MainServerThread server;
@@ -77,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();
} }
@@ -89,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) -> {
@@ -100,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);
@@ -150,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");
} }
@@ -184,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() {
@@ -288,10 +284,12 @@ public class GameClient {
case CHATTER_TEXT: case CHATTER_TEXT:
Pair<Integer, String> playerIdMessagePair = StreamParser Pair<Integer, String> playerIdMessagePair = StreamParser
.extractChatterText(packet); .extractChatterText(packet);
raceView.updateChatHistory( if (playerIdMessagePair != null) {
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(), raceView.updateChatHistory(
playerIdMessagePair.getValue() allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
); playerIdMessagePair.getValue()
);
}
} }
} }
} }
@@ -328,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());
} }
} }
@@ -367,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();
} }
} }
@@ -392,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
@@ -522,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();
@@ -81,6 +75,7 @@ public class GameView3D extends GameView {
private Double windDir; private Double windDir;
private Skybox skybox; private Skybox skybox;
public GameView3D () { public GameView3D () {
isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y); isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y);
topDownCam = new TopDownCamera(); topDownCam = new TopDownCamera();
@@ -95,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));
@@ -350,18 +345,19 @@ 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();
Point2D midPoint = new Point2D(0, 0);
if (marks.size() == 1) {
midPoint = scaledPoint.findScaledXY(marks.get(0));
} else if (marks.size() == 2) {
midPoint = (scaledPoint.findScaledXY(marks.get(0)))
.midpoint(scaledPoint.findScaledXY(marks.get(1)));
}
List<Mark> marks = course.get(playerYacht.getLegNumber()).getMarks(); if (midPoint != null) {
Point2D midPoint = new Point2D(0, 0); playerBoat.updateMarkIndicator(midPoint);
if (marks.size() == 1) { }
midPoint = scaledPoint.findScaledXY(marks.get(0));
} else if (marks.size() == 2) {
midPoint = (scaledPoint.findScaledXY(marks.get(0)))
.midpoint(scaledPoint.findScaledXY(marks.get(1)));
}
if (midPoint != null) {
playerBoat.updateMarkIndicator(midPoint);
} }
}); });
@@ -375,6 +371,10 @@ public class GameView3D extends GameView {
return view; return view;
} }
public SubScene getView() {
return view;
}
/** /**
* Updates the boatObjects color with that of the clientYachts object. Used in notification from * Updates the boatObjects color with that of the clientYachts object. Used in notification from
* a listener on this attribute in clientYacht to re paint the boat mesh * a listener on this attribute in clientYacht to re paint the boat mesh
@@ -501,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() {
@@ -534,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();
protected 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()
@@ -11,8 +11,6 @@ import seng302.model.ClientYacht;
import seng302.model.Limit; import seng302.model.Limit;
import seng302.model.mark.CompoundMark; import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner; import seng302.model.mark.Corner;
import seng302.model.mark.Mark;
import seng302.utilities.Sounds;
/** /**
* Class converts a map preview to a minimap by adding boats. * Class converts a map preview to a minimap by adding boats.
@@ -20,15 +18,9 @@ import seng302.utilities.Sounds;
public class MiniMap extends MapPreview { public class MiniMap extends MapPreview {
private HashMap<ClientYacht, Polygon> boatIcons = new HashMap<>(); private HashMap<ClientYacht, Polygon> boatIcons = new HashMap<>();
private Polygon playerBoat;
private double playerRotation;
private List<ClientYacht> boats;
private ClientYacht player;
public MiniMap (List<CompoundMark> marks, List<Corner> course, List<Limit> border, List<ClientYacht> boats, ClientYacht player) { public MiniMap (List<CompoundMark> marks, List<Corner> course, List<Limit> border, List<ClientYacht> boats, ClientYacht player) {
super(marks, course, border); super(marks, course, border);
this.boats = boats;
this.player = player;
setBoats(boats); setBoats(boats);
player.addMarkRoundingListener(this::updateMarkArrows); player.addMarkRoundingListener(this::updateMarkArrows);
} }
@@ -56,31 +48,4 @@ public class MiniMap extends MapPreview {
gameObjects.getChildren().addAll(boatIcons.values()); gameObjects.getChildren().addAll(boatIcons.values());
}); });
} }
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,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);
}
} }
@@ -7,28 +7,33 @@ import java.util.ArrayList;
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 javafx.animation.RotateTransition;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.SubScene; import javafx.scene.SubScene;
import javafx.scene.control.Button;
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.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.Paint; import javafx.scene.paint.Paint;
import javafx.util.Duration; import javafx.scene.text.Text;
import seng302.model.ClientYacht; import seng302.model.ClientYacht;
import seng302.model.RaceState; import seng302.model.RaceState;
import seng302.model.mark.CompoundMark;
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;
import seng302.visualiser.GameView3D; import seng302.visualiser.GameView3D;
import seng302.visualiser.MiniMap; import seng302.visualiser.MiniMap;
import seng302.visualiser.controllers.cells.WindCell;
import seng302.visualiser.controllers.dialogs.FinishDialogController; import seng302.visualiser.controllers.dialogs.FinishDialogController;
import seng302.visualiser.fxObjects.ChatHistory; import seng302.visualiser.fxObjects.ChatHistory;
@@ -50,6 +55,8 @@ public class RaceViewController extends Thread {
@FXML @FXML
private Pane chatHistoryHolder; private Pane chatHistoryHolder;
@FXML @FXML
private JFXButton chatToggleButton;
@FXML
private TextField chatInput; private TextField chatInput;
@FXML @FXML
private Label timerLabel; private Label timerLabel;
@@ -59,6 +66,20 @@ public class RaceViewController extends Thread {
private Pane miniMapPane; private Pane miniMapPane;
@FXML @FXML
private ImageView windImageView; private ImageView windImageView;
@FXML
private AnchorPane rvAnchorPane;
@FXML
private AnchorPane windArrowHolder;
@FXML
private Slider annotationSlider;
@FXML
private Button selectAnnotationBtn;
@FXML
private ComboBox<ClientYacht> yachtSelectionComboBox;
@FXML
private Text fpsDisplay;
// @FXML
// private ImageView windImageView;
@FXML @FXML
private Label windDirectionLabel; private Label windDirectionLabel;
@FXML @FXML
@@ -68,12 +89,20 @@ public class RaceViewController extends Thread {
@FXML @FXML
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon; private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
@FXML @FXML
private VBox windArrowVBox;
@FXML
private JFXButton miniMapButton; private JFXButton miniMapButton;
private WindCell windCell;
//Race Data
private Map<Integer, ClientYacht> participants;
private Map<Integer, CompoundMark> markers;
private RaceXMLData courseData;
private GameView3D gameView; private GameView3D gameView;
private RaceState raceState; private RaceState raceState;
private ChatHistory chatHistory; private ChatHistory chatHistory;
private Timer timer = new Timer(); private Timer timer = new Timer();
private ClientYacht player; private ClientYacht player;
private JFXDialog finishScreenDialog; private JFXDialog finishScreenDialog;
private FinishDialogController finishDialogController; private FinishDialogController finishDialogController;
@@ -85,6 +114,8 @@ public class RaceViewController extends Thread {
public void initialize() { public void initialize() {
miniMapPane.setVisible(false); miniMapPane.setVisible(false);
miniMapButton.setVisible(false); miniMapButton.setVisible(false);
chatHistoryHolder.setVisible(false);
chatToggleButton.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);
@@ -120,6 +151,9 @@ public class RaceViewController extends Thread {
chatHistoryHolder.heightProperty() chatHistoryHolder.heightProperty()
); );
contentStackPane.getChildren().remove(chatToggleButton);
contentStackPane.getChildren().add(chatToggleButton);
contentStackPane.setOnMouseClicked(event -> { contentStackPane.setOnMouseClicked(event -> {
contentStackPane.requestFocus(); contentStackPane.requestFocus();
}); });
@@ -134,6 +168,30 @@ public class RaceViewController extends Thread {
}); });
lastWindDirection = 0d; lastWindDirection = 0d;
}
/**
* Initialise wind arrow cell.
*/
private void initialiseWindArrow() {
FXMLLoader loader = new FXMLLoader(
getClass().getResource("/views/cells/WindCell.fxml"));
windCell = new WindCell();
loader.setController(windCell);
try {
loader.load();
} catch (IOException e) {
e.printStackTrace();
}
windCell.init(player, raceState.getWindDirection());
windCell.setCamera(gameView.getView().getCamera());
gameView.getView().cameraProperty()
.addListener((obs, oldVal, newVal) -> windCell.setCamera(newVal));
windArrowVBox.getChildren().add(windCell.getAssets());
} }
public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) { public void showFinishDialog(ArrayList<ClientYacht> finishedBoats) {
@@ -146,12 +204,10 @@ public class RaceViewController extends Thread {
contentStackPane.setVisible(true); contentStackPane.setVisible(true);
miniMapPane.setVisible(true); miniMapPane.setVisible(true);
miniMapButton.setVisible(true); miniMapButton.setVisible(true);
Platform.runLater(new Runnable() { chatHistoryHolder.setVisible(true);
@Override chatToggleButton.setVisible(true);
public void run() {
contentStackPane.requestFocus(); Platform.runLater(() -> contentStackPane.requestFocus());
}
});
} }
/** /**
@@ -195,10 +251,20 @@ public class RaceViewController extends Thread {
miniMapButton.setOnMouseClicked((event) -> { miniMapButton.setOnMouseClicked((event) -> {
if (miniMapPane.visibleProperty().get()) { if (miniMapPane.visibleProperty().get()) {
miniMapPane.setVisible(false); miniMapPane.setVisible(false);
miniMapButton.setText(""); miniMapButton.setText("+");
} else { } else {
miniMapPane.setVisible(true); miniMapPane.setVisible(true);
miniMapButton.setText(""); miniMapButton.setText("");
}
});
chatToggleButton.setOnMouseClicked((event) -> {
if (chatHistoryHolder.visibleProperty().get()) {
chatHistoryHolder.setVisible(false);
chatToggleButton.setText("+");
} else {
chatHistoryHolder.setVisible(true);
chatToggleButton.setText("");
} }
}); });
@@ -233,6 +299,12 @@ public class RaceViewController extends Thread {
}); });
gameView.setWindDir(raceState.windDirectionProperty().doubleValue()); gameView.setWindDir(raceState.windDirectionProperty().doubleValue());
Platform.runLater(this::initializeUpdateTimer); Platform.runLater(this::initializeUpdateTimer);
Platform.runLater(() -> {
//windCell.setCamera(gameView.getView().getCamera());
initialiseWindArrow();
});
} }
/** /**
@@ -288,7 +360,7 @@ public class RaceViewController extends Thread {
} }
} }
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);
@@ -319,12 +391,12 @@ public class RaceViewController extends Thread {
*/ */
private void updateWindDirection(double direction) { private void updateWindDirection(double direction) {
windDirectionLabel.setText(String.format("%.1f°", direction)); windDirectionLabel.setText(String.format("%.1f°", direction));
RotateTransition rt = new RotateTransition(Duration.millis(300), windImageView); // RotateTransition rt = new RotateTransition(Duration.millis(300), windImageView);
rt.setByAngle(direction - lastWindDirection); // rt.setByAngle(direction - lastWindDirection);
rt.setCycleCount(3); // rt.setCycleCount(3);
rt.setAutoReverse(true); // rt.setAutoReverse(true);
rt.play(); // rt.play();
lastWindDirection = direction; // lastWindDirection = direction;
// windImageView.setRotate(direction); // windImageView.setRotate(direction);
} }
@@ -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,17 +27,14 @@ 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 try {
public void run() { Stage stage = new Stage();
try { ViewManager.getInstance().initialStartView(stage);
Stage stage = new Stage(); } catch (Exception e) {
ViewManager.getInstance().initialStartView(stage); e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
rootPane.getScene().getWindow().hide();
} }
rootPane.getScene().getWindow().hide();
}); });
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
@@ -6,10 +6,16 @@ import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialog.DialogTransition; import com.jfoenix.controls.JFXDialog.DialogTransition;
import com.jfoenix.controls.JFXSnackbar; import com.jfoenix.controls.JFXSnackbar;
import com.jfoenix.svg.SVGGlyph; import com.jfoenix.svg.SVGGlyph;
import java.io.IOException;
import java.util.HashMap;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.*; import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
@@ -24,9 +30,6 @@ import seng302.visualiser.GameClient;
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController; import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
import seng302.visualiser.controllers.dialogs.PopupDialogController; import seng302.visualiser.controllers.dialogs.PopupDialogController;
import java.io.IOException;
import java.util.HashMap;
public class ViewManager { public class ViewManager {
private static ViewManager instance; private static ViewManager instance;
@@ -79,7 +82,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")));
@@ -376,8 +379,8 @@ public class ViewManager {
scene.setOnKeyPressed(gameClient::keyPressed); scene.setOnKeyPressed(gameClient::keyPressed);
scene.setOnKeyReleased(gameClient::keyReleased); scene.setOnKeyReleased(gameClient::keyReleased);
stage.setMinHeight(500); stage.setMinHeight(800);
stage.setMinWidth(800); stage.setMinWidth(1200);
stage.setTitle("Party Parrots At Sea"); stage.setTitle("Party Parrots At Sea");
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png"))); stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
stage.setOnCloseRequest(e -> closeAll()); stage.setOnCloseRequest(e -> closeAll());
@@ -0,0 +1,131 @@
package seng302.visualiser.controllers.cells;
import java.util.Arrays;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.fxml.FXML;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PerspectiveCamera;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate;
import seng302.model.ClientYacht;
import seng302.visualiser.cameras.ChaseCamera;
import seng302.visualiser.fxObjects.assets_3D.Model;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
public class WindCell {
//--------FXML BEGIN--------//
@FXML
private Pane windPane;
//---------FXML END---------//
private final double FOV = 60;
private final double DEFAULT_CAMERA_X = 0;
private final double DEFAULT_CAMERA_Y = 50;
private Group root3D;
private SubScene view;
private Group gameObjects;
private ChaseCamera chaseCam;
private ClientYacht playerYacht;
// Cameras
private PerspectiveCamera camera = null;
private Model windArrowModel;
private Boolean isChaseCam;
/**
* Initialise WindCell fxml and load 3D wind arrow into a group.
*/
public void init(ClientYacht playerYacht, ReadOnlyDoubleWrapper windDirection) {
this.playerYacht = playerYacht;
camera = new PerspectiveCamera();
camera.setFarClip(1000);
camera.setNearClip(0.1);
camera.setFieldOfView(60);
initialiseWindView();
for (DoubleProperty o : Arrays.asList(playerYacht.getHeadingProperty(), windDirection)) {
o.addListener((obs, oldValue, newValue) -> {
Platform.runLater(() -> {
if (isChaseCam) {
camera.getTransforms().clear();
for (Transform t : chaseCam.getTransforms()) {
if (t instanceof Rotate) {
camera.getTransforms().add(t);
}
}
this.camera.getTransforms().addAll(
new Translate(-55, -60, 0)
);
}
windArrowModel.getAssets().getTransforms().clear();
windArrowModel.getAssets().getTransforms().addAll(
new Rotate(windDirection.getValue(),
new Point3D(0, 0, 1))
);
});
});
}
}
private void initialiseWindView() {
gameObjects = new Group();
windPane.getChildren().add(gameObjects);
root3D = new Group(camera, gameObjects);
view = new SubScene(
root3D, 110, 120, true, SceneAntialiasing.BALANCED
);
view.setCamera(camera);
windArrowModel = ModelFactory.makeWindArrow();
gameObjects.getChildren().addAll(
windArrowModel.getAssets()
);
}
public Node getAssets() {
return view;
}
public void updateCameraTransforms(Camera camera) {
this.camera.getTransforms().clear();
for (Transform transform : camera.getTransforms()) {
if (!(transform instanceof Translate)) {
this.camera.getTransforms().add(transform);
}
}
this.camera.getTransforms().addAll(
new Translate(-55, -60, 0)
);
windArrowModel.getAssets().getTransforms().clear();
}
public void setCamera(Camera camera) {
isChaseCam = camera instanceof ChaseCamera;
if (isChaseCam) {
this.chaseCam = (ChaseCamera) camera;
} else {
this.chaseCam = null;
}
updateCameraTransforms(camera);
}
}
@@ -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){
@@ -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.
@@ -79,7 +75,8 @@ 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()) {
Platform.runLater(() -> Platform.runLater(() ->
this.getChildren().setAll(mark, arrowList.get(arrowListIndex)) this.getChildren().setAll(mark, 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;
@@ -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))
@@ -16,7 +16,6 @@ import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate; import javafx.scene.transform.Translate;
/** /**
* Factory class for creating 3D models of boatTypes. * Factory class for creating 3D models of boatTypes.
*/ */
@@ -100,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);
} }
@@ -276,4 +275,31 @@ public class ModelFactory {
); );
return new Model(new Group(assets), null); return new Model(new Group(assets), null);
} }
/**
* Create a 3D wind arrow.
*
* @return 3D wind arrow object
*/
public static Model makeWindArrow() {
ColModelImporter importer = new ColModelImporter();
importer.read(ModelFactory.class.getResource("/meshes/" + ModelType.WIND_ARROW.filename));
Group assets = new Group(importer.getImport());
assets.setCache(true);
assets.setCacheHint(CacheHint.SCALE_AND_ROTATE);
Rotate animationRotate = new Rotate(0, new Point3D(0, 1, 0));
assets.getTransforms().addAll(
new Translate(0, 0, 0),
new Scale(5, 5, 5),
new Rotate(270, new Point3D(1, 0, 0)),
animationRotate
);
assets.getChildren().addAll(
new AmbientLight()
);
return new Model(new Group(assets), null);
}
} }
@@ -30,7 +30,8 @@ public enum ModelType {
LAND("land.dae"), LAND("land.dae"),
LAND_SMOOTH("land_smooth.dae"), LAND_SMOOTH("land_smooth.dae"),
NEXT_MARK_INDICATOR("indicator_arrow.dae"), NEXT_MARK_INDICATOR("indicator_arrow.dae"),
PLAYER_IDENTIFIER_TORUS("torus.dae"); PLAYER_IDENTIFIER_TORUS("torus.dae"),
WIND_ARROW("windFiles/arrow56.dae"); // change filename
final String filename; final String filename;
@@ -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());
}
}
+24
View File
@@ -5,6 +5,7 @@
#timerGrid{ #timerGrid{
-fx-background-color: rgba(255, 255, 255, 0.6); -fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light; -fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
} }
GridPane .timer * { GridPane .timer * {
@@ -27,20 +28,24 @@ GridPane .timer * {
#chatHistoryHolder { #chatHistoryHolder {
-fx-background-color: rgba(255, 255, 255, 0.6); -fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light; -fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
} }
#chatInputHolder { #chatInputHolder {
-fx-background-color: rgba(255, 255, 255, 0.6); -fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light; -fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
} }
#windGridPane { #windGridPane {
-fx-background-color: rgba(255, 255, 255, 0.6); -fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light; -fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
} }
#windHolder { #windHolder {
-fx-background-color: rgba(255, 255, 255, 0.5); -fx-background-color: rgba(255, 255, 255, 0.5);
-fx-background-radius: 5;
} }
#chatSend { #chatSend {
@@ -61,6 +66,25 @@ GridPane .timer * {
-fx-background-color: transparent; -fx-background-color: transparent;
} }
#chatToggleButton {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-background-radius: 5;
-fx-min-width: 30;
-fx-min-height: 30;
}
#windImageView { #windImageView {
-fx-image: url("/images/wind-180.png"); -fx-image: url("/images/wind-180.png");
}
#miniMapPane {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-background-radius: 5;
}
#miniMapButton {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-background-radius: 5;
-fx-min-width: 30;
-fx-min-height: 30;
} }
@@ -0,0 +1,3 @@
#windPane {
-fx-background-color: rgba(255, 255, 255, 0);
}
+3 -3
View File
@@ -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" />
+8 -3
View File
@@ -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>
+65
View File
@@ -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>
+61
View File
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1,518 @@
<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<asset>
<contributor>
<author>Blender User</author>
<authoring_tool>Blender 2.79.0 commit date:2017-09-11, commit time:10:43, hash:5bd8ac9</authoring_tool>
</contributor>
<created>2017-09-28T02:22:29</created>
<modified>2017-09-28T02:22:29</modified>
<unit name="meter" meter="1"/>
<up_axis>Z_UP</up_axis>
</asset>
<library_cameras>
<camera id="Camera-camera" name="Camera">
<optics>
<technique_common>
<perspective>
<xfov sid="xfov">49.13434</xfov>
<aspect_ratio>1.777778</aspect_ratio>
<znear sid="znear">0.1</znear>
<zfar sid="zfar">100</zfar>
</perspective>
</technique_common>
</optics>
<extra>
<technique profile="blender">
<shiftx sid="shiftx" type="float">0</shiftx>
<shifty sid="shifty" type="float">0</shifty>
<YF_dofdist sid="YF_dofdist" type="float">0</YF_dofdist>
</technique>
</extra>
</camera>
<camera id="Camera_001-camera" name="Camera.001">
<optics>
<technique_common>
<perspective>
<xfov sid="xfov">49.13434</xfov>
<aspect_ratio>1.777778</aspect_ratio>
<znear sid="znear">0.1</znear>
<zfar sid="zfar">100</zfar>
</perspective>
</technique_common>
</optics>
<extra>
<technique profile="blender">
<shiftx sid="shiftx" type="float">0</shiftx>
<shifty sid="shifty" type="float">0</shifty>
<YF_dofdist sid="YF_dofdist" type="float">0</YF_dofdist>
</technique>
</extra>
</camera>
<camera id="Camera_001-camera" name="Camera.003">
<optics>
<technique_common>
<perspective>
<xfov sid="xfov">49.13434</xfov>
<aspect_ratio>1.777778</aspect_ratio>
<znear sid="znear">0.1</znear>
<zfar sid="zfar">100</zfar>
</perspective>
</technique_common>
</optics>
<extra>
<technique profile="blender">
<shiftx sid="shiftx" type="float">0</shiftx>
<shifty sid="shifty" type="float">0</shifty>
<YF_dofdist sid="YF_dofdist" type="float">0</YF_dofdist>
</technique>
</extra>
</camera>
<camera id="Camera_001_001-camera" name="Camera.003">
<optics>
<technique_common>
<perspective>
<xfov sid="xfov">49.13434</xfov>
<aspect_ratio>1.777778</aspect_ratio>
<znear sid="znear">0.1</znear>
<zfar sid="zfar">100</zfar>
</perspective>
</technique_common>
</optics>
<extra>
<technique profile="blender">
<shiftx sid="shiftx" type="float">0</shiftx>
<shifty sid="shifty" type="float">0</shifty>
<YF_dofdist sid="YF_dofdist" type="float">0</YF_dofdist>
</technique>
</extra>
</camera>
</library_cameras>
<library_lights>
<light id="Lamp-light" name="Lamp">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">0.000999987</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
<light id="Lamp_001-light" name="Lamp.001">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">9.99987e-4</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
<light id="Lamp_001-light" name="Lamp.003">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">9.99987e-4</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
<light id="Lamp_001_001-light" name="Lamp.003">
<technique_common>
<point>
<color sid="color">1 1 1</color>
<constant_attenuation>1</constant_attenuation>
<linear_attenuation>0</linear_attenuation>
<quadratic_attenuation>0.00111109</quadratic_attenuation>
</point>
</technique_common>
<extra>
<technique profile="blender">
<type sid="type" type="int">0</type>
<flag sid="flag" type="int">0</flag>
<mode sid="mode" type="int">8192</mode>
<gamma sid="blender_gamma" type="float">1</gamma>
<red sid="red" type="float">1</red>
<green sid="green" type="float">1</green>
<blue sid="blue" type="float">1</blue>
<shadow_r sid="blender_shadow_r" type="float">0</shadow_r>
<shadow_g sid="blender_shadow_g" type="float">0</shadow_g>
<shadow_b sid="blender_shadow_b" type="float">0</shadow_b>
<energy sid="blender_energy" type="float">1</energy>
<dist sid="blender_dist" type="float">29.99998</dist>
<spotsize sid="spotsize" type="float">75</spotsize>
<spotblend sid="spotblend" type="float">0.15</spotblend>
<halo_intensity sid="blnder_halo_intensity" type="float">1</halo_intensity>
<att1 sid="att1" type="float">0</att1>
<att2 sid="att2" type="float">1</att2>
<falloff_type sid="falloff_type" type="int">2</falloff_type>
<clipsta sid="clipsta" type="float">1.000799</clipsta>
<clipend sid="clipend" type="float">30.002</clipend>
<bias sid="bias" type="float">1</bias>
<soft sid="soft" type="float">3</soft>
<compressthresh sid="compressthresh" type="float">0.04999995</compressthresh>
<bufsize sid="bufsize" type="int">2880</bufsize>
<samp sid="samp" type="int">3</samp>
<buffers sid="buffers" type="int">1</buffers>
<filtertype sid="filtertype" type="int">0</filtertype>
<bufflag sid="bufflag" type="int">0</bufflag>
<buftype sid="buftype" type="int">2</buftype>
<ray_samp sid="ray_samp" type="int">1</ray_samp>
<ray_sampy sid="ray_sampy" type="int">1</ray_sampy>
<ray_sampz sid="ray_sampz" type="int">1</ray_sampz>
<ray_samp_type sid="ray_samp_type" type="int">0</ray_samp_type>
<area_shape sid="area_shape" type="int">1</area_shape>
<area_size sid="area_size" type="float">0.1</area_size>
<area_sizey sid="area_sizey" type="float">0.1</area_sizey>
<area_sizez sid="area_sizez" type="float">1</area_sizez>
<adapt_thresh sid="adapt_thresh" type="float">9.99987e-4</adapt_thresh>
<ray_samp_method sid="ray_samp_method" type="int">1</ray_samp_method>
<shadhalostep sid="shadhalostep" type="int">0</shadhalostep>
<sun_effect_type sid="sun_effect_type" type="int">0</sun_effect_type>
<skyblendtype sid="skyblendtype" type="int">1</skyblendtype>
<horizon_brightness sid="horizon_brightness" type="float">1</horizon_brightness>
<spread sid="spread" type="float">1</spread>
<sun_brightness sid="sun_brightness" type="float">1</sun_brightness>
<sun_size sid="sun_size" type="float">1</sun_size>
<backscattered_light sid="backscattered_light" type="float">1</backscattered_light>
<sun_intensity sid="sun_intensity" type="float">1</sun_intensity>
<atm_turbidity sid="atm_turbidity" type="float">2</atm_turbidity>
<atm_extinction_factor sid="atm_extinction_factor" type="float">1</atm_extinction_factor>
<atm_distance_factor sid="atm_distance_factor" type="float">1</atm_distance_factor>
<skyblendfac sid="skyblendfac" type="float">1</skyblendfac>
<sky_exposure sid="sky_exposure" type="float">1</sky_exposure>
<sky_colorspace sid="sky_colorspace" type="int">0</sky_colorspace>
</technique>
</extra>
</light>
</library_lights>
<library_images/>
<library_effects>
<effect id="Material_004-effect">
<profile_COMMON>
<technique sid="common">
<phong>
<emission>
<color sid="emission">0 0 0 1</color>
</emission>
<ambient>
<color sid="ambient">0 0 0 1</color>
</ambient>
<diffuse>
<color sid="diffuse">0.8 0 0 1</color>
</diffuse>
<specular>
<color sid="specular">0.125 0.125 0.125 1</color>
</specular>
<shininess>
<float sid="shininess">50</float>
</shininess>
<index_of_refraction>
<float sid="index_of_refraction">1</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
<effect id="Material_002-effect">
<profile_COMMON>
<technique sid="common">
<phong>
<emission>
<color sid="emission">0 0 0 1</color>
</emission>
<ambient>
<color sid="ambient">0 0 0 1</color>
</ambient>
<diffuse>
<color sid="diffuse">0 0 0.8 1</color>
</diffuse>
<specular>
<color sid="specular">0.125 0.125 0.125 1</color>
</specular>
<shininess>
<float sid="shininess">50</float>
</shininess>
<index_of_refraction>
<float sid="index_of_refraction">1</float>
</index_of_refraction>
</phong>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_materials>
<material id="Material_004-material" name="Material_004">
<instance_effect url="#Material_004-effect"/>
</material>
<material id="Material_002-material" name="Material_002">
<instance_effect url="#Material_002-effect"/>
</material>
</library_materials>
<library_geometries>
<geometry id="Cone_003-mesh" name="Cone.003">
<mesh>
<source id="Cone_003-mesh-positions">
<float_array id="Cone_003-mesh-positions-array" count="198">0 -0.6151299 -0.05701982 -1.77995e-7 -1.7983e-7 -2.05702 0.1200059 -0.6033104 -0.05701982 0.2354 -0.5683059 -0.05701982 0.3417478 -0.5114619 -0.05701982 0.4349624 -0.4349625 -0.05701982 0.5114617 -0.3417478 -0.05701982 0.5683057 -0.2354 -0.05701982 0.6033101 -0.120006 -0.05701988 0.6151297 -1.61108e-7 -0.05701988 0.6033102 0.1200057 -0.05701988 0.5683057 0.2353997 -0.05701988 0.5114617 0.3417476 -0.05701988 0.4349624 0.4349623 -0.05701988 0.3417478 0.5114615 -0.05701988 0.2353999 0.5683056 -0.05701988 0.1200057 0.60331 -0.05701988 -1.59668e-7 0.6151295 -0.05701988 -0.120006 0.6033099 -0.05701988 -0.2354001 0.5683054 -0.05701982 -0.341748 0.5114613 -0.05701982 -0.4349626 0.434962 -0.05701982 -0.5114619 0.3417473 -0.05701982 -0.568306 0.2353994 -0.05701982 -0.6033103 0.1200052 -0.05701982 -0.6151297 -7.08636e-7 -0.05701982 -0.6033101 -0.1200066 -0.05701977 -0.5683055 -0.2354007 -0.05701977 -0.5114613 -0.3417485 -0.05701977 -0.4349618 -0.4349631 -0.05701977 -0.341747 -0.5114623 -0.05701977 -0.235399 -0.5683063 -0.05701977 -0.1200048 -0.6033105 -0.05701977 0 0.6151295 -0.06060606 0 -2.89444e-7 1.939394 0.1200058 0.60331 -0.06060606 0.2353999 0.5683056 -0.06060606 0.3417478 0.5114615 -0.06060606 0.4349623 0.4349622 -0.06060606 0.5114616 0.3417475 -0.06060606 0.5683057 0.2353997 -0.06060606 0.6033101 0.1200057 -0.06060606 0.6151297 -1.40432e-7 -0.06060606 0.6033102 -0.1200059 -0.06060606 0.5683057 -0.2354 -0.06060606 0.5114616 -0.3417478 -0.06060606 0.4349623 -0.4349626 -0.06060606 0.3417477 -0.5114619 -0.06060606 0.2353998 -0.568306 -0.06060606 0.1200056 -0.6033104 -0.06060606 -2.4745e-7 -0.6151298 -0.06060606 -0.1200062 -0.6033103 -0.06060606 -0.2354003 -0.5683058 -0.06060606 -0.3417481 -0.5114617 -0.06060606 -0.4349627 -0.4349622 -0.06060606 -0.511462 -0.3417476 -0.06060606 -0.568306 -0.2353997 -0.06060606 -0.6033104 -0.1200055 -0.06060606 -0.6151298 4.10911e-7 -0.06060606 -0.6033101 0.1200063 -0.06060606 -0.5683056 0.2354003 -0.06060606 -0.5114613 0.3417482 -0.06060606 -0.4349619 0.4349627 -0.06060606 -0.3417471 0.511462 -0.06060606 -0.2353991 0.5683059 -0.06060606 -0.120005 0.6033102 -0.06060606</float_array>
<technique_common>
<accessor source="#Cone_003-mesh-positions-array" count="66" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cone_003-mesh-normals">
<float_array id="Cone_003-mesh-normals-array" count="198">0 0.8207646 -0.5712665 0 0 1 0.1601035 0.8050041 -0.5712578 0.3140783 0.7582927 -0.5712679 0.4559909 0.6824451 -0.5712627 0.5803661 0.5803661 -0.5712711 0.6824451 0.4559909 -0.5712627 0.7582927 0.3140783 -0.5712679 0.8050041 0.1601035 -0.5712578 0.8207646 0 -0.5712665 0.8050041 -0.1601035 -0.5712578 0.7582927 -0.3140783 -0.5712679 0.6824451 -0.4559909 -0.5712627 0.5803661 -0.5803661 -0.5712711 0.4559909 -0.6824451 -0.5712627 0.3140783 -0.7582927 -0.5712679 0.1601035 -0.8050041 -0.5712578 0 -0.8207646 -0.5712665 -0.1601035 -0.8050041 -0.5712578 -0.3140783 -0.7582927 -0.5712679 -0.4559909 -0.6824451 -0.5712627 -0.5803661 -0.5803661 -0.5712711 -0.6824451 -0.4559909 -0.5712627 -0.7582927 -0.3140783 -0.5712679 -0.8050041 -0.1601035 -0.5712578 -0.8207646 0 -0.5712665 -0.8050041 0.1601035 -0.5712578 -0.7582927 0.3140783 -0.5712679 -0.6824451 0.4559909 -0.5712627 -0.5803661 0.5803661 -0.5712711 -0.4559909 0.6824451 -0.5712627 -0.3140783 0.7582927 -0.5712679 -0.1601035 0.8050041 -0.5712578 0 -0.8207646 0.5712665 0 0 -1 0.1601035 -0.8050041 0.5712578 0.3140783 -0.7582927 0.5712679 0.4559909 -0.6824451 0.5712627 0.5803661 -0.5803661 0.5712711 0.6824451 -0.4559909 0.5712627 0.7582927 -0.3140783 0.5712679 0.8050041 -0.1601035 0.5712578 0.8207646 0 0.5712665 0.8050041 0.1601035 0.5712578 0.7582927 0.3140783 0.5712679 0.6824451 0.4559909 0.5712627 0.5803661 0.5803661 0.5712711 0.4559909 0.6824451 0.5712627 0.3140783 0.7582927 0.5712679 0.1601035 0.8050041 0.5712578 0 0.8207646 0.5712665 -0.1601035 0.8050041 0.5712578 -0.3140783 0.7582927 0.5712679 -0.4559909 0.6824451 0.5712627 -0.5803661 0.5803661 0.5712711 -0.6824451 0.4559909 0.5712627 -0.7582927 0.3140783 0.5712679 -0.8050041 0.1601035 0.5712578 -0.8207646 0 0.5712665 -0.8050041 -0.1601035 0.5712578 -0.7582927 -0.3140783 0.5712679 -0.6824451 -0.4559909 0.5712627 -0.5803661 -0.5803661 0.5712711 -0.4559909 -0.6824451 0.5712627 -0.3140783 -0.7582927 0.5712679 -0.1601035 -0.8050041 0.5712578</float_array>
<technique_common>
<accessor source="#Cone_003-mesh-normals-array" count="66" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="Cone_003-mesh-vertices">
<input semantic="POSITION" source="#Cone_003-mesh-positions"/>
</vertices>
<triangles material="Material_004-material" count="62">
<input semantic="VERTEX" source="#Cone_003-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cone_003-mesh-normals" offset="1"/>
<p>33 0 34 1 35 2 35 2 34 1 36 3 36 3 34 1 37 4 37 4 34 1 38 5 38 5 34 1 39 6 39 6 34 1 40 7 40 7 34 1 41 8 41 8 34 1 42 9 42 9 34 1 43 10 43 10 34 1 44 11 44 11 34 1 45 12 45 12 34 1 46 13 46 13 34 1 47 14 47 14 34 1 48 15 48 15 34 1 49 16 49 16 34 1 50 17 50 17 34 1 51 18 51 18 34 1 52 19 52 19 34 1 53 20 53 20 34 1 54 21 54 21 34 1 55 22 55 22 34 1 56 23 56 23 34 1 57 24 57 24 34 1 58 25 58 25 34 1 59 26 59 26 34 1 60 27 60 27 34 1 61 28 61 28 34 1 62 29 62 29 34 1 63 30 63 30 34 1 64 31 64 31 34 1 65 32 65 32 34 1 33 0 49 16 57 24 65 32 65 32 33 0 35 2 35 2 36 3 65 32 37 4 38 5 39 6 39 6 40 7 41 8 41 8 42 9 43 10 43 10 44 11 41 8 45 12 46 13 47 14 47 14 48 15 45 12 49 16 50 17 53 20 51 18 52 19 53 20 53 20 54 21 57 24 55 22 56 23 57 24 57 24 58 25 59 26 59 26 60 27 61 28 61 28 62 29 65 32 63 30 64 31 65 32 65 32 36 3 37 4 37 4 39 6 41 8 41 8 44 11 45 12 45 12 48 15 49 16 50 17 51 18 53 20 54 21 55 22 57 24 57 24 59 26 65 32 62 29 63 30 65 32 65 32 37 4 41 8 41 8 45 12 65 32 49 16 53 20 57 24 59 26 61 28 65 32 65 32 45 12 49 16</p>
</triangles>
<triangles material="Material_002-material" count="62">
<input semantic="VERTEX" source="#Cone_003-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cone_003-mesh-normals" offset="1"/>
<p>0 33 1 34 2 35 2 35 1 34 3 36 3 36 1 34 4 37 4 37 1 34 5 38 5 38 1 34 6 39 6 39 1 34 7 40 7 40 1 34 8 41 8 41 1 34 9 42 9 42 1 34 10 43 10 43 1 34 11 44 11 44 1 34 12 45 12 45 1 34 13 46 13 46 1 34 14 47 14 47 1 34 15 48 15 48 1 34 16 49 16 49 1 34 17 50 17 50 1 34 18 51 18 51 1 34 19 52 19 52 1 34 20 53 20 53 1 34 21 54 21 54 1 34 22 55 22 55 1 34 23 56 23 56 1 34 24 57 24 57 1 34 25 58 25 58 1 34 26 59 26 59 1 34 27 60 27 60 1 34 28 61 28 61 1 34 29 62 29 62 1 34 30 63 30 63 1 34 31 64 31 64 1 34 32 65 32 65 1 34 0 33 16 49 24 57 8 41 32 65 0 33 2 35 2 35 3 36 4 37 4 37 5 38 8 41 6 39 7 40 8 41 8 41 9 42 10 43 10 43 11 44 8 41 12 45 13 46 14 47 14 47 15 48 16 49 16 49 17 50 20 53 18 51 19 52 20 53 20 53 21 54 22 55 22 55 23 56 24 57 24 57 25 58 26 59 26 59 27 60 24 57 28 61 29 62 32 65 30 63 31 64 32 65 32 65 2 35 8 41 5 38 6 39 8 41 8 41 11 44 12 45 12 45 14 47 16 49 17 50 18 51 20 53 20 53 22 55 24 57 24 57 27 60 28 61 29 62 30 63 32 65 2 35 4 37 8 41 8 41 12 45 16 49 16 49 20 53 24 57 24 57 28 61 32 65 32 65 8 41 24 57</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_controllers/>
<library_visual_scenes>
<visual_scene id="Scene" name="Scene">
<node id="Camera" name="Camera" type="NODE">
<matrix sid="transform">0.6859207 -0.3240135 0.6515582 7.481132 0.7276763 0.3054208 -0.6141704 -6.50764 0 0.8953956 0.4452714 5.343665 0 0 0 1</matrix>
<instance_camera url="#Camera-camera"/>
</node>
<node id="Lamp" name="Lamp" type="NODE">
<matrix sid="transform">-0.2908646 -0.7711008 0.5663932 4.076245 0.9551712 -0.1998834 0.2183912 1.005454 -0.05518906 0.6045247 0.7946723 5.903862 0 0 0 1</matrix>
<instance_light url="#Lamp-light"/>
</node>
<node id="Camera_001" name="Camera_001" type="NODE">
<matrix sid="transform">1.371841 -0.648027 1.303116 10.0091 1.455353 0.6108412 -1.228341 -10.6572 3.76898e-7 1.790791 0.8905425 5.77815 0 0 0 1</matrix>
<instance_camera url="#Camera_001-camera"/>
</node>
<node id="Lamp_001" name="Lamp_001" type="NODE">
<matrix sid="transform">-0.5817292 -1.542202 1.132786 3.199329 1.910342 -0.3997671 0.4367821 4.368987 -0.1103777 1.209049 1.589345 6.898543 0 0 0 1</matrix>
<instance_light url="#Lamp_001-light"/>
</node>
<node id="Cone_000" name="Cone_000" type="NODE">
<matrix sid="transform">0.1515022 -3.01129e-7 -1.994254 0.004837528 -3.54228e-13 -2 3.01996e-7 -0.04310748 -1.994254 -2.28762e-8 -0.1515022 -0.001579307 0 0 0 1</matrix>
<instance_geometry url="#Cone_003-mesh" name="Cone_000">
<bind_material>
<technique_common>
<instance_material symbol="Material_004-material" target="#Material_004-material"/>
<instance_material symbol="Material_002-material" target="#Material_002-material"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
<node id="Lamp_001" name="Lamp_001" type="NODE">
<matrix sid="transform">-0.5817294 -1.542202 1.132787 3.199328 1.910342 -0.3997668 0.4367828 4.368987 -0.1103783 1.209049 1.589345 6.898543 0 0 0 1</matrix>
<instance_light url="#Lamp_001-light"/>
</node>
<node id="Camera_001" name="Camera_001" type="NODE">
<matrix sid="transform">1.371841 -0.648027 1.303116 10.0091 1.455353 0.6108412 -1.228341 -10.6572 3.76898e-7 1.790791 0.8905425 5.77815 0 0 0 1</matrix>
<instance_camera url="#Camera_001-camera"/>
</node>
<node id="Camera_001_001" name="Camera_001_001" type="NODE">
<matrix sid="transform">1.371841 -0.648027 1.303116 10.0091 1.455353 0.6108412 -1.228341 -10.6572 3.76898e-7 1.790791 0.8905425 5.77815 0 0 0 1</matrix>
<instance_camera url="#Camera_001_001-camera"/>
</node>
<node id="Lamp_001_001" name="Lamp_001_001" type="NODE">
<matrix sid="transform">-0.5817294 -1.542202 1.132787 3.199328 1.910342 -0.3997668 0.4367828 4.368987 -0.1103783 1.209049 1.589345 6.898543 0 0 0 1</matrix>
<instance_light url="#Lamp_001_001-light"/>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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>
+46 -68
View File
@@ -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,116 +112,92 @@
<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>
<padding> <padding>
<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>
<padding> <padding>
<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>
<padding> <padding>
<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>
<padding> <padding>
<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>
<padding> <padding>
<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>
@@ -236,7 +214,7 @@
</GridPane> </GridPane>
</children> </children>
<stylesheets> <stylesheets>
<URL value="@../css/Master.css"/> <URL value="@../css/Master.css" />
<URL value="@../css/LobbyView.css"/> <URL value="@../css/LobbyView.css" />
</stylesheets> </stylesheets>
</StackPane> </StackPane>
+298 -289
View File
@@ -2,316 +2,325 @@
<?import com.jfoenix.controls.*?> <?import com.jfoenix.controls.*?>
<?import java.lang.*?> <?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.image.*?> <?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?> <?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?> <?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXSpinner?>
<?import com.jfoenix.controls.JFXTextField?> <?import com.jfoenix.controls.JFXTextField?>
<?import java.lang.String?> <?import java.net.URL?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?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.ColumnConstraints?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?> <?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?> <?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<StackPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1200.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.RaceViewController"> <StackPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1200.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.RaceViewController">
<children> <children>
<StackPane fx:id="contentStackPane" maxHeight="1.7976931348623157E308" <StackPane fx:id="contentStackPane" maxHeight="1.7976931348623157E308"
maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0"
prefWidth="1200.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8.0.111" prefWidth="1200.0" style="-fx-background-color: skyblue;" xmlns="http://javafx.com/javafx/8.0.111"
xmlns:fx="http://javafx.com/fxml/1"> xmlns:fx="http://javafx.com/fxml/1">
<children> <children>
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" <GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="800.0" prefWidth="1200.0"> prefHeight="800.0" prefWidth="1200.0">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="250.0" minWidth="250.0"
prefWidth="250.0"/> prefWidth="250.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/> <ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="400.0"
prefWidth="400.0"/> prefWidth="400.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" <RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/> <RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0" <RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0"
valignment="BOTTOM" vgrow="SOMETIMES"/> valignment="BOTTOM" vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0" styleClass="timer"> <GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0" styleClass="timer">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0"
prefWidth="50.0"/> prefWidth="50.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0" minWidth="135.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0" minWidth="135.0"
prefWidth="135.0"/> prefWidth="135.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<opaqueInsets> <opaqueInsets>
<Insets/> <Insets/>
</opaqueInsets> </opaqueInsets>
<GridPane.margin> <GridPane.margin>
<Insets left="10.0" right="200.0" top="10.0"/> <Insets left="10.0" right="200.0" top="10.0"/>
</GridPane.margin> </GridPane.margin>
<children> <children>
<ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true" <ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true"
preserveRatio="true" GridPane.halignment="CENTER" preserveRatio="true" GridPane.halignment="CENTER"
GridPane.valignment="CENTER"> GridPane.valignment="CENTER">
<image> <image>
<Image url="@../images/timer.png"/> <Image url="@../images/timer.png"/>
</image> </image>
<GridPane.margin> <GridPane.margin>
<Insets/> <Insets/>
</GridPane.margin> </GridPane.margin>
</ImageView> </ImageView>
<Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1" <Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1"
GridPane.halignment="CENTER" GridPane.valignment="CENTER"> GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<font> <font>
<Font size="21.0"/> <Font size="21.0"/>
</font> </font>
<GridPane.margin> <GridPane.margin>
<Insets/> <Insets/>
</GridPane.margin> </GridPane.margin>
</Label> </Label>
</children> </children>
</GridPane> </GridPane>
<GridPane GridPane.columnIndex="2"> <GridPane GridPane.columnIndex="2">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/> <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
</GridPane> </GridPane>
<GridPane fx:id="chatGridPane" GridPane.columnIndex="2" GridPane.rowIndex="2"> <GridPane fx:id="chatGridPane" GridPane.columnIndex="2" GridPane.rowIndex="2">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="390.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="390.0"
prefWidth="390.0"/> prefWidth="390.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/> <RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" <RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0" <Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0"
GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM" GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM"
GridPane.vgrow="ALWAYS"> GridPane.vgrow="ALWAYS">
<GridPane.margin> <GridPane.margin>
<Insets/> <Insets/>
</GridPane.margin> </GridPane.margin>
<padding> <padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding> </padding>
</Pane> </Pane>
<GridPane fx:id="chatInputHolder" GridPane.rowIndex="1"> <GridPane fx:id="chatInputHolder" GridPane.rowIndex="1">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/> prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
minWidth="90.0" prefWidth="90.0"/> minWidth="90.0" prefWidth="90.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0" <RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0"
valignment="CENTER" vgrow="SOMETIMES"/> valignment="CENTER" vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<JFXButton fx:id="chatSend" alignment="CENTER" buttonType="RAISED" <JFXButton fx:id="chatSend" alignment="CENTER" buttonType="RAISED"
focusTraversable="false" maxHeight="-Infinity" focusTraversable="false" maxHeight="-Infinity"
maxWidth="1.7976931348623157E308" minHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="35.0" text="SEND" minWidth="-Infinity" prefHeight="35.0" text="SEND"
GridPane.columnIndex="1"> GridPane.columnIndex="1">
<GridPane.margin> <GridPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</GridPane.margin> </GridPane.margin>
</JFXButton> </JFXButton>
<JFXTextField fx:id="chatInput" focusTraversable="false" <JFXTextField fx:id="chatInput" focusTraversable="false"
maxHeight="35.0" minHeight="-Infinity" prefHeight="35.0"> maxHeight="35.0" minHeight="-Infinity" prefHeight="35.0">
<GridPane.margin> <GridPane.margin>
<Insets bottom="10.0" left="20.0" right="10.0"/> <Insets bottom="10.0" left="20.0" right="10.0"/>
</GridPane.margin> </GridPane.margin>
<padding> <padding>
<Insets right="15.0"/> <Insets right="15.0"/>
</padding> </padding>
</JFXTextField> </JFXTextField>
</children> </children>
<GridPane.margin> <GridPane.margin>
<Insets top="10.0"/> <Insets top="10.0"/>
</GridPane.margin> </GridPane.margin>
</GridPane> </GridPane>
</children> </children>
<GridPane.margin> <GridPane.margin>
<Insets bottom="10.0" right="10.0"/> <Insets bottom="10.0" right="10.0"/>
</GridPane.margin> </GridPane.margin>
</GridPane> </GridPane>
<GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity" <GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity"
prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER" prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER"
GridPane.rowIndex="2" GridPane.valignment="BOTTOM"> GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" minWidth="110.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" minWidth="110.0"
prefWidth="110.0"/> prefWidth="110.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0"
prefWidth="132.0"/> prefWidth="132.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0" <RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" <RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<Label fx:id="positionLabel" text="Position:" GridPane.columnIndex="1" <Label fx:id="positionLabel" text="Position:" GridPane.columnIndex="1"
GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="TOP"> GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="TOP">
<padding> <padding>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
</padding> </padding>
</Label> </Label>
<Label fx:id="boatSpeedLabel" text="Boat Speed:" GridPane.columnIndex="1" <Label fx:id="boatSpeedLabel" text="Boat Speed:" GridPane.columnIndex="1"
GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.halignment="LEFT" GridPane.rowSpan="2"
GridPane.valignment="CENTER"> GridPane.valignment="CENTER">
<opaqueInsets> <opaqueInsets>
<Insets/> <Insets/>
</opaqueInsets> </opaqueInsets>
<padding> <padding>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
</padding> </padding>
</Label> </Label>
<Label fx:id="boatHeadingLabel" text="Boat Heading:" <Label fx:id="boatHeadingLabel" text="Boat Heading:"
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2"
GridPane.valignment="BOTTOM"> GridPane.valignment="BOTTOM">
<padding> <padding>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/> <Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
</padding> </padding>
</Label> </Label>
<GridPane fx:id="windHolder" GridPane.rowSpan="2"> <GridPane fx:id="windHolder" GridPane.rowSpan="2">
<columnConstraints> <columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/> prefWidth="100.0"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints maxHeight="120.0" minHeight="120.0" <RowConstraints maxHeight="120.0" minHeight="120.0"
prefHeight="120.0" vgrow="SOMETIMES"/> prefHeight="120.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" <RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
vgrow="SOMETIMES"/> vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
<children> <children>
<ImageView fx:id="windImageView" fitHeight="92.0" fitWidth="109.0" <Label fx:id="windSpeedLabel" text="0.0 Knots"
pickOnBounds="true" preserveRatio="true" GridPane.halignment="RIGHT" GridPane.rowIndex="1"
GridPane.halignment="CENTER" GridPane.rowSpan="2" GridPane.valignment="CENTER">
GridPane.valignment="CENTER"/> <GridPane.margin>
<Label fx:id="windSpeedLabel" text="0.0 Knots" <Insets right="5.0"/>
GridPane.halignment="RIGHT" GridPane.rowIndex="1" </GridPane.margin>
GridPane.valignment="CENTER"> </Label>
<GridPane.margin> <Label fx:id="windDirectionLabel" text="180.0°"
<Insets right="5.0"/> GridPane.halignment="LEFT" GridPane.rowIndex="1"
</GridPane.margin> GridPane.valignment="CENTER">
</Label> <GridPane.margin>
<Label fx:id="windDirectionLabel" text="180.0°" <Insets left="5.0"/>
GridPane.halignment="LEFT" GridPane.rowIndex="1" </GridPane.margin>
GridPane.valignment="CENTER"> </Label>
<GridPane.margin> <VBox fx:id="windArrowVBox" prefHeight="200.0" prefWidth="100.0"/>
<Insets left="5.0"/> </children>
</GridPane.margin> </GridPane>
</Label> </children>
</children> <opaqueInsets>
</GridPane> <Insets/>
</children> </opaqueInsets>
<opaqueInsets> <GridPane.margin>
<Insets/> <Insets bottom="10.0" left="10.0" top="40.0"/>
</opaqueInsets> </GridPane.margin>
<GridPane.margin> </GridPane>
<Insets bottom="10.0" left="10.0" top="40.0"/> <GridPane GridPane.columnIndex="1" GridPane.rowIndex="2">
</GridPane.margin> <columnConstraints>
</GridPane> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="2"> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<columnConstraints> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> </columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <rowConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/> <RowConstraints maxHeight="152.0" minHeight="10.0" prefHeight="152.0"
</columnConstraints> vgrow="SOMETIMES"/>
<rowConstraints> <RowConstraints maxHeight="118.0" minHeight="10.0" prefHeight="98.0"
<RowConstraints maxHeight="152.0" minHeight="10.0" prefHeight="152.0" vgrow="SOMETIMES"/>
vgrow="SOMETIMES"/> </rowConstraints>
<RowConstraints maxHeight="118.0" minHeight="10.0" prefHeight="98.0" <children>
vgrow="SOMETIMES"/> <ImageView fx:id="velocityIcon" fitHeight="88.0" fitWidth="106.0"
</rowConstraints> pickOnBounds="true" preserveRatio="true" visible="false"
<children> GridPane.halignment="CENTER" GridPane.rowIndex="1">
<ImageView fx:id="velocityIcon" fitHeight="88.0" fitWidth="106.0" <image>
pickOnBounds="true" preserveRatio="true" visible="false" <Image url="@../icons/velocity.png"/>
GridPane.halignment="CENTER" GridPane.rowIndex="1"> </image>
<image> </ImageView>
<Image url="@../icons/velocity.png"/> <ImageView fx:id="handlingIcon" fitHeight="87.0" fitWidth="98.0"
</image> pickOnBounds="true" preserveRatio="true" visible="false"
</ImageView> GridPane.columnIndex="1" GridPane.halignment="CENTER"
<ImageView fx:id="handlingIcon" fitHeight="87.0" fitWidth="98.0" GridPane.rowIndex="1">
pickOnBounds="true" preserveRatio="true" visible="false" <image>
GridPane.columnIndex="1" GridPane.halignment="CENTER" <Image url="@../icons/handlingIcon.png"/>
GridPane.rowIndex="1"> </image>
<image> </ImageView>
<Image url="@../icons/handlingIcon.png"/> <ImageView fx:id="windWalkerIcon" fitHeight="83.0" fitWidth="100.0"
</image> pickOnBounds="true" preserveRatio="true" visible="false"
</ImageView> GridPane.columnIndex="2" GridPane.halignment="CENTER"
<ImageView fx:id="windWalkerIcon" fitHeight="83.0" fitWidth="100.0" GridPane.rowIndex="1">
pickOnBounds="true" preserveRatio="true" visible="false" <image>
GridPane.columnIndex="2" GridPane.halignment="CENTER" <Image url="@../icons/windWalkerIcon.png"/>
GridPane.rowIndex="1"> </image>
<image> </ImageView>
<Image url="@../icons/windWalkerIcon.png"/> <ImageView fx:id="bumperIcon" fitHeight="83.0" fitWidth="88.0"
</image> pickOnBounds="true" preserveRatio="true" visible="false"
</ImageView> GridPane.columnIndex="3" GridPane.halignment="CENTER"
<ImageView fx:id="bumperIcon" fitHeight="83.0" fitWidth="88.0" GridPane.rowIndex="1">
pickOnBounds="true" preserveRatio="true" visible="false" <image>
GridPane.columnIndex="3" GridPane.halignment="CENTER" <Image url="@../icons/bumperIcon.png"/>
GridPane.rowIndex="1"> </image>
<image> </ImageView>
<Image url="@../icons/bumperIcon.png"/> <ImageView fx:id="badRandomIcon" fitHeight="69.0" fitWidth="103.0"
</image> pickOnBounds="true" preserveRatio="true" visible="false"
</ImageView> GridPane.columnIndex="4" GridPane.halignment="CENTER"
<ImageView fx:id="badRandomIcon" fitHeight="69.0" fitWidth="103.0" GridPane.rowIndex="1" GridPane.valignment="CENTER">
pickOnBounds="true" preserveRatio="true" visible="false" <image>
GridPane.columnIndex="4" GridPane.halignment="CENTER" <Image url="@../icons/slowedIcon.png"/>
GridPane.rowIndex="1" GridPane.valignment="CENTER"> </image>
<image> </ImageView>
<Image url="@../icons/slowedIcon.png"/> </children>
</image> </GridPane>
</ImageView> </children>
</children> </GridPane>
</GridPane> </children>
</children> </StackPane>
</GridPane> <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">
</children> <StackPane.margin>
</StackPane> <Insets right="15.0" top="15.0" />
<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>
<StackPane.margin> </Pane>
<Insets right="15.0" top="15.0" /> <JFXButton fx:id="miniMapButton" text="—" StackPane.alignment="TOP_RIGHT">
</StackPane.margin> <font>
</Pane> <Font size="15.0" />
<JFXButton fx:id="miniMapButton" style="-fx-background-color: white; -fx-opacity: 0.45; -fx-background-radius: 10;" text="✕" StackPane.alignment="TOP_RIGHT"> </font>
<font> <StackPane.margin>
<Font size="15.0" /> <Insets right="15.0" top="15.0" />
</font> </StackPane.margin>
<StackPane.margin> </JFXButton>
<Insets right="15.0" top="15.0" /> <AnchorPane fx:id="loadingScreenPane">
</StackPane.margin>
</JFXButton>
<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" />
</AnchorPane> </AnchorPane>
</children> <JFXButton fx:id="chatToggleButton" text="—" StackPane.alignment="BOTTOM_RIGHT">
<font>
<Font size="15.0"/>
</font>
<StackPane.margin>
<Insets bottom="70.0" right="10.0"/>
</StackPane.margin>
</JFXButton>
</children>
<stylesheets> <stylesheets>
<String fx:value="/css/Master.css" /> <URL value="@../css/Master.css"/>
<String fx:value="/css/RaceView.css" /> <URL value="@../css/RaceView.css"/>
</stylesheets> </stylesheets>
</StackPane> </StackPane>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.Pane?>
<Pane fx:id="windPane" prefHeight="120.0" prefWidth="110.0"
stylesheets="@../../css/cells/WindCell.css" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"/>
@@ -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);
}
}
+19 -16
View File
@@ -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$")
+2 -2
View File
@@ -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) {
+1 -1
View File
@@ -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) {