Compare commits

...

79 Commits

Author SHA1 Message Date
William Muir a1d468c689 Added toggle button for the chat history
#story[1274]
2017-09-28 16:39:59 +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
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 e1ebbc71c1 Added drawing to fx thread
#fix
2017-09-28 14:57:52 +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
William Muir c98297ea79 Merged dev changes back on to mini map
#story[1273]
2017-09-28 14:44:16 +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
William Muir a5eea10c87 Merge branch 'develop' into story1273_minimap
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
#	src/main/resources/meshes/boatSTLs/parrot_features.stl
2017-09-28 14:41:08 +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
Calum 597fbe935f Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 14:28:16 +13:00
Calum 7cfad28d6b Fixed parrot 2017-09-28 14:28:07 +13:00
Michael Rausch 3345734efd Fixed memory leak by forcing garbage collection 2017-09-28 14:22:33 +13:00
Haoming Yin 9795083d4d Added confirm button in keybinding dialog.
-  clicking confirm button will exit the dialog
- [WIP] exit without clicking confirm button will still save changes, which should be fixed in the future

tags: #story[1273]
2017-09-28 13:58:25 +13:00
Kusal Ekanayake f02208ba3a Loopty loop map added 2017-09-28 13:33:09 +13:00
William Muir b9a2d60115 Merged dev changes back on to mini map
#story[1273]
2017-09-28 12:58:19 +13:00
William Muir 076c4c9a40 Merge branch 'develop' into story1273_minimap
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
#	src/main/resources/views/RaceView.fxml
2017-09-28 12:54:12 +13:00
Calum 8d74c3b756 Merge remote-tracking branch 'origin/develop' into develop 2017-09-28 12:44:33 +13:00
Calum 3f666fa092 Made waka larger. 2017-09-28 12:44:24 +13:00
Haoming Yin 55d82298b6 Beautified the loading splash screen
- added 7-color rainbow spinners
- added background image
- added subtitle
- changed font size and color

tags: #story[1273]
2017-09-28 12:42:46 +13:00
William Muir 909407fe63 Merge branch '1293_PowerUps_TokenInfo' into develop 2017-09-28 12:31:14 +13:00
William Muir cb4e47f71a Fixed icon backgrounds to be white
#story[1293]
2017-09-28 12:31:00 +13:00
William Muir 499acb9733 Merge branch '1293_PowerUps_TokenInfo' into develop 2017-09-28 12:21:12 +13:00
William Muir 5688e10e6f Tokens now display on the right and are clickable for further information
#story[1293]
2017-09-28 12:20:16 +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
William Muir 5cbd729214 Tokens now display on the right and are clickable for further information
#story[1293]
2017-09-28 12:08:14 +13:00
Calum ddf5a96e0f Merge branch '1276_Next_Mark_Indicator' into develop 2017-09-28 12:03:30 +13:00
Calum 81b2d285e9 Changed arrow colour.
#fix
2017-09-28 12:02:24 +13:00
Calum 5d7f307260 Changed arrow colour.
#fix
2017-09-28 12:02:09 +13:00
Calum e87931a8fc Merge branch 'develop' into story1273_minimap 2017-09-28 10:21:23 +13:00
Calum d1edbc4b8a Put the arrows into the minimap. Fixed the issue with curved section of port marks.
#fix #implement
2017-09-28 10:19:32 +13:00
Calum 275a2cbab7 Made continous turning the default. Added triangles to minimap. Made mark areas bigger
#fix #implement
2017-09-28 10:12:18 +13:00
Calum 705669ad07 centered icons #fix 2017-09-28 07:23:25 +13:00
Calum 71f6b9accb Fixed duplicate waka files.
#fix
2017-09-28 06:59:44 +13:00
Calum caf04e1e99 Added a waka model.
#implement #story[1274]
2017-09-28 06:54:20 +13:00
Calum b9cb6fa5b4 Added token information to the lobby screen.
#implement #story[1293]
2017-09-28 05:09:54 +13:00
Calum 0b8e2499a7 Fixed some internal stl faces on parrot
#fix
2017-09-28 03:35:28 +13:00
Calum 9075d2a909 Added a minimap to the race view.
#implement #story[1273]
2017-09-28 03:17:33 +13:00
alistairjmcintyre 00e2af9c14 - Fixed Merge Errors and some broken lighting AGAIN
#tags [1276]
2017-09-28 02:20:34 +13:00
William Muir ba768deabc Initial commit for The Token info panel in the lobby controller
- Having some mad issues with front end formatting with JFX.
- Icons are put in boxes

#story[1293]
2017-09-28 02:17:39 +13:00
alistairjmcintyre 73861b2ef3 Merge branch 'develop' into 1276_Next_Mark_Indicator 2017-09-28 02:06:18 +13:00
alistairjmcintyre 4018dd783e - Fixed Merge Errors and some broken lighting
#tags [1276]
2017-09-28 02:05:47 +13:00
alistairjmcintyre a08a38c985 - Fixed Merge Errors
#tags [1276]
2017-09-27 22:25:32 +13:00
alistairjmcintyre 810dde6a21 Merge branch 'develop' into 1276_Next_Mark_Indicator
# Conflicts:
#	src/main/java/seng302/visualiser/GameView3D.java
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelType.java
2017-09-27 22:15:02 +13:00
alistairjmcintyre 7a76efa2ce - Added ability to color the indicators.
#tags [1276]
2017-09-27 22:07:24 +13:00
alistairjmcintyre c5e6302f86 - Added circle to boat to indicate which boat is the players and to show where the arrow is pointing.
#tags [1276]
2017-09-27 21:31:02 +13:00
Alistair McIntyre be72062c8e Merge branch 'develop' into 1276_Next_Mark_Indicator
# Conflicts:
#	src/main/java/seng302/visualiser/fxObjects/assets_3D/ModelFactory.java
2017-09-27 19:25:08 +13:00
Alistair McIntyre 0d212a4a1d - Indicator works correctly, sits in the right place, rotates around the boat correctly and sits on top of the water now.
tags : #story[1276]
2017-09-27 19:20:33 +13:00
Alistair McIntyre 0e9b818071 - Indicator points towards the next mark. Seems to do some funny stuff when entering a compound mark(gate).
tags : #story[1276]
2017-09-27 18:50:38 +13:00
Alistair McIntyre 452e83c1c3 - Marker seems to be detecting the correct mark but somethings wrong with the maths.
tags : #story[1276]
2017-09-27 17:52:54 +13:00
Alistair McIntyre aded794a67 - Added new indicator for direction to next mark.
- Marker rotates towards a given heading.

tags : #story[1276]
2017-09-27 17:17:50 +13:00
84 changed files with 1668 additions and 1769 deletions
+13
View File
@@ -13,6 +13,9 @@ import org.slf4j.LoggerFactory;
import seng302.discoveryServer.DiscoveryServer;
import seng302.visualiser.controllers.ViewManager;
import java.util.Timer;
import java.util.TimerTask;
public class App extends Application {
private static Logger logger = LoggerFactory.getLogger(App.class);
@@ -92,6 +95,16 @@ public class App extends Application {
}
public static void main(String[] args) throws Exception {
/*
* Do not trust Java to do garbage collection
*/
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.gc();
}
}, 0, 1_000);
try {
parseArgs(args);
} catch (ParseException e) {
@@ -48,7 +48,7 @@ public class DiscoveryServer {
" .:;...'cxxxxxxxxxxxxoc;,::,..cdl;;l' \n" +
" .cl;':,'';oxxxxxxdxxxxxx:....,cooc,cO; \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" +
"olc,..',:cccccccccccc:;;;;;;;;:ccccccccc,.'c, \n" +
"Ol;......................................;l' ");
@@ -19,7 +19,7 @@ import java.util.Timer;
import java.util.TimerTask;
public class DiscoveryServerClient {
private final Integer UPDATE_INTERVAL_MS = 5000;
private final Integer UPDATE_INTERVAL_MS = 1000;
private static String roomCode = null;
private Timer serverListingUpdateTimer;
@@ -1,7 +1,7 @@
package seng302.discoveryServer.util;
public class ServerListing {
public final static int SERVER_TTL_DEFAULT = 10;
public final static int SERVER_TTL_DEFAULT = 5;
private String serverName = "";
private String mapName = "";
@@ -68,7 +68,7 @@ public class GameState implements Runnable {
//Collision constants
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;
public static final Double BOUNCE_DISTANCE_YACHT = 30.0;
private static final Double COLLISION_VELOCITY_PENALTY = 0.3;
@@ -238,7 +238,7 @@ public class GameState implements Runnable {
if (System.currentTimeMillis() > startTime) {
startSpawningTokens();
startUpdatingWind();
GameState.setCurrentStage(GameStages.RACING);
GameState.currentStage = GameStages.RACING;
}
}
if (currentStage == GameStages.RACING) {
@@ -299,8 +299,8 @@ public class GameState implements Runnable {
windSpeed += random.nextInt(500);
}
GameState.setWindSpeed(Double.valueOf(windSpeed));
GameState.setWindDirection(direction.doubleValue());
GameState.windSpeed = Double.valueOf(windSpeed);
GameState.windDirection = direction.doubleValue();
}
@@ -5,7 +5,6 @@ import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
@@ -19,12 +18,6 @@ import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
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
@@ -32,22 +25,32 @@ import java.util.TimerTask;
*/
public class MainServerThread implements Runnable, ClientConnectionDelegate {
private Logger logger = LoggerFactory.getLogger(MainServerThread.class);
private static final int PORT = 4942;
private static int selectedPort = PORT;
private static final Integer CLIENT_UPDATES_PER_SECOND = 60;
private Logger logger = LoggerFactory.getLogger(MainServerThread.class);
private boolean terminated;
private Thread thread;
private boolean hasStarted = false;
private ServerSocket serverSocket = null;
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
private static Integer capacity;
private RaceXMLData raceXMLData;
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() {
Integer capacity = GameState.getCapacity();
@@ -65,25 +68,12 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
.setMapName(regattaXMLData.getCourseName())
.setCapacity(capacity)
.setNumberOfPlayers(numPlayers - 1)
.registerGame(PORT, regattaXMLData.getRegattaName());
.registerGame(selectedPort, regattaXMLData.getRegattaName());
} catch (IOException e) {
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() {
PolarTable.parsePolarFile(getClass().getResourceAsStream("/server_config/acc_polars.csv"));
MessageFactory.updateXMLGenerator(raceXMLData, regattaXMLData);
@@ -122,7 +112,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
} catch (InterruptedException e) {
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()));
sendSetupMessages();
GameState.resetCustomizationFlag();
@@ -141,7 +132,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
else if (GameState.getCurrentStage() == GameStages.FINISHED) {
broadcastMessage(MessageFactory.getRaceStatusMessage());
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();
} catch (InterruptedException ie) {
logger.trace("Thread interrupted while waiting to terminate clients", 1);
@@ -149,7 +141,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
}
}
try {
synchronized (this){
synchronized (this) {
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
serverToClientThread.terminate();
}
@@ -205,9 +197,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
startServer();
}
});
} else {
//serverToClientThread.addConnectionListener(this::sendSetupMessages);
}
serverToClientThreads.add(serverToClientThread);
try {
@@ -216,7 +207,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
logger.warn("Couldn't update advertisement");
}
while (regattaXMLData == null && raceXMLData == null){
while (regattaXMLData == null && raceXMLData == null) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
@@ -242,7 +233,7 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
if (serverToClientThread.getSocket() == player.getSocket()) {
closedConnection = serverToClientThread;
} else if (GameState.getCurrentStage() != GameStages.RACING){
} else if (GameState.getCurrentStage() != GameStages.RACING) {
serverToClientThread.sendSetupMessages();
}
}
@@ -255,7 +246,9 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
logger.warn("Couldn't update advertisement");
}
closedConnection.terminate();
if (closedConnection != null) {
closedConnection.terminate();
}
}
public void startGame() {
@@ -273,16 +266,12 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
public void run() {
broadcastMessage(MessageFactory.getRaceStatusMessage());
if (GameState.getCurrentStage() == GameStages.PRE_RACE
|| GameState.getCurrentStage() == GameStages.LOBBYING) {
|| GameState.getCurrentStage() == GameStages.LOBBYING) {
broadcastMessage(MessageFactory.getRaceStartStatusMessage());
}
}
}, 0, 500);
// if (GameState.getCurrentStage() == GameStages.LOBBYING) {
// sendSetupMessages();
// }
}
public void terminate() {
@@ -293,108 +282,6 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
* Initialise boats to specific spaced out geopoints behind starting line.
*/
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 YACHT_SEPARATION = 20d;
@@ -434,14 +321,16 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
Collections.shuffle(randomisedYachts);
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;
GeoPoint firstYachtPoint = GeoUtility.getGeoCoordinate(
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).setLocation(firstYachtPoint);
firstYachtPoint = GeoUtility.getGeoCoordinate(
@@ -459,4 +348,8 @@ public class MainServerThread implements Runnable, ClientConnectionDelegate {
public boolean hasStarted() {
return hasStarted;
}
public int getPortNumber() {
return selectedPort;
}
}
@@ -1,6 +1,5 @@
package seng302.gameServer;
import seng302.gameServer.messages.*;
import java.util.ArrayList;
import java.util.List;
import seng302.gameServer.messages.BoatLocationMessage;
@@ -25,9 +24,6 @@ import seng302.model.token.Token;
import seng302.model.token.TokenType;
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
* through the MainServerThread.
@@ -77,9 +73,6 @@ public class MessageFactory {
}
public static void updateBoats(List<ServerYacht> yachts) {
// for (ServerYacht serverYacht : yachts) {
// System.out.println(serverYacht);
// }
xmlGenerator.getRace().setBoats(yachts);
String xmlStr = xmlGenerator.getBoatsAsXml();
MessageFactory.boats = new XMLMessage(xmlStr, XMLMessageSubType.BOAT, xmlStr.length());
@@ -146,6 +146,8 @@ public class ServerAdvertiser {
public void unregister(){
if (serviceInfo != null)
jmdnsInstance.unregisterService(serviceInfo);
repositoryClient.unregister();
}
/**
@@ -158,7 +158,13 @@ public abstract class Message {
* @return The current buffer as a byte array
*/
public byte[] getBuffer(){
return buffer.array();
byte[] bytes = buffer.array();
// buffer.reset();
// buffer.clear();
// buffer = null;
return bytes;
}
/**
+1 -4
View File
@@ -13,15 +13,11 @@ import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.beans.value.ObservableObjectValue;
import javafx.collections.FXCollections;
import javafx.scene.paint.Color;
import jdk.nashorn.internal.objects.annotations.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seng302.model.token.TokenType;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
import seng302.model.token.TokenType;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
/**
@@ -286,6 +282,7 @@ public class ClientYacht extends Observable {
public void setHeading(Double heading) {
this.heading = heading;
System.out.println(heading);
setHeadingProperty();
}
@@ -72,7 +72,6 @@ public class CompoundMark {
getSubMark(1).setRoundingSide(RoundingSide.STARBOARD);
break;
}
}
@@ -1,14 +1,5 @@
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.IOException;
import java.io.InputStream;
@@ -43,7 +34,7 @@ import seng302.model.stream.xml.generator.RaceXMLTemplate;
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
import seng302.utilities.XMLGenerator;
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
@@ -180,10 +171,12 @@ public class ClientToServerThread implements Runnable {
notifyDisconnectListeners("Connection to server was terminated");
closeSocket();
Platform.runLater(() -> {
ViewManager.getInstance().showErrorSnackBar("Server rejected connection.");
ViewManager.getInstance().goToStartView();
});
//thread.interrupt();
// Platform.runLater(() -> {
// ViewManager.getInstance().showErrorSnackBar("Server rejected connection.");
// ViewManager.getInstance().goToStartView();
// });
}
public void sendCustomizationRequest(CustomizeRequestType reqType, byte[] payload) {
@@ -5,9 +5,7 @@ import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.Timer;
@@ -17,7 +15,6 @@ import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.util.Pair;
import seng302.gameServer.GameStages;
@@ -49,19 +46,12 @@ import seng302.visualiser.controllers.RaceViewController;
import seng302.visualiser.controllers.ViewManager;
import seng302.visualiser.controllers.dialogs.PopupDialogController;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
/**
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
* with a JavaFX Pane to insert itself into.
*/
public class GameClient {
private Pane holderPane;
private ClientToServerThread socketThread;
private MainServerThread server;
@@ -83,10 +73,8 @@ public class GameClient {
/**
* Create an instance of the game client. Does not do anything until run with runAsClient()
* runAsHost().
* @param holder The JavaFX Pane that the visual elements for the race will be inserted into.
*/
public GameClient(Pane holder) {
this.holderPane = holder;
public GameClient() {
this.gameKeyBind = GameKeyBind.getInstance();
}
@@ -95,7 +83,7 @@ public class GameClient {
* @param ipAddress IP to connect to.
* @param portNumber Port to connect to.
*/
public void runAsClient(String ipAddress, Integer portNumber) {
public boolean runAsClient(String ipAddress, Integer portNumber) {
try {
startClientToServerThread(ipAddress, portNumber);
socketThread.addDisconnectionListener((cause) -> {
@@ -106,41 +94,40 @@ public class GameClient {
ViewManager.getInstance().setPlayerList(clientLobbyList);
while (regattaData == null){
int triesLeft = 10;
while (regattaData == null && triesLeft >= 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InterruptedException ignored) {
;
}
triesLeft--;
}
if (triesLeft < 1){
return false;
}
ViewManager.getInstance().setProperty("serverName", regattaData.getRegattaName());
ViewManager.getInstance().setProperty("mapName", regattaData.getCourseName());
getServerThread().setConnectionErrorListener((eMessage) -> {
ViewManager.getInstance().showErrorSnackBar(eMessage);
//destroyClientToServerThread();
});
getServerThread().setConnectionErrorListener((eMessage) -> ViewManager.getInstance().showErrorSnackBar(eMessage));
this.lobbyController = ViewManager.getInstance().goToLobby(true);
} catch (IOException ioe) {
ViewManager.getInstance().showErrorSnackBar("There are no servers currently available.");
}
}
private void destroyClientToServerThread() {
socketThread.closeSocket();
socketThread = null;
return true;
}
/**
* 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(
String ipAddress, Integer portNumber, String serverName, Integer maxPlayers, String race,
String serverName, Integer maxPlayers, String race,
Integer numLegs, Boolean tokensEnabled
) {
XMLGenerator.setDefaultRaceName(serverName);
@@ -156,7 +143,7 @@ public class GameClient {
}
try {
startClientToServerThread(ipAddress, 4942);
startClientToServerThread("localhost", server.getPortNumber());
} catch (IOException e) {
showConnectionError("Cannot connect to server as host");
}
@@ -190,8 +177,11 @@ public class GameClient {
this.lobbyController = ViewManager.getInstance().goToLobby(false);
lobbyController.setPortNumber(""+server.getPortNumber());
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() {
@@ -294,10 +284,12 @@ public class GameClient {
case CHATTER_TEXT:
Pair<Integer, String> playerIdMessagePair = StreamParser
.extractChatterText(packet);
raceView.updateChatHistory(
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
playerIdMessagePair.getValue()
);
if (playerIdMessagePair != null) {
raceView.updateChatHistory(
allBoatsMap.get(playerIdMessagePair.getKey()).getColour(),
playerIdMessagePair.getValue()
);
}
}
}
}
@@ -314,6 +306,7 @@ public class GameClient {
formatAndSendChatMessage(raceView.readChatInput());
}
});
gameKeyBind.toggleTurningMode();
sendToggleTurningModePacket(); // notify the server about player's steering mode
}
}
@@ -333,8 +326,6 @@ public class GameClient {
positionData.getLon(), positionData.getHeading(),
positionData.getGroundSpeed());
}
} else if (positionData.getType() == DeviceType.MARK_TYPE) {
//CompoundMark mark = courseData.getCompoundMarks().get(positionData.getDeviceId());
}
}
@@ -372,21 +363,17 @@ public class GameClient {
ClientYacht clientYacht = allBoatsMap.get((int) boatData[0]);
clientYacht.setEstimateTimeTillNextMark(raceState.getRaceTime() - boatData[1]);
clientYacht.setEstimateTimeAtFinish(boatData[2]);
// int legNumber = (int) boatData[3];
clientYacht.setBoatStatus((int) boatData[4]);
// if (legNumber != clientYacht.getLegNumber()) {
// clientYacht.setLegNumber(legNumber);
// }
}
if (raceFinished) {
raceViewController.showFinishDialog(finishedBoats);
if (raceFinished && !raceState.getRaceFinished()) {
raceState.setRaceFinished();
Sounds.playFinishSound();
close();
ViewManager.getInstance().getGameClient().stopGame();
raceViewController.showFinishDialog(finishedBoats);
// close();
// ViewManager.getInstance().getGameClient().stopGame();
//loadFinishScreenView();
}
raceState.setRaceFinished();
}
}
@@ -397,10 +384,6 @@ public class GameClient {
}
}
private void close() {
socketThread.setSocketToClose();
}
/**
* Handle the key-pressed event from the text field.
* @param e The key event triggering this call
@@ -527,10 +510,6 @@ public class GameClient {
return socketThread;
}
public List<String> getPlayerNames(){
return Collections.unmodifiableList(clientLobbyList.sorted());
}
public void stopGame() {
GameState.setCurrentStage(GameStages.CANCELLED);
if (server != null) server.terminate();
@@ -1,13 +1,18 @@
package seng302.visualiser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javafx.scene.Group;
import javafx.scene.Node;
import seng302.model.ClientYacht;
import seng302.model.Limit;
import seng302.model.ScaledPoint;
import seng302.model.mark.CompoundMark;
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.
@@ -24,8 +29,36 @@ public abstract class GameView {
List<CompoundMark> course = new ArrayList<>();
List<CompoundMark> compoundMarks = new ArrayList<>();
List<Corner> courseOrder = new ArrayList<>();
HashMap<Mark, Marker> markerObjects = new HashMap<>();
public abstract Node getAssets();
public abstract void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence);
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();
}
}
}
}
}
@@ -2,12 +2,12 @@ package seng302.visualiser;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.geometry.Point3D;
import javafx.scene.Camera;
@@ -24,13 +24,16 @@ import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import org.fxyz3d.scene.Skybox;
import seng302.gameServer.messages.RoundingSide;
import seng302.model.*;
import seng302.model.ClientYacht;
import seng302.model.GameKeyBind;
import seng302.model.KeyAction;
import seng302.model.Limit;
import seng302.model.ScaledPoint;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner;
import seng302.model.mark.Mark;
import seng302.model.token.Token;
import seng302.utilities.GeoUtility;
import seng302.utilities.Sounds;
import seng302.visualiser.cameras.ChaseCamera;
import seng302.visualiser.cameras.IsometricCamera;
import seng302.visualiser.cameras.RaceCamera;
@@ -47,11 +50,11 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
* Collection of animated3D assets that displays a race.
*/
public class GameView3D extends GameView{
public class GameView3D extends GameView {
private final double FOV = 60;
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 SubScene view;
@@ -62,10 +65,7 @@ public class GameView3D extends GameView{
private PerspectiveCamera isometricCam;
private PerspectiveCamera topDownCam;
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 Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
private Group wakesGroup = new Group();
private Group boatObjectGroup = new Group();
@@ -89,11 +89,11 @@ public class GameView3D extends GameView{
}
gameObjects = new Group();
root3D = new Group(isometricCam, gameObjects);
root3D = new Group(chaseCam, gameObjects);
view = new SubScene(
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.getTransforms().addAll(new Rotate(90, Rotate.X_AXIS));
@@ -331,9 +331,36 @@ public class GameView3D extends GameView{
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
newBoat.setMarkIndicator(ModelFactory.importSTL("mark_pointer.stl"));
playerBoat = newBoat;
}
}
Platform.runLater(() -> {
ClientYacht playerYacht = ViewManager.getInstance().getGameClient().getAllBoatsMap()
.get(ViewManager.getInstance().getGameClient().getServerThread().getClientId());
for (ObservableValue o : Arrays
.asList(playerBoat.layoutXProperty(), playerBoat.layoutXProperty())) {
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)));
}
if (midPoint != null) {
playerBoat.updateMarkIndicator(midPoint);
}
}
});
}
gameObjects.getChildren().addAll(wakes);
gameObjects.getChildren().addAll(boatObjectGroup);
});
@@ -469,6 +496,7 @@ public class GameView3D extends GameView{
}
public void setBoatAsPlayer (ClientYacht playerYacht) {
playerBoat.updateMarkIndicator(scaledPoint.findScaledXY(course.get(0).getMidPoint()));
playerYacht.toggleSail();
playerBoatAnimationTimer = new AnimationTimer() {
@@ -502,31 +530,4 @@ public class GameView3D extends GameView{
public void setWindDir(double 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;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
@@ -35,7 +34,8 @@ public class MapMaker {
private int index = 0;
private XMLGenerator xmlGenerator = new XMLGenerator();
private List<String> maps = new ArrayList<>(Arrays.asList("default.xml", "horseshoe.xml"));
private List<String> maps = new ArrayList<>(
Arrays.asList("default.xml", "horseshoe.xml", "loop.xml", "madagascar.xml", "waiheke.xml"));
public static MapMaker getInstance() {
if (instance == null) {
@@ -108,10 +108,6 @@ public class MapMaker {
return mapPreviews.get(index).getAssets();
}
public RaceXMLData getCurrentRace() {
return races.get(index);
}
public RegattaXMLData getCurrentRegatta() {
return regattas.get(index);
}
@@ -3,7 +3,6 @@ package seng302.visualiser;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.application.Platform;
import javafx.geometry.Point2D;
import javafx.scene.Node;
@@ -19,6 +18,7 @@ import seng302.model.mark.Corner;
import seng302.model.mark.Mark;
import seng302.utilities.GeoUtility;
import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.Marker;
import seng302.visualiser.fxObjects.assets_2D.CourseBoundary;
import seng302.visualiser.fxObjects.assets_2D.Gate;
import seng302.visualiser.fxObjects.assets_2D.Marker2D;
@@ -29,7 +29,6 @@ import seng302.visualiser.fxObjects.assets_2D.Marker2D;
public class MapPreview extends GameView {
private Polygon raceBorder = new CourseBoundary();
private Map<Mark, Marker2D> markerObjects;
public MapPreview(List<CompoundMark> marks, List<Corner> course, List<Limit> border) {
this.compoundMarks = marks;
@@ -240,7 +239,7 @@ public class MapPreview extends GameView {
* @param colour The desired colour of the 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.startXProperty().bind(
m1.layoutXProperty()
@@ -0,0 +1,51 @@
package seng302.visualiser;
import java.util.HashMap;
import java.util.List;
import javafx.application.Platform;
import javafx.geometry.Point2D;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.transform.Rotate;
import seng302.model.ClientYacht;
import seng302.model.Limit;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Corner;
/**
* Class converts a map preview to a minimap by adding boats.
*/
public class MiniMap extends MapPreview {
private HashMap<ClientYacht, Polygon> boatIcons = new HashMap<>();
public MiniMap (List<CompoundMark> marks, List<Corner> course, List<Limit> border, List<ClientYacht> boats, ClientYacht player) {
super(marks, course, border);
setBoats(boats);
player.addMarkRoundingListener(this::updateMarkArrows);
}
public void setBoats(List<ClientYacht> yachts) {
for (ClientYacht yacht : yachts) {
Polygon boatIcon = new Polygon(0, -3.5, 3.5, 3.5, -3.5, 3.5);
boatIcon.setStroke(Color.BLACK);
boatIcon.setFill(Color.GRAY);
boatIcon.setFill(yacht.getColour());
boatIcon.setFill(yacht.getColour());
boatIcons.put(yacht, boatIcon);
boatIcon.getTransforms().add(new Rotate(0));
yacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
Platform.runLater(() -> {
Polygon bi = boatIcons.get(boat);
Point2D p2d = scaledPoint.findScaledXY(lat, lon);
bi.setLayoutX(p2d.getX());
bi.setLayoutY(p2d.getY());
((Rotate) bi.getTransforms().get(0)).setAngle(heading);
});
});
}
Platform.runLater(() -> {
gameObjects.getChildren().addAll(boatIcons.values());
});
}
}
@@ -1,17 +1,17 @@
package seng302.visualiser;
import seng302.gameServer.ServerAdvertiser;
import seng302.gameServer.ServerDescription;
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
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.ServiceEvent;
import javax.jmdns.ServiceListener;
import javax.jmdns.impl.JmDNSImpl;
import java.io.IOException;
import java.net.InetAddress;
import java.util.*;
import static seng302.gameServer.ServerAdvertiser.getLocalHostIp;
import seng302.gameServer.ServerAdvertiser;
import seng302.gameServer.ServerDescription;
/**
* Listens for servers on the local network
@@ -58,7 +58,7 @@ public class ServerListener{
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
jmdns.requestServiceInfo(ServerAdvertiser.SERVICE_TYPE, serverName);
@@ -94,13 +94,6 @@ public class ServerListener{
listener = new GameServeMonitor();
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 {
@@ -134,7 +127,7 @@ public class ServerListener{
for (ServerDescription server : servers){
if (server.serverShouldBeRemoved()){
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 PAN_LIMIT = 160.0;
private final Double NEAR_ZOOM_LIMIT = -50.0;
private final Double FAR_ZOOM_LIMIT = -160.0;
private final Double NEAR_ZOOM_LIMIT = -30.0;
private final Double FAR_ZOOM_LIMIT = -180.0;
private Double horizontalPan;
private Double verticalPan;
@@ -29,7 +29,7 @@ public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
super(true);
transforms = this.getTransforms();
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
zoomFactor = FAR_ZOOM_LIMIT;
horizontalPan = cameraStartX;
verticalPan = cameraStartY;
@@ -11,9 +11,9 @@ import seng302.visualiser.fxObjects.assets_3D.BoatObject;
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
private final Double PAN_LIMIT = 30.0;
private final Double NEAR_ZOOM_LIMIT = -30.0;
private final Double FAR_ZOOM_LIMIT = -130.0;
private final Double PAN_LIMIT = 40d;
private final Double NEAR_ZOOM_LIMIT = -20.0;
private final Double FAR_ZOOM_LIMIT = -200d;
private final Double ZOOM_STEP = 2.5;
private ObservableList<Transform> transforms;
@@ -27,7 +27,7 @@ public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
super(true);
transforms = this.getTransforms();
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
zoomFactor = FAR_ZOOM_LIMIT;
horizontalPan = 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();
}
}
@@ -2,17 +2,33 @@ package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.collections.ListChangeListener;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import seng302.discoveryServer.DiscoveryServerClient;
import seng302.gameServer.GameStages;
import seng302.gameServer.GameState;
@@ -27,13 +43,10 @@ import seng302.utilities.Sounds;
import seng302.visualiser.MapPreview;
import seng302.visualiser.controllers.cells.PlayerCell;
import seng302.visualiser.controllers.dialogs.BoatCustomizeController;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import seng302.visualiser.controllers.dialogs.PopupDialogController;
import seng302.visualiser.controllers.dialogs.TokenInfoDialogController;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.fxObjects.assets_3D.ModelType;
public class LobbyController implements Initializable {
@@ -57,10 +70,15 @@ public class LobbyController implements Initializable {
private AnchorPane serverMap;
@FXML
private Label roomLabel;
@FXML
private Label portNumber;
@FXML
private Pane speedTokenPane, handlingTokenPane, windWalkerTokenPane, bumperTokenPane, randomTokenPane;
//---------FXML END---------//
private RaceState raceState;
private JFXDialog customizationDialog;
private JFXDialog tokenInfoDialog;
public Color playersColor;
private Map<Integer, ClientYacht> playerBoats;
private Double mapWidth = INITIAL_MAP_WIDTH, mapHeight = INITIAL_MAP_HEIGHT;
@@ -69,6 +87,8 @@ public class LobbyController implements Initializable {
@Override
public void initialize(URL location, ResourceBundle resources) {
roomLabel.setText("");
portNumber.setText("");
this.playerBoats = ViewManager.getInstance().getGameClient().getAllBoatsMap();
if (this.playersColor == null) {
@@ -128,6 +148,107 @@ public class LobbyController implements Initializable {
beginRaceButton.setOnMouseEntered(e -> Sounds.playHoverSound());
initMapPreview();
initTokenPreviews();
}
/**
* Initialises the tokens in the side panel
*/
private void initTokenPreviews() {
Group speedToken = ModelFactory.importModel(ModelType.VELOCITY_PICKUP).getAssets();
Group handlingToken = ModelFactory.importModel(ModelType.HANDLING_PICKUP).getAssets();
Group windWalkerToken = ModelFactory.importModel(ModelType.WIND_WALKER_PICKUP).getAssets();
Group bumperToken = ModelFactory.importModel(ModelType.BUMPER_PICKUP).getAssets();
Group randomToken = ModelFactory.importModel(ModelType.RANDOM_PICKUP).getAssets();
HashMap<Pane, Group> tokenPanes = new HashMap<>();
tokenPanes.put(speedTokenPane, speedToken);
tokenPanes.put(handlingTokenPane, handlingToken);
tokenPanes.put(windWalkerTokenPane, windWalkerToken);
tokenPanes.put(bumperTokenPane, bumperToken);
tokenPanes.put(randomTokenPane, randomToken);
Scale hoverScale = new Scale(1.2, 1.2, 1.2);
tokenPanes.entrySet().forEach((entry) -> {
Pane thisPane = entry.getKey();
Group thisToken = entry.getValue();
thisToken.getTransforms().addAll(
new Translate(40, 50, 0),
new Scale(13, 13, 13));
thisPane.setOnMouseEntered(event -> {
thisToken.getTransforms().add(hoverScale);
});
thisPane.setOnMouseExited(event -> {
thisToken.getTransforms().remove(hoverScale);
});
thisPane.setOnMouseReleased(event -> {
tokenInfoDialog = makeTokenDialog(thisPane);
tokenInfoDialog.show();
});
thisPane.getChildren().add(thisToken);
});
//Hacky rotations for wind and random to level it in the plane
windWalkerToken.getTransforms().addAll(
new Rotate(-70, new Point3D(1, 0, 0)),
new Translate(0, 2,0)
);
randomToken.getTransforms().addAll(
new Rotate(-90, new Point3D(1, 0, 0)),
new Translate(0, 0,1)
);
}
private JFXDialog makeTokenDialog(Pane inducingPane) {
String header = "...";
String body = "Nothing to see here";
ModelType modelType = ModelType.RANDOM_PICKUP;
if (inducingPane == speedTokenPane) {
header = "Speed Boost";
body = "Increases your max velocity";
modelType = ModelType.VELOCITY_PICKUP;
} else if (inducingPane == handlingTokenPane) {
header = "Handling Boost";
body = "Increases your turing rate";
modelType = ModelType.HANDLING_PICKUP;
} else if (inducingPane == windWalkerTokenPane) {
header = "Wind Walker";
body = "The wind now rotates with you, giving you your optimal speed in all directions";
modelType = ModelType.WIND_WALKER_PICKUP;
} else if (inducingPane == bumperTokenPane) {
header = "Bumper";
body = "While this is active, upon hitting another boat, you will power it down for a short time";
modelType = ModelType.BUMPER_PICKUP;
} else if (inducingPane == randomTokenPane) {
header = "Random";
body = "A 50% chance of becoming any other token and a 50% chance of slowing your boat for a time";
modelType = ModelType.RANDOM_PICKUP;
}
FXMLLoader dialog = new FXMLLoader(
getClass().getResource("/views/dialogs/TokenInfoDialog.fxml"));
JFXDialog tokenInfoDialog = null;
try {
tokenInfoDialog = new JFXDialog(serverListMainStackPane, dialog.load(),
JFXDialog.DialogTransition.CENTER);
} catch (IOException e) {
e.printStackTrace();
}
TokenInfoDialogController controller = dialog.getController();
controller.setParentController(this);
controller.setHeader(header);
controller.setContent(body);
controller.setToken(modelType);
return tokenInfoDialog;
}
private JFXDialog createCustomizeDialog() {
@@ -252,7 +373,15 @@ public class LobbyController implements Initializable {
customizationDialog.close();
}
public void closeTokenInfoDialog() {
tokenInfoDialog.close();
}
public void setRoomCode(String roomCode) {
roomLabel.setText("Room: " + roomCode);
}
public void setPortNumber(String p){
portNumber.setText("Port: " + p);
}
}
@@ -4,67 +4,38 @@ import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXDialog;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javafx.animation.RotateTransition;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.SubScene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polyline;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
import seng302.model.ClientYacht;
import seng302.model.RaceState;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.token.TokenType;
import seng302.utilities.Sounds;
import seng302.visualiser.GameView3D;
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
import seng302.visualiser.MiniMap;
import seng302.visualiser.controllers.dialogs.FinishDialogController;
import seng302.visualiser.fxObjects.ChatHistory;
import seng302.visualiser.fxObjects.assets_2D.WindArrow;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
/**
* Controller class that manages the display of a race
*/
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
public class RaceViewController extends Thread {
private final int CHAT_LIMIT = 128;
private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6;
@@ -75,39 +46,19 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
@FXML
private ImageView loadingScreen;
@FXML
private Pane basePane;
@FXML
private JFXButton chatSend;
@FXML
private Pane chatHistoryHolder;
@FXML
private JFXButton chatToggleButton;
@FXML
private TextField chatInput;
@FXML
private LineChart<String, Double> raceSparkLine;
@FXML
private NumberAxis sparklineYAxis;
@FXML
private VBox positionVbox;
@FXML
private CheckBox toggleFps;
@FXML
private Label timerLabel;
@FXML
private StackPane contentStackPane;
private GridPane contentGridPane;
@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;
private Pane miniMapPane;
@FXML
private ImageView windImageView;
@FXML
@@ -118,33 +69,26 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
@FXML
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
@FXML
private JFXButton miniMapButton;
//Race Data
private Map<Integer, ClientYacht> participants;
private Map<Integer, CompoundMark> markers;
private RaceXMLData courseData;
private GameView3D gameView;
private RaceState raceState;
private ChatHistory chatHistory;
private Timeline timerTimeline;
private Timer timer = new Timer();
private List<Series<String, Double>> sparkLineData = new ArrayList<>();
private ImportantAnnotationsState importantAnnotations;
private Polyline windArrow = new WindArrow(Color.LIGHTGRAY);
private ObservableList<ClientYacht> selectionComboBoxList = FXCollections.observableArrayList();
private ClientYacht player;
private JFXDialog finishScreenDialog;
private FinishDialogController finishDialogController;
//Icon stuff
private Timer blinkingTimer = new Timer();
private ImageView iconToDisplay;
private Double lastWindDirection;
private MiniMap miniMap;
public void initialize() {
miniMapPane.setVisible(false);
miniMapButton.setVisible(false);
chatHistoryHolder.setVisible(false);
chatToggleButton.setVisible(false);
contentStackPane.setVisible(false);
Image loadingImage = new Image("PP.png");
loadingScreen.setImage(loadingImage);
@@ -180,6 +124,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
chatHistoryHolder.heightProperty()
);
contentStackPane.getChildren().remove(chatToggleButton);
contentStackPane.getChildren().add(chatToggleButton);
contentStackPane.setOnMouseClicked(event -> {
contentStackPane.requestFocus();
});
@@ -204,13 +151,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
public void showView(){
loadingScreenPane.setVisible(false);
contentStackPane.setVisible(true);
miniMapPane.setVisible(true);
miniMapButton.setVisible(true);
chatHistoryHolder.setVisible(true);
chatToggleButton.setVisible(true);
Platform.runLater(new Runnable() {
@Override
public void run() {
contentStackPane.requestFocus();
}
});
Platform.runLater(() -> contentStackPane.requestFocus());
}
/**
@@ -238,31 +184,46 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
ClientYacht player) {
this.participants = participants;
this.courseData = raceData;
this.markers = raceData.getCompoundMarks();
this.raceState = raceState;
this.player = player;
raceState.getPlayerPositions().addListener((ListChangeListener<ClientYacht>) c -> {
while (c.next()) {
if (c.wasPermutated()) {
updateOrder(raceState.getPlayerPositions());
}
}
});
player.addPowerUpListener(this::displayPowerUpIcon);
player.addPowerDownListener(this::removeIcon);
updateOrder(raceState.getPlayerPositions());
gameView = new GameView3D();
miniMap = new MiniMap(
new ArrayList<>(raceData.getCompoundMarks().values()),
raceData.getMarkSequence(), raceData.getCourseLimit(),
new ArrayList<>(participants.values()), player
);
miniMapButton.setOnMouseClicked((event) -> {
if (miniMapPane.visibleProperty().get()) {
miniMapPane.setVisible(false);
miniMapButton.setText("+");
} else {
miniMapPane.setVisible(true);
miniMapButton.setText("");
}
});
chatToggleButton.setOnMouseClicked((event) -> {
if (chatHistoryHolder.visibleProperty().get()) {
chatHistoryHolder.setVisible(false);
chatToggleButton.setText("+");
} else {
chatHistoryHolder.setVisible(true);
chatToggleButton.setText("");
}
});
Platform.runLater(() -> {
contentStackPane.getChildren().add(0, gameView.getAssets());
((SubScene) gameView.getAssets()).widthProperty()
.bind(ViewManager.getInstance().getStage().widthProperty());
((SubScene) gameView.getAssets()).heightProperty()
.bind(ViewManager.getInstance().getStage().heightProperty());
miniMapPane.getChildren().add(miniMap.getAssets());
});
gameView.setBoats(new ArrayList<>(participants.values()));
gameView.updateBorder(raceData.getCourseLimit());
@@ -342,7 +303,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
}
public void removeIcon(ClientYacht yacht) {
private void removeIcon(ClientYacht yacht) {
if (yacht == player) {
blinkingTimer.cancel();
iconToDisplay.setVisible(false);
@@ -350,45 +311,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
}
/**
* The important annotations have been changed, update this view
*
* @param importantAnnotationsState The current state of the selected annotations
*/
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) {
this.importantAnnotations = importantAnnotationsState;
setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations
}
/**
* Loads the "select annotations" view in a new window
*/
private void loadSelectAnnotationView() {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
Stage stage = new Stage();
// Set controller
ImportantAnnotationController controller = new ImportantAnnotationController(
this, stage
);
fxmlLoader.setController(controller);
// Load FXML and set CSS
fxmlLoader.setLocation(
getClass().getResource("/views/importantAnnotationSelectView.fxml")
);
Scene scene = new Scene(fxmlLoader.load(), 469, 298);
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
stage.initStyle(StageStyle.UNDECORATED);
stage.setScene(scene);
stage.show();
controller.loadState(importantAnnotations);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Initialises a timer which updates elements of the RaceView such as wind direction, yacht
* orderings etc.. which are dependent on the info from the stream parser constantly.
@@ -406,35 +328,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}, 0, 1000);
}
/**
* Iterates over all corners until ones SeqID matches with the yachts current leg number.
* Then it gets the compoundMarkID of that corner and uses it to fetch the appropriate mark
* Returns null if no next mark found.
* @param bg The BoatGroup to find the next mark of
* @return The next Mark or null if none found
*/
private Mark getNextMark(BoatObject bg) {
// TODO: 1/08/17 Move to GameView
//
// Integer legNumber = bg.getClientYacht().getLegNumber();
// List<Corner> markSequence = courseData.getMarkSequence();
//
// if (legNumber == 0) {
// return null;
// } else if (legNumber == markSequence.size() - 1) {
// return null;
// }
//
// for (Corner corner : markSequence) {
// if (legNumber + 2 == corner.getSeqID()) {
// return courseData.getCompoundMarks().get(corner.getCompoundMarkID());
// }
// }
// return null;
return null;
}
/**
* Updates the wind direction arrow and text as from info from the StreamParser
* @param direction the from north angle of the wind.
@@ -516,226 +409,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
boatHeadingLabel.setText(String.format("Boat Heading:\n%.1f°", player.getHeading()));
}
/**
* Updates the order of the yachts as from the StreamParser and sets them in the yacht order
* section
*/
private void updateOrder(ObservableList<ClientYacht> yachts) {
// List<Text> vboxEntries = new ArrayList<>();
//
// for (int i = 0; i < yachts.size(); i++) {
//// System.out.println("yacht == null " + String.valueOf(yacht == null));
// if (yachts.get(i).getBoatStatus() == BoatStatus.FINISHED
// .getCode()) { // 3 is finish status
// Text textToAdd = new Text(i + 1 + ". " +
// yachts.get(i).getShortName() + " (Finished)");
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
// vboxEntries.add(textToAdd);
//
// } else {
// Text textToAdd = new Text(i + 1 + ". " +
// yachts.get(i).getShortName() + " ");
// textToAdd.setFill(Paint.valueOf("#d3d3d3"));
// textToAdd.setStyle("");
// vboxEntries.add(textToAdd);
// }
// }
// Platform.runLater(() ->
// positionVbox.getChildren().setAll(vboxEntries)
// );
}
private void updateLaylines(BoatObject bg) {
// TODO: 1/08/17 move to GameView
//
// Mark nextMark = getNextMark(bg);
// Boolean isUpwind = null;
// // Can only calc leg direction if there is a next mark and it is a gate mark
// if (nextMark != null) {
// if (nextMark instanceof GateMark) {
// if (bg.isUpwindLeg(gameViewController, nextMark)) {
// isUpwind = true;
// } else {
// isUpwind = false;
// }
//
// for(MarkObject mg : gameViewController.getMarkGroups()) {
//
// mg.removeLaylines();
//
// if (mg.getMainMark().getId() == nextMark.getId()) {
//
// SingleMark singleMark1 = ((GateMark) nextMark).getSingleMark1();
// SingleMark singleMark2 = ((GateMark) nextMark).getSingleMark2();
// Point2D markPoint1 = gameViewController
// .findScaledXY(singleMark1.getLatitude(), singleMark1.getLongitude());
// Point2D markPoint2 = gameViewController
// .findScaledXY(singleMark2.getLatitude(), singleMark2.getLongitude());
// HashMap<Double, Double> angleAndSpeed;
// if (isUpwind) {
// angleAndSpeed = PolarTable.getOptimalUpwindVMG(StreamParser.getWindSpeed());
// } else {
// angleAndSpeed = PolarTable.getOptimalDownwindVMG(StreamParser.getWindSpeed());
// }
//
// Double resultingAngle = angleAndSpeed.keySet().iterator().next();
//
//
// Point2D yachtCurrentPos = new Point2D(bg.getBoatLayoutX(), bg.getBoatLayoutY());
// Point2D gateMidPoint = markPoint1.midpoint(markPoint2);
// Integer lineFuncResult = GeoUtility.lineFunction(yachtCurrentPos, gateMidPoint, markPoint2);
// Line rightLayline = new Line();
// Line leftLayline = new Line();
// if (lineFuncResult == 1) {
// rightLayline = makeRightLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
// leftLayline = makeLeftLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
// } else if (lineFuncResult == -1) {
// rightLayline = makeRightLayline(markPoint1, 180 - resultingAngle, StreamParser.getWindDirection());
// leftLayline = makeLeftLayline(markPoint2, 180 - resultingAngle, StreamParser.getWindDirection());
// }
//
// leftLayline.setStrokeWidth(0.5);
// leftLayline.setStroke(bg.getBoat().getColour());
//
// rightLayline.setStrokeWidth(0.5);
// rightLayline.setStroke(bg.getBoat().getColour());
//
// bg.setLaylines(leftLayline, rightLayline);
// mg.addLaylines(leftLayline, rightLayline);
//
// }
// }
// }
// }
}
private Point2D getPointRotation(Point2D ref, Double distance, Double angle) {
Double newX = ref.getX() + (ref.getX() + distance - ref.getX()) * Math.cos(angle)
- (ref.getY() + distance - ref.getY()) * Math.sin(angle);
Double newY = ref.getY() + (ref.getX() + distance - ref.getX()) * Math.sin(angle)
+ (ref.getY() + distance - ref.getY()) * Math.cos(angle);
return new Point2D(newX, newY);
}
public Line makeLeftLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) {
Point2D ep = getPointRotation(startPoint, 50.0, baseAngle + layLineAngle);
Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY());
return line;
}
public Line makeRightLayline(Point2D startPoint, Double layLineAngle, Double baseAngle) {
Point2D ep = getPointRotation(startPoint, 50.0, baseAngle - layLineAngle);
Line line = new Line(startPoint.getX(), startPoint.getY(), ep.getX(), ep.getY());
return line;
}
/**
* Initialised the combo box with any yachts currently in the race and adds the required listener
* for the combobox to take action upon selection
*/
private void initialiseBoatSelectionComboBox() {
// yachtSelectionComboBox.setItems(
// FXCollections.observableArrayList(participants.values())
// );
// //Null check is if the listener is fired but nothing selected
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
// if (selectedBoat != null) {
// gameView.selectBoat(selectedBoat);
// }
// });
//TODO uncomment out
// selectionComboBoxList.setAll(participants.values());
// yachtSelectionComboBox.setItems(selectionComboBoxList);
// yachtSelectionComboBox.valueProperty().addListener((obs, lastSelection, selectedBoat) -> {
// if (selectedBoat != null) {
// gameView.selectBoat(selectedBoat);
// }
// });
}
/**
* Display the list of yachts in the order they finished the race
*/
private void loadRaceResultView() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml"));
try {
contentGridPane.getChildren().removeAll();
contentGridPane.getChildren().clear();
contentGridPane.getChildren().addAll((Pane) loader.load());
} catch (javafx.fxml.LoadException e) {
System.err.println(e.getCause().toString());
} catch (IOException e) {
System.err.println(e.toString());
}
}
private String getMillisToFormattedTime(long milliseconds) {
return String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(milliseconds),
TimeUnit.MILLISECONDS.toMinutes(milliseconds) % 60, //Modulus 60 minutes per hour
TimeUnit.MILLISECONDS.toSeconds(milliseconds) % 60 //Modulus 60 seconds per minute
);
}
private void setAnnotations(Integer annotationLevel) {
// switch (annotationLevel) {
// // No Annotations
// case 0:
// gameView.setAnnotationVisibilities(
// false, false, false, false, false, false
// );
// break;
// // Important Annotations
// case 1:
// gameView.setAnnotationVisibilities(
// importantAnnotations.getAnnotationState(Annotation.NAME),
// importantAnnotations.getAnnotationState(Annotation.SPEED),
// importantAnnotations.getAnnotationState(Annotation.ESTTIMETONEXTMARK),
// importantAnnotations.getAnnotationState(Annotation.LEGTIME),
// importantAnnotations.getAnnotationState(Annotation.TRACK),
// importantAnnotations.getAnnotationState(Annotation.WAKE)
// );
// break;
// // All Annotations
// case 2:
// gameView.setAnnotationVisibilities(
// true, true, true, true, true, true
// );
// break;
// }
}
/**
* Sets all the annotations of the selected yacht to be visible and all others to be hidden
*
* @param yacht The yacht for which we want to view all annotations
*/
private void setSelectedBoat(ClientYacht yacht) {
// for (BoatObject bg : gameViewController.getBoatGroups()) {
// //We need to iterate over all race groups to get the matching yacht group belonging to this yacht if we
// //are to toggle its annotations, there is no other backwards knowledge of a yacht to its yachtgroup.
// if (bg.getBoat().getHullID().equals(yacht.getHullID())) {
//// updateLaylines(bg);
// bg.setIsSelected(true);
//// selectedBoat = yacht;
// } else {
// bg.setIsSelected(false);
// }
// }
}
public void updateTokens(RaceXMLData raceData) {
gameView.updateTokens(raceData.getTokens());
@@ -140,7 +140,9 @@ public class ServerListController implements Initializable, ServerListenerDelega
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");
}
});
/*
@@ -1,26 +1,15 @@
package seng302.visualiser.controllers;
import com.jfoenix.controls.JFXDecorator;
import com.jfoenix.controls.JFXSnackbar;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import seng302.gameServer.ServerAdvertiser;
import seng302.utilities.Sounds;
import seng302.visualiser.GameClient;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* The pre loading screen before launch the start view
* Created by Kusal on 26-Sep-17.
*/
public class SplashScreenController implements Initializable{
@@ -37,18 +26,15 @@ public class SplashScreenController implements Initializable{
class SplashScreen extends Thread {
public void run(){
try {
Thread.sleep(2000);
Platform.runLater(new Runnable() {
@Override
public void run() {
try {
Stage stage = new Stage();
ViewManager.getInstance().initialStartView(stage);
} catch (Exception e) {
e.printStackTrace();
}
rootPane.getScene().getWindow().hide();
Thread.sleep(3000);
Platform.runLater(() -> {
try {
Stage stage = new Stage();
ViewManager.getInstance().initialStartView(stage);
} catch (Exception e) {
e.printStackTrace();
}
rootPane.getScene().getWindow().hide();
});
} catch (InterruptedException e) {
e.printStackTrace();
@@ -6,10 +6,16 @@ import com.jfoenix.controls.JFXDialog;
import com.jfoenix.controls.JFXDialog.DialogTransition;
import com.jfoenix.controls.JFXSnackbar;
import com.jfoenix.svg.SVGGlyph;
import java.io.IOException;
import java.util.HashMap;
import javafx.application.Platform;
import javafx.collections.ObservableList;
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.layout.HBox;
import javafx.scene.layout.StackPane;
@@ -24,9 +30,6 @@ import seng302.visualiser.GameClient;
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
import seng302.visualiser.controllers.dialogs.PopupDialogController;
import java.io.IOException;
import java.util.HashMap;
public class ViewManager {
private static ViewManager instance;
@@ -79,7 +82,7 @@ public class ViewManager {
decorator.applyCss();
decorator.getStylesheets()
.add(getClass().getResource("/css/Master.css").toExternalForm());
gameClient = new GameClient(decorator);
gameClient = new GameClient();
setDecorator(decorator);
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
@@ -302,7 +305,7 @@ public class ViewManager {
Stage stage = new Stage();
initialStartView(stage);
} catch (Exception e) {
e.printStackTrace();
logger.warn("Could not go to start view");
}
}
@@ -376,8 +379,8 @@ public class ViewManager {
scene.setOnKeyPressed(gameClient::keyPressed);
scene.setOnKeyReleased(gameClient::keyReleased);
stage.setMinHeight(500);
stage.setMinWidth(800);
stage.setMinHeight(800);
stage.setMinWidth(1200);
stage.setTitle("Party Parrots At Sea");
stage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
stage.setOnCloseRequest(e -> closeAll());
@@ -404,7 +407,9 @@ public class ViewManager {
.add(getClass().getResource("/css/dialogs/Snackbar.css").toExternalForm());
JFXSnackbar bar = new JFXSnackbar(decorator);
bar.enqueue(new JFXSnackbar.SnackbarEvent(msg));
Platform.runLater(() -> {
bar.enqueue(new JFXSnackbar.SnackbarEvent(msg));
});
}
public Stage getStage() {
@@ -27,7 +27,7 @@ public class KeyBindingDialogController implements Initializable {
@FXML
private Label closeLabel;
@FXML
private JFXButton zoomInbtn;
private JFXButton zoomInBtn;
@FXML
private JFXButton zoomOutBtn;
@FXML
@@ -43,6 +43,8 @@ public class KeyBindingDialogController implements Initializable {
@FXML
private JFXButton resetBtn;
@FXML
private JFXButton confirmBtn;
@FXML
private Label upwindLabel;
@FXML
private Label downwindLabel;
@@ -70,7 +72,7 @@ public class KeyBindingDialogController implements Initializable {
gameKeyBind = GameKeyBind.getInstance();
buttons = new ArrayList<>();
Collections.addAll(buttons,
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn,
zoomInBtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn,
viewButton, rightButton, leftButton, forwardButton, backwardButton);
bindButtonWithAction();
loadKeyBind();
@@ -91,6 +93,7 @@ public class KeyBindingDialogController implements Initializable {
});
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
confirmBtn.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
}
/**
@@ -115,7 +115,7 @@ public class ServerCreationController implements Initializable {
*/
private void createServer() {
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());
if (serverDescription == null){
@@ -0,0 +1,90 @@
package seng302.visualiser.controllers.dialogs;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTextArea;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Translate;
import seng302.utilities.Sounds;
import seng302.visualiser.controllers.LobbyController;
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
import seng302.visualiser.fxObjects.assets_3D.ModelType;
/**
* Created by wmu16 on 28/09/17.
*/
public class TokenInfoDialogController implements Initializable {
@FXML
private Label headerLabel;
@FXML
private TextArea contentText;
@FXML
private Pane tokenPane;
@FXML
private Button optionButton;
private LobbyController lobbyController;
@Override
public void initialize(URL location, ResourceBundle resources) {
optionButton.setOnMouseReleased(event -> {
Sounds.playButtonClick();
lobbyController.closeTokenInfoDialog();
});
contentText.setEditable(false);
}
public void setContent(String content) {
contentText.setText(content);
}
public void setHeader(String header) {
this.headerLabel.setText(header);
}
public void setToken(ModelType token) {
tokenPane.getChildren().clear();
Group tokenObject = ModelFactory.importModel(token).getAssets();
tokenObject.getTransforms().addAll(
new Translate(138 / 2, 138 / 2, 0),
new Scale(20, 20, 20));
if (token == ModelType.WIND_WALKER_PICKUP) {
tokenObject.getTransforms().addAll(
new Rotate(-70, new Point3D(1, 0, 0)),
new Translate(0, 2, 0)
);
} else if (token == ModelType.RANDOM_PICKUP) {
tokenObject.getTransforms().addAll(
new Rotate(-90, new Point3D(1, 0, 0)),
new Translate(0, 0, 1)
);
}
tokenPane.getChildren().add(tokenObject);
}
public void setParentController(LobbyController lobbyController) {
this.lobbyController = lobbyController;
}
}
@@ -29,11 +29,11 @@ public class MarkArrowFactory {
STARBOARD,
}
public static final double MARK_ARROW_SEPARATION = 15;
public static final double ARROW_LENGTH = 75;
public static final double ARROW_HEAD_DEPTH = 10;
public static final double ARROW_HEAD_WIDTH = 6;
public static final double STROKE_WIDTH = 3;
public static final double MARK_ARROW_SEPARATION = 8;
public static final double ARROW_LENGTH = 20;
public static final double ARROW_HEAD_DEPTH = 5;
public static final double ARROW_HEAD_WIDTH = 3;
public static final double STROKE_WIDTH = 1;
public static Model constructEntryArrow3D (
RoundingSide roundingSide, double angle, ModelType type) {
@@ -106,7 +106,7 @@ public class MarkArrowFactory {
Arc roundSection = new Arc(
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
//Where to start drawing arc from
(roundingSide == RoundingSide.PORT ? 0 : angleOfEntry),
(roundingSide == RoundingSide.PORT ? 180 + angleOfEntry : angleOfEntry),
//Which way to go around the mark. (clockwise vs anticlockwise)
roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit)
);
@@ -0,0 +1,38 @@
package seng302.visualiser.fxObjects;
import java.util.ArrayList;
import java.util.List;
import javafx.scene.Group;
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
/**
* Created by cir27 on 28/09/17.
*/
public abstract class Marker extends Group{
protected List<Group> enterArrows = new ArrayList<>();
protected List<Group> exitArrows = new ArrayList<>();
protected int enterArrowIndex = 0;
protected int exitArrowIndex = 0;
public abstract void addArrows(RoundingSide roundingSide, double entryAngle, double exitAngle);
/**
* Shows the next EnterArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
*/
public void showNextEnterArrow() {
showArrow(enterArrows, enterArrowIndex);
enterArrowIndex++;
}
/**
* Shows the next ExitArrow. Does nothing if there are no more enter arrows. Other arrows become hidden.
*/
public void showNextExitArrow() {
showArrow(exitArrows, exitArrowIndex);
exitArrowIndex++;
}
protected abstract void showArrow(List<Group> arrowList, int arrowListIndex);
public abstract void hideAllArrows();
}
@@ -1,230 +0,0 @@
package seng302.visualiser.fxObjects.assets_2D;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.scene.CacheHint;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
/**
* Grouping of string objects over a semi transparent background.
*/
public class AnnotationBox extends Group {
@FunctionalInterface
public interface AnnotationFormatter<T> {
String transformString (T input);
}
/**
* Class stores a text object and relationship for updating the text object if needed
*
* @param <T> The type of observable value passed to the annotation, if there is one.
*/
public class Annotation<T> {
private Text text;
private ObservableValue<T> source;
private AnnotationFormatter<T> format;
/**
* Constructor for observing annotation
* @param textObject the javaFX text object the annotation is displayed in
* @param source observable value that the annotation is taken from
* @param formatter interface describing how to format the source data if needed
*/
public Annotation (Text textObject, ObservableValue<T> source, AnnotationFormatter<T> formatter) {
this.text = textObject;
this.source = source;
this.format = formatter;
source.addListener((obs, oldVal, newVal) ->
Platform.runLater(() -> text.setText(format.transformString(newVal)))
);
}
/**
* Constructor for a static annotation
* @param textObject the javaFX text object the annotation is displayed in
* @param annotationText the static value of the test object
*/
public Annotation (Text textObject, String annotationText) {
textObject.setText(annotationText);
text = textObject;
}
private Text getText () {
return text;
}
}
//Text offset constants
private static final double X_OFFSET_TEXT = 20d;
private static final double Y_OFFSET_TEXT_INIT = -35d;
private static final double Y_OFFSET_PER_TEXT = 12d;
//Background constants
private static final double TEXT_BUFFER = 3;
private static final double BACKGROUND_X = X_OFFSET_TEXT - TEXT_BUFFER;
private static final double BACKGROUND_Y = Y_OFFSET_TEXT_INIT - TEXT_BUFFER;
private static final double BACKGROUND_H_PER_TEXT = 9.5d;
private static final double BACKGROUND_ARC_SIZE = 10;
private int visibleAnnotations = 0;
private double backgroundWidth = 145d;
private Rectangle background = new Rectangle();
private Paint theme = Color.BLACK;
private Map<String, Annotation> annotationsByName = new HashMap<>();
/**
* Creates an empty annotation box. The box is offset from (0,0) by (17, -38).
*/
public AnnotationBox() {
this.setCache(true);
background.setX(BACKGROUND_X);
background.setY(BACKGROUND_Y);
background.setWidth(backgroundWidth);
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * 4);
background.setArcHeight(BACKGROUND_ARC_SIZE);
background.setArcWidth(BACKGROUND_ARC_SIZE);
background.setFill(new Color(1, 1, 1, 0.75));
background.setStroke(theme);
background.setStrokeWidth(2);
background.setCache(true);
background.setCacheHint(CacheHint.SCALE);
this.getChildren().add(background);
}
/**
* Adds an annotation to the box. Use the name to reference the annotation for removal or\
* changing visibility.
* @param annotationName the name of the annotation.
* @param annotation the annotation.
*/
public void addAnnotation (String annotationName, Annotation annotation) {
annotationsByName.put(annotationName, annotation);
Platform.runLater(() -> {
this.getChildren().add(annotation.getText());
visibleAnnotations++;
update();
});
}
/**
* Adds an annotation with a constant text.
* @param annotationName The name of the annotation. Will be used to reference it later.
* @param annotationText The desired text.
*/
public void addAnnotation (String annotationName, String annotationText) {
Text text = getTextObject();
addAnnotation(annotationName, new Annotation(text, annotationText));
}
/**
* Adds an annotation with the given name. The annotation will contain the value of the given
* ObservableValue. The formatter should return a String and takes an object of the same type as
* the ObservableValue as a parameter. The String is how you want the annotation to look.
* @param annotationName The annotation name.
* @param observable The observable value the annotation will display.
* @param formatter A formatting function for the observable value.
* @param <E> The type of ObservableValue.
*/
public <E> void addAnnotation (String annotationName, ObservableValue<E> observable,
AnnotationFormatter<E> formatter) {
Text newText = getTextObject();
addAnnotation(annotationName, new Annotation<>(newText, observable, formatter));
}
/**
* Sets the visibility of the annotation with the given name if it exists.
* @param annotationName The name of the annotation
* @param visibility the desired visibility
*/
public void setAnnotationVisibility (String annotationName, boolean visibility) {
if (annotationsByName.containsKey(annotationName)) {
Text textField = annotationsByName.get(annotationName).text;
boolean currentState = textField.visibleProperty().get();
if (visibility != currentState) {
if (visibility)
visibleAnnotations++;
else
visibleAnnotations--;
}
textField.setVisible(visibility);
update();
}
}
/**
* Removes the annotation with the given name if it exits.
* @param annotationName The name given when the annotation was created.
*/
public void removeAnnotation (String annotationName) {
if (annotationName.contains(annotationName)) {
Platform.runLater(() -> {
this.getChildren().remove(annotationsByName.remove(annotationName).getText());
visibleAnnotations--;
update();
});
annotationsByName.remove(annotationName);
}
}
/**
* Moves the annotation.
* @param x x location
* @param y y location
*/
public void setLocation (double x, double y) {
Platform.runLater(()-> this.relocate(x + BACKGROUND_X, y + BACKGROUND_Y));
}
/**
* Changes the width of the annotation box. Default is 145.
* @param width new width.
*/
public void setWidth (double width) {
backgroundWidth = width;
Platform.runLater(() -> background.setWidth(backgroundWidth));
}
private void update () {
background.setVisible(visibleAnnotations != 0);
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * visibleAnnotations);
for (int i = 1; i <= visibleAnnotations; i++) {
Text text = (Text) this.getChildren().get(i);
if (text.visibleProperty().get()) {
text.setX(X_OFFSET_TEXT);
text.setY(Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * i);
// });
}
}
}
/**
* Returns a text object for an annotation.
* @return The text object
*/
private Text getTextObject() {
Text text = new Text();
text.setFill(theme);
text.setStrokeWidth(2);
// text.setCacheHint(CacheHint.QUALITY);
text.setCache(true);
return text;
}
/**
* Set the colour of the annotation box's border and text colour.
* @param value desired colour.
*/
public void setFill (Paint value) {
theme = value;
background.setStroke(theme);
annotationsByName.forEach((name, annotation) -> annotation.getText().setFill(theme));
}
}
@@ -1,6 +1,5 @@
package seng302.visualiser.fxObjects.assets_2D;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.scene.Group;
@@ -8,18 +7,15 @@ import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.Marker;
/**
* 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 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.
@@ -28,8 +24,7 @@ public class Marker2D extends Group {
mark.setRadius(5);
mark.setCenterX(0);
mark.setCenterY(0);
Platform.runLater(() -> this.getChildren()
.addAll(mark, new Group())); //Empty group placeholder or arrows.
Platform.runLater(() -> this.getChildren().add(mark));
}
/**
@@ -80,15 +75,12 @@ public class Marker2D extends Group {
exitArrowIndex++;
}
private void showArrow(List<Group> arrowList, int arrowListIndex) {
@Override
protected void showArrow(List<Group> arrowList, int arrowListIndex) {
if (arrowListIndex < arrowList.size()) {
if (arrowListIndex == 1) {
;
}
Platform.runLater(() -> {
this.getChildren().remove(1);
this.getChildren().add(arrowList.get(arrowListIndex));
});
Platform.runLater(() ->
this.getChildren().setAll(mark, arrowList.get(arrowListIndex))
);
}
}
@@ -16,10 +16,6 @@ public class Wake extends Group {
//The number of wakes
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];
@@ -69,34 +65,6 @@ public class Wake extends Group {
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,8 @@ public enum BoatMeshType {
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),
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);
final String hullFile, mastFile, sailFile, jibFile;
final double mastOffset, sailOffset;
@@ -21,7 +22,7 @@ public enum BoatMeshType {
public final double accelerationMultiplier;
public final double turnStep;
final boolean fixedSail;
final static BoatMeshType[] boatTypes = new BoatMeshType[]{DINGHY, CATAMARAN, PIRATE_SHIP, DUCKY, PARROT};
final static BoatMeshType[] boatTypes = new BoatMeshType[]{DINGHY, CATAMARAN, PIRATE_SHIP, DUCKY, PARROT, WAKA};
BoatMeshType(String hullFile, String mastFile, double mastOffset, String sailFile,
double sailOffset, String jibFile, boolean fixedSail, double maxSpeedMultiplier, double accelerationMultiplier, double turnStep) {
@@ -60,7 +60,9 @@ public class BoatModel extends Model {
*/
public void changeColour(Color newColour) {
changeColourChild(HULL_INDEX, newColour);
changeColourChild(MAST_INDEX, newColour);
if (meshType != BoatMeshType.PARROT) {
changeColourChild(MAST_INDEX, newColour);
}
}
private void changeColourChild(int index, Color newColour) {
@@ -4,10 +4,14 @@ import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyDoubleWrapper;
import javafx.geometry.Point2D;
import javafx.geometry.Point3D;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
/**
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
@@ -30,9 +34,10 @@ public class BoatObject extends Group {
private Color colour = Color.BLACK;
private Boolean isSelected = false;
private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
// private Rotate tilt = new Rotate(0, new Point3D(0, 1, 0));
private double previousRotation = 0;
// This stuff only matters to the players boat object.
private MeshView markIndicator;
private MeshView playerIndicator;
private ReadOnlyDoubleWrapper rotationProperty;
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
@@ -81,6 +86,19 @@ public class BoatObject extends Group {
});
}
public void updateMarkIndicator(Point2D markPoint) {
Point2D boatLoc = new Point2D(this.getLayoutX(), this.getLayoutY());
Double angle = Math.toDegrees(
Math.atan2(boatLoc.getY() - markPoint.getY(), boatLoc.getX() - markPoint.getX())) - 90;
Double radius = 0.5;
markIndicator.getTransforms().clear();
markIndicator.getTransforms().addAll(
new Rotate(angle, new Point3D(0, 0, 1)),
new Translate(0, -radius, 0)
);
}
private Double normalizeHeading(double heading, double windDirection) {
Double normalizedHeading = heading - windDirection;
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
@@ -91,14 +109,6 @@ public class BoatObject extends Group {
private void rotateTo(double heading, boolean sailsIn, double windDir) {
rotationProperty.set(heading);
rotation.setAngle(heading);
// if (heading == previousRotation) {
// tilt.setAngle(0);
// } else if (heading < previousRotation) {
// tilt.setAngle(-10);
// } else {
// tilt.setAngle(10);
// }
// previousRotation = heading;
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
if (sailsIn) {
boatAssets.showSail();
@@ -128,6 +138,26 @@ public class BoatObject extends Group {
}
}
public void setMarkIndicator(MeshView indicator) {
this.markIndicator = indicator;
this.getChildren().add(markIndicator);
createPlayerIndicator();
setIndicatorColor();
}
private void createPlayerIndicator() {
MeshView torus = ModelFactory.importSTL("player_circle.stl");
playerIndicator = torus;
this.getChildren().add(torus);
}
public void setIndicatorColor() {
Platform.runLater(() -> {
markIndicator.setMaterial(new PhongMaterial(Color.DARKORANGE));
playerIndicator.setMaterial(new PhongMaterial(colour));
});
}
public Group getWake () {
return wake;
}
@@ -1,22 +1,17 @@
package seng302.visualiser.fxObjects.assets_3D;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Platform;
import javafx.scene.Group;
import seng302.visualiser.fxObjects.MarkArrowFactory;
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
import seng302.visualiser.fxObjects.Marker;
/**
* 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 List<Group> enterArrows = new ArrayList<>();
private List<Group> exitArrows = new ArrayList<>();
private int enterArrowIndex = 0;
private int exitArrowIndex = 0;
private ModelType markType;
private ModelType arrowType;
@@ -60,23 +55,8 @@ public class Marker3D extends Group {
);
}
/**
* 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++;
}
private void showArrow(List<Group> arrowList, int arrowListIndex) {
@Override
protected void showArrow(List<Group> arrowList, int arrowListIndex) {
if (arrowListIndex < arrowList.size()) {
Platform.runLater(() ->
this.getChildren().setAll(mark.getAssets(), arrowList.get(arrowListIndex))
@@ -80,30 +80,6 @@ public class ModelFactory {
return bo;
}
public static BoatModel boatRotatingView(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
boatAssets.getTransforms().addAll(
new Scale(40, 40, 40),
new Rotate(90, new Point3D(0,0,1)),
new Rotate(90, new Point3D(0, 1, 0))
);
final Rotate animationRotate = new Rotate(0, new Point3D(1,1,1));
boatAssets.getTransforms().add(animationRotate);
return new BoatModel(boatAssets, new AnimationTimer() {
private double rotation = 0;
private Rotate rotate = animationRotate;
@Override
public void handle(long now) {
rotation += 0.5;
rotate.setAngle(rotation);
}
}, boatType);
}
public static BoatModel boatGameView(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
boatAssets.getTransforms().setAll(
@@ -115,24 +91,27 @@ public class ModelFactory {
private static Group getUnmodifiedBoatModel(BoatMeshType boatType, Color primaryColour) {
Group boatAssets = new Group();
MeshView hull = importSTL(boatType.hullFile);
MeshView hull = importBoatSTL(boatType.hullFile);
hull.setMaterial(new PhongMaterial(primaryColour));
MeshView sail = importSTL(boatType.sailFile);
boatAssets.getChildren().add(hull);
if (boatType.mastFile != null) {
MeshView mast = importBoatSTL(boatType.mastFile);
mast.setMaterial(new PhongMaterial(primaryColour));
boatAssets.getChildren().add(mast);
} else {
boatAssets.getChildren().add(new MeshView());
}
MeshView sail = importBoatSTL(boatType.sailFile);
sail.setMaterial(
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.BLACK : Color.WHITE)
);
boatAssets.getChildren().addAll(hull, sail);
if (boatType.mastFile != null) {
MeshView mast = importSTL(boatType.mastFile);
mast.setMaterial(new PhongMaterial(primaryColour));
boatAssets.getChildren().add(mast);
}
boatAssets.getChildren().add(sail);
if (boatType.jibFile != null) {
MeshView jib = importSTL(boatType.jibFile);
sail.setMaterial(
MeshView jib = importBoatSTL(boatType.jibFile);
jib.setMaterial(
new PhongMaterial(boatType == BoatMeshType.PARROT ? Color.DARKGRAY : Color.WHITE)
);
boatAssets.getChildren().add(jib);
@@ -141,9 +120,13 @@ public class ModelFactory {
return boatAssets;
}
private static MeshView importSTL(String fileName) {
private static MeshView importBoatSTL(String fileName) {
return importSTL("boatSTLs/" + fileName);
}
public static MeshView importSTL(String fileName) {
StlMeshImporter importer = new StlMeshImporter();
importer.read(ModelFactory.class.getResource("/meshes/boatSTLs/" + fileName));
importer.read(ModelFactory.class.getResource("/meshes/" + fileName));
MeshView importedFile = new MeshView(importer.getImport());
importedFile.setCache(true);
importedFile.setCacheHint(CacheHint.SCALE_AND_ROTATE);
@@ -162,6 +145,10 @@ public class ModelFactory {
assets.setCacheHint(CacheHint.SCALE_AND_ROTATE);
}
switch (tokenType) {
case PLAYER_IDENTIFIER_TORUS:
return makeIdentifierTorus(assets);
case NEXT_MARK_INDICATOR:
return makeNextMarkIndicator(assets);
case VELOCITY_PICKUP:
case BUMPER_PICKUP:
case RANDOM_PICKUP:
@@ -196,6 +183,16 @@ public class ModelFactory {
}
}
private static Model makeIdentifierTorus(Group assets) {
// assets.getChildren().add(new AmbientLight());
return new Model(new Group(assets), null);
}
private static Model makeNextMarkIndicator(Group assets) {
// assets.getChildren().add(new AmbientLight());
return new Model(new Group(assets), null);
}
private static Model makeTokenPickup(Group assets) {
Rotate animationRotate = new Rotate(0, new Point3D(0, 0, 1));
assets.getTransforms().addAll(
@@ -28,7 +28,9 @@ public enum ModelType {
START_ARROW ("start_arrow.dae"),
FINISH_ARROW ("finish_arrow.dae"),
LAND("land.dae"),
LAND_SMOOTH("land_smooth.dae");
LAND_SMOOTH("land_smooth.dae"),
NEXT_MARK_INDICATOR("indicator_arrow.dae"),
PLAYER_IDENTIFIER_TORUS("torus.dae");
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());
}
}
+8
View File
@@ -65,4 +65,12 @@
/*-fx-background-repeat: no-repeat;*/
/*-fx-background-size: cover;*/
-fx-background-color: dodgerblue;
}
.tokenView {
-fx-cursor: hand;
}
.tokenGridView StackPane {
-fx-background-color: white;
}
+17
View File
@@ -5,6 +5,7 @@
#timerGrid{
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
}
GridPane .timer * {
@@ -27,20 +28,24 @@ GridPane .timer * {
#chatHistoryHolder {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
}
#chatInputHolder {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
}
#windGridPane {
-fx-background-color: rgba(255, 255, 255, 0.6);
-fx-effect: -fx-pp-dropshadow-light;
-fx-background-radius: 5;
}
#windHolder {
-fx-background-color: rgba(255, 255, 255, 0.5);
-fx-background-radius: 5;
}
#chatSend {
@@ -63,4 +68,16 @@ GridPane .timer * {
#windImageView {
-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;
}
+45 -5
View File
@@ -1,10 +1,50 @@
#background {
-fx-background-color: #E7F1F8;
.root {
-fx-effect: -fx-pp-dropshadow-dark;
-fx-background-radius: 5;
-fx-padding: 10;
}
#rootPane {
-fx-background-image: url("/images/waves.png");
}
#headText {
-fx-background-color: transparent;
-fx-font-size: 52px;
-fx-text-fill: -fx-pp-light-text-color;
-fx-effect: -fx-pp-dropshadow-headers;
-fx-text-fill: rgb(30, 30, 30);
-fx-effect: -fx-pp-dropshadow-dark;
}
#subHeadLabel {
-fx-text-fill: rgb(30, 30, 30);
-fx-effect: -fx-pp-dropshadow-dark;
-fx-font-size: 12px;
}
.materialDesign-purple .arc {
-fx-stroke: #ab47bc;
}
.materialDesign-blue .arc {
-fx-stroke: #2962ff;
}
.materialDesign-cyan .arc {
-fx-stroke: #00b8d4;
}
.materialDesign-green .arc {
-fx-stroke: #00c853;
}
.materialDesign-yellow .arc {
-fx-stroke: #ffd600;
}
.materialDesign-orange .arc {
-fx-stroke: #ff6d00;
}
.materialDesign-red .arc {
-fx-stroke: #d50000;
}
@@ -0,0 +1,22 @@
.text-area {
-fx-background-insets: 0;
-fx-background-color: transparent, white, transparent, white;
}
.text-area .content {
-fx-background-color: transparent, white, transparent, white;
}
.text-area:focused .content {
-fx-background-color: transparent, white, transparent, white;
}
.text-area:focused {
-fx-highlight-fill: #7ecfff;
}
.text-area .content {
-fx-padding: 10px;
-fx-text-fill: gray;
-fx-highlight-fill: #7ecfff;
}
@@ -35,14 +35,14 @@ JFXToggleButton {
-fx-text-fill: -fx-pp-theme-color;
}
#resetBtn {
#resetBtn, #confirmBtn {
-fx-background-color: -fx-pp-theme-color;
-fx-text-fill: -fx-pp-front-color;
-fx-effect: -fx-pp-dropshadow-light;
-fx-font-size: 18;
}
#resetBtn:hover {
#resetBtn:hover, #confirmBtn:hover {
-fx-font-size: 20;
}
+3 -3
View File
@@ -10,8 +10,8 @@
<Marks>
<CompoundMark CompoundMarkID="1">
<Mark Lat="-14.071412" Lng="47.05756"/>
<Mark Lat="-14.069914" Lng="47.058541"/>
<Mark Lat="-14.070412" Lng="47.05746"/>
<Mark Lat="-14.068014" Lng="47.057541"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2">
<Mark Lat="-14.067194" Lng="47.053818" />
@@ -64,7 +64,7 @@
<CourseLimit>
<Limit Lat="-14.073371" Lng="47.058213" />
<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.06261" Lng="47.071293" />
<Limit Lat="-14.070814" Lng="47.06762" />
+66
View File
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<RaceDefinition>
<CourseName> Loopty Loop </CourseName>
<CentralLat> 57.6679590 </CentralLat>
<CentralLng> 11.8503233 </CentralLng>
<MaxPlayers> 5 </MaxPlayers>
<Marks>
<CompoundMark CompoundMarkID="1">
<Mark Lat="57.6675700" Lng="11.8359880"/>
<Mark Lat="57.667610" Lng="11.833473"/>
</CompoundMark>
<CompoundMark CompoundMarkID="2">
<Mark Lat="57.670914" Lng="11.835263"/>
</CompoundMark>
<CompoundMark CompoundMarkID="3">
<Mark Lat="57.6674596" Lng="11.8417500"/>
<Mark Lat="57.667473" Lng="11.84429"/>
</CompoundMark>
<CompoundMark CompoundMarkID="4">
<Mark Lat="57.6657945" Lng="11.8351409"/>
<Mark Lat="57.6643158" Lng="11.8352297"/>
</CompoundMark>
<CompoundMark CompoundMarkID="5">
<Mark Lat="57.667311" Lng="11.828857"/>
<Mark Lat="57.667334" Lng="11.825853"/>
</CompoundMark>
<CompoundMark CompoundMarkID="6">
<Mark Lat="57.6675700" Lng="11.8359880"/>
<Mark Lat="57.667610" Lng="11.833473"/>
</CompoundMark>
</Marks>
<Course>
<OpeningSegment>
<Corner CompoundMarkID="1" Rounding="PS"/>
<Corner CompoundMarkID="2" Rounding="S"/>
</OpeningSegment>
<RepeatingSegment>
<Corner CompoundMarkID="3" Rounding="SP"/>
<Corner CompoundMarkID="4" Rounding="PS"/>
<Corner CompoundMarkID="5" Rounding="PS"/>
<Corner CompoundMarkID="2" Rounding="S"/>
</RepeatingSegment>
<ClosingSegment>
<Corner CompoundMarkID="6" Rounding="PS"/>
</ClosingSegment>
</Course>
<CourseLimit>
<Limit Lat="57.672937" Lng="11.836257" />
<Limit Lat="57.671239" Lng="11.843078" />
<Limit Lat="57.667128" Lng="11.848022" />
<Limit Lat="57.664512" Lng="11.844839" />
<Limit Lat="57.662515" Lng="11.835569" />
<Limit Lat="57.663939" Lng="11.827501" />
<Limit Lat="57.667542" Lng="11.822952" />
<Limit Lat="57.671123" Lng="11.826858" />
</CourseLimit>
</RaceDefinition>
+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.
@@ -0,0 +1,99 @@
<?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-28T01:59:46</created>
<modified>2017-09-28T01:59:46</modified>
<unit name="meter" meter="1"/>
<up_axis>Z_UP</up_axis>
</asset>
<library_images/>
<library_effects>
<effect id="Material_001-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.3215737 0.002428917 1</color>
</diffuse>
<specular>
<color sid="specular">0.1614584 0.1614584 0.1614584 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_001-material" name="Material_001">
<instance_effect url="#Material_001-effect"/>
</material>
</library_materials>
<library_geometries>
<geometry id="Cone-mesh" name="Cone">
<mesh>
<source id="Cone-mesh-positions">
<float_array id="Cone-mesh-positions-array" count="99">0 1 -1 0 0 1 0.1950902 0.9807853 -1 0.3826835 0.9238795 -1 0.5555703 0.8314696 -1 0.7071068 0.7071068 -1 0.8314697 0.5555702 -1 0.9238795 0.3826834 -1 0.9807853 0.1950902 -1 1 0 -1 0.9807853 -0.1950902 -1 0.9238796 -0.3826833 -1 0.8314697 -0.5555702 -1 0.7071068 -0.7071068 -1 0.5555702 -0.8314697 -1 0.3826833 -0.9238796 -1 0.1950901 -0.9807853 -1 -3.25841e-7 -1 -1 -0.1950907 -0.9807852 -1 -0.3826839 -0.9238793 -1 -0.5555707 -0.8314693 -1 -0.7071073 -0.7071064 -1 -0.83147 -0.5555697 -1 -0.9238799 -0.3826827 -1 -0.9807854 -0.1950893 -1 -1 9.65599e-7 -1 -0.9807851 0.1950913 -1 -0.9238791 0.3826845 -1 -0.8314689 0.5555713 -1 -0.7071059 0.7071077 -1 -0.5555691 0.8314704 -1 -0.3826821 0.9238801 -1 -0.1950888 0.9807856 -1</float_array>
<technique_common>
<accessor source="#Cone-mesh-positions-array" count="33" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cone-mesh-normals">
<float_array id="Cone-mesh-normals-array" count="117">0.08775347 0.8909768 0.4454884 0.2598883 0.8567371 0.4454883 0.4220357 0.7895733 0.4454883 0.5679644 0.6920669 0.4454883 0.6920669 0.5679644 0.4454883 0.7895736 0.4220353 0.4454883 0.8567369 0.2598885 0.4454883 0.8909768 0.08775347 0.4454884 0.8909768 -0.08775347 0.4454884 0.8567371 -0.2598881 0.4454883 0.7895734 -0.4220355 0.4454884 0.6920669 -0.5679644 0.4454883 0.5679644 -0.6920669 0.4454883 0.4220356 -0.7895734 0.4454883 0.2598879 -0.8567371 0.4454885 0.08775335 -0.8909768 0.4454884 -0.08775389 -0.8909767 0.4454883 -0.2598887 -0.8567368 0.4454883 -0.4220361 -0.7895731 0.4454884 -0.5679646 -0.6920668 0.4454883 -0.6920675 -0.5679637 0.4454884 -0.7895734 -0.4220355 0.4454884 -0.8567374 -0.2598869 0.4454883 -0.8909769 -0.08775287 0.4454884 -0.8909766 0.08775418 0.4454883 -0.8567367 0.2598895 0.4454884 -0.7895728 0.4220367 0.4454883 -0.6920663 0.5679652 0.4454883 -0.5679636 0.6920676 0.4454884 -0.4220345 0.789574 0.4454885 -0.259887 0.8567373 0.4454883 -0.08775269 0.8909768 0.4454884 0 0 -1 -3.97508e-6 0 -1 3.97512e-6 0 -1 3.88859e-7 0 -1 -1.36853e-6 0 -1 1.36853e-6 0 -1 -3.88857e-7 0 -1</float_array>
<technique_common>
<accessor source="#Cone-mesh-normals-array" count="39" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="Cone-mesh-vertices">
<input semantic="POSITION" source="#Cone-mesh-positions"/>
</vertices>
<triangles material="Material_001-material" count="62">
<input semantic="VERTEX" source="#Cone-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cone-mesh-normals" offset="1"/>
<p>0 0 1 0 2 0 2 1 1 1 3 1 3 2 1 2 4 2 4 3 1 3 5 3 5 4 1 4 6 4 6 5 1 5 7 5 7 6 1 6 8 6 8 7 1 7 9 7 9 8 1 8 10 8 10 9 1 9 11 9 11 10 1 10 12 10 12 11 1 11 13 11 13 12 1 12 14 12 14 13 1 13 15 13 15 14 1 14 16 14 16 15 1 15 17 15 17 16 1 16 18 16 18 17 1 17 19 17 19 18 1 18 20 18 20 19 1 19 21 19 21 20 1 20 22 20 22 21 1 21 23 21 23 22 1 22 24 22 24 23 1 23 25 23 25 24 1 24 26 24 26 25 1 25 27 25 27 26 1 26 28 26 28 27 1 27 29 27 29 28 1 28 30 28 30 29 1 29 31 29 31 30 1 30 32 30 32 31 1 31 0 31 16 32 24 32 8 32 32 32 0 32 2 32 2 32 3 32 4 32 4 32 5 32 6 32 6 32 7 32 4 32 8 32 9 32 10 32 10 32 11 32 8 32 12 32 13 32 16 32 14 32 15 32 16 32 16 32 17 32 18 32 18 32 19 32 20 32 20 32 21 32 22 32 22 33 23 33 24 33 24 34 25 34 26 34 26 32 27 32 28 32 28 32 29 32 32 32 30 32 31 32 32 32 32 35 2 35 8 35 4 36 7 36 8 36 8 37 11 37 12 37 13 32 14 32 16 32 16 32 18 32 24 32 20 32 22 32 24 32 24 38 26 38 32 38 29 32 30 32 32 32 2 32 4 32 8 32 8 32 12 32 16 32 18 32 20 32 24 32 26 32 28 32 32 32 32 32 8 32 24 32</p>
</triangles>
</mesh>
</geometry>
</library_geometries>
<library_controllers/>
<library_visual_scenes>
<visual_scene id="Scene" name="Scene">
<node id="Cone" name="Cone" type="NODE">
<matrix sid="transform">1 0 0 0 0 1 0 0 0 0 1 1.015816 0 0 0 1</matrix>
<instance_geometry url="#Cone-mesh" name="Cone">
<bind_material>
<technique_common>
<instance_material symbol="Material_001-material" target="#Material_001-material"/>
</technique_common>
</bind_material>
</instance_geometry>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
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>
+117 -12
View File
@@ -1,5 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.net.*?>
<?import javafx.scene.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
@@ -13,7 +21,7 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<StackPane fx:id="serverListMainStackPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.LobbyController">
<children>
<GridPane fx:id="serverListMainGridPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<children>
@@ -58,6 +66,11 @@
<GridPane.margin>
<Insets right="20.0" top="10.0" />
</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>
</children>
<columnConstraints>
@@ -72,29 +85,121 @@
</GridPane>
<GridPane GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="400.0" minWidth="400.0" prefWidth="400.0" />
<ColumnConstraints hgrow="NEVER" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="115.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="337.0" prefWidth="430.0" />
<ColumnConstraints hgrow="NEVER" maxWidth="350.0" minWidth="350.0" prefWidth="350.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES" />
</rowConstraints>
<children>
<ScrollPane fx:id="playerListScrollPane" hbarPolicy="NEVER" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<ScrollPane fx:id="playerListScrollPane" hbarPolicy="NEVER" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<content>
<VBox fx:id="playerListVBox" prefHeight="200.0" prefWidth="100.0" />
<VBox fx:id="playerListVBox" alignment="TOP_RIGHT" maxWidth="328.0" minWidth="328.0" prefWidth="328.0" />
</content>
<GridPane.margin>
<Insets bottom="15.0" left="7.0" right="15.0" top="15.0" />
</GridPane.margin>
<padding>
<Insets right="5.0" />
</padding>
</ScrollPane>
<AnchorPane fx:id="serverMap" style="-fx-background-color: skyblue;">
<AnchorPane fx:id="serverMap" style="-fx-background-color: skyblue;" GridPane.columnIndex="1">
<opaqueInsets>
<Insets />
</opaqueInsets>
<GridPane.margin>
<Insets bottom="15.0" left="15.0" right="7.0" top="15.0" />
<Insets bottom="15.0" left="7.0" right="7.0" top="15.0" />
</GridPane.margin>
</AnchorPane>
</AnchorPane>
<GridPane prefHeight="370.0" prefWidth="189.0" styleClass="tokenGridView" vgap="5.0">
<children>
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Tokens" GridPane.halignment="CENTER">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Text>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="1">
<children>
<Label alignment="BOTTOM_CENTER" text="Speed" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font size="12.0" />
</font>
<padding>
<Insets bottom="5.0" />
</padding>
</Label>
<Pane fx:id="speedTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
</children>
</StackPane>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="2">
<children>
<Label alignment="BOTTOM_CENTER" text="Handling" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font size="12.0" />
</font>
<padding>
<Insets bottom="5.0" />
</padding>
</Label>
<Pane fx:id="handlingTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
</children>
</StackPane>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="3">
<children>
<Label alignment="BOTTOM_CENTER" text="Wind Walker" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font size="12.0" />
</font>
<padding>
<Insets bottom="5.0" />
</padding>
</Label>
<Pane fx:id="windWalkerTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
</children>
</StackPane>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="4">
<children>
<Label alignment="BOTTOM_CENTER" text="Bumper" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font size="12.0" />
</font>
<padding>
<Insets bottom="5.0" />
</padding>
</Label>
<Pane fx:id="bumperTokenPane" prefHeight="999.0" prefWidth="200.0" styleClass="tokenView" />
</children>
</StackPane>
<StackPane prefHeight="150.0" prefWidth="200.0" GridPane.rowIndex="5">
<children>
<Label alignment="BOTTOM_CENTER" text="Random" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font size="12.0" />
</font>
<padding>
<Insets bottom="5.0" />
</padding>
</Label>
<Pane fx:id="randomTokenPane" prefHeight="999.0" prefWidth="60.0" styleClass="tokenView" />
</children>
</StackPane>
</children>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="80.0" prefWidth="80.0" />
</columnConstraints>
<padding>
<Insets bottom="15.0" left="15.0" right="7.0" top="15.0" />
</padding>
<rowConstraints>
<RowConstraints maxHeight="116.0" minHeight="0.0" prefHeight="40.0" vgrow="NEVER" />
<RowConstraints maxHeight="285.0" minHeight="-Infinity" 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>
</GridPane>
</children>
</GridPane>
</children>
@@ -106,10 +211,10 @@
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="400.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
</rowConstraints>
<stylesheets>
<String fx:value="/css/Master.css" />
<String fx:value="/css/LobbyView.css" />
</stylesheets>
</GridPane>
</children>
<stylesheets>
<URL value="@../css/Master.css" />
<URL value="@../css/LobbyView.css" />
</stylesheets>
</StackPane>
+153 -105
View File
@@ -1,21 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.*?>
<?import javafx.scene.shape.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXSpinner?>
<?import com.jfoenix.controls.JFXTextField?>
<?import java.lang.String?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
@@ -26,36 +27,37 @@
<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>
<StackPane fx:id="contentStackPane" 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.0.111"
xmlns:fx="http://javafx.com/fxml/1">
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" xmlns:fx="http://javafx.com/fxml/1">
<children>
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="800.0" prefWidth="1200.0">
prefHeight="800.0" prefWidth="1200.0">
<columnConstraints>
<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="-Infinity" minWidth="400.0"
prefWidth="400.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
minWidth="400.0" prefWidth="400.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0"
vgrow="SOMETIMES"/>
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="250.0" minHeight="250.0" prefHeight="250.0"
valignment="BOTTOM" vgrow="SOMETIMES"/>
valignment="BOTTOM" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<GridPane id="timerGrid" fx:id="timerGrid" prefWidth="192.0" styleClass="timer">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0" minWidth="50.0"
prefWidth="50.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0" minWidth="135.0"
prefWidth="135.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="50.0"
minWidth="50.0" prefWidth="50.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="135.0"
minWidth="135.0" prefWidth="135.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0"
vgrow="SOMETIMES"/>
</rowConstraints>
<opaqueInsets>
<Insets/>
@@ -65,8 +67,8 @@
</GridPane.margin>
<children>
<ImageView fitHeight="40.0" fitWidth="40.0" pickOnBounds="true"
preserveRatio="true" GridPane.halignment="CENTER"
GridPane.valignment="CENTER">
preserveRatio="true" GridPane.halignment="CENTER"
GridPane.valignment="CENTER">
<image>
<Image url="@../images/timer.png"/>
</image>
@@ -74,8 +76,9 @@
<Insets/>
</GridPane.margin>
</ImageView>
<Label fx:id="timerLabel" text="00:03:34" GridPane.columnIndex="1"
GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<Label fx:id="timerLabel" text="00:03:34"
GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.valignment="CENTER">
<font>
<Font size="21.0"/>
</font>
@@ -87,57 +90,68 @@
</GridPane>
<GridPane GridPane.columnIndex="2">
<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>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="10.0" prefHeight="30.0"
vgrow="SOMETIMES"/>
</rowConstraints>
</GridPane>
<GridPane fx:id="chatGridPane" GridPane.columnIndex="2" GridPane.rowIndex="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="390.0"
prefWidth="390.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0"
minWidth="390.0" prefWidth="390.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="60.0" minHeight="60.0"
prefHeight="60.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Pane fx:id="chatHistoryHolder" prefHeight="200.0" prefWidth="200.0"
GridPane.hgrow="ALWAYS" GridPane.valignment="BOTTOM"
GridPane.vgrow="ALWAYS">
<Pane fx:id="chatHistoryHolder" prefHeight="200.0"
prefWidth="200.0" GridPane.hgrow="ALWAYS"
GridPane.valignment="BOTTOM" GridPane.vgrow="ALWAYS">
<GridPane.margin>
<Insets/>
</GridPane.margin>
<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>
</Pane>
<GridPane fx:id="chatInputHolder" GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity"
minWidth="90.0" prefWidth="90.0"/>
prefWidth="100.0"/>
<ColumnConstraints hgrow="SOMETIMES"
maxWidth="-Infinity" minWidth="90.0"
prefWidth="90.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="50.0" minHeight="50.0" prefHeight="50.0"
valignment="CENTER" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="50.0" minHeight="50.0"
prefHeight="50.0" valignment="CENTER"
vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<JFXButton fx:id="chatSend" alignment="CENTER" buttonType="RAISED"
focusTraversable="false" maxHeight="-Infinity"
maxWidth="1.7976931348623157E308" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="35.0" text="SEND"
GridPane.columnIndex="1">
<JFXButton fx:id="chatSend" alignment="CENTER"
buttonType="RAISED" focusTraversable="false"
maxHeight="-Infinity"
maxWidth="1.7976931348623157E308"
minHeight="-Infinity" minWidth="-Infinity"
prefHeight="35.0" text="SEND"
GridPane.columnIndex="1">
<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>
</JFXButton>
<JFXTextField fx:id="chatInput" focusTraversable="false"
maxHeight="35.0" minHeight="-Infinity" prefHeight="35.0">
maxHeight="35.0" minHeight="-Infinity"
prefHeight="35.0">
<GridPane.margin>
<Insets bottom="10.0" left="20.0" right="10.0"/>
</GridPane.margin>
@@ -155,31 +169,33 @@
<Insets bottom="10.0" right="10.0"/>
</GridPane.margin>
</GridPane>
<GridPane fx:id="windGridPane" maxHeight="-Infinity" maxWidth="-Infinity"
prefHeight="150.0" prefWidth="240.0" GridPane.halignment="CENTER"
GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
<GridPane fx:id="windGridPane" maxHeight="-Infinity"
maxWidth="-Infinity" prefHeight="150.0" prefWidth="240.0"
GridPane.halignment="CENTER" GridPane.rowIndex="2"
GridPane.valignment="BOTTOM">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" minWidth="110.0"
prefWidth="110.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0" minWidth="10.0"
prefWidth="132.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0"
minWidth="110.0" prefWidth="110.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="132.0"
minWidth="10.0" prefWidth="132.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="120.0" minHeight="120.0" prefHeight="120.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="120.0" minHeight="120.0"
prefHeight="120.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0"
prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Label fx:id="positionLabel" text="Position:" GridPane.columnIndex="1"
GridPane.halignment="LEFT" GridPane.rowSpan="2" GridPane.valignment="TOP">
<Label fx:id="positionLabel" text="Position:"
GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.rowSpan="2" GridPane.valignment="TOP">
<padding>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
</padding>
</Label>
<Label fx:id="boatSpeedLabel" text="Boat Speed:" GridPane.columnIndex="1"
GridPane.halignment="LEFT" GridPane.rowSpan="2"
GridPane.valignment="CENTER">
<Label fx:id="boatSpeedLabel" text="Boat Speed:"
GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.rowSpan="2" GridPane.valignment="CENTER">
<opaqueInsets>
<Insets/>
</opaqueInsets>
@@ -188,8 +204,8 @@
</padding>
</Label>
<Label fx:id="boatHeadingLabel" text="Boat Heading:"
GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowSpan="2"
GridPane.valignment="BOTTOM">
GridPane.columnIndex="1" GridPane.halignment="LEFT"
GridPane.rowSpan="2" GridPane.valignment="BOTTOM">
<padding>
<Insets bottom="5.0" left="10.0" right="5.0" top="5.0"/>
</padding>
@@ -197,29 +213,29 @@
<GridPane fx:id="windHolder" GridPane.rowSpan="2">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"
prefWidth="100.0"/>
prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="120.0" minHeight="120.0"
prefHeight="120.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0"
vgrow="SOMETIMES"/>
prefHeight="120.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="30.0" minHeight="30.0"
prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<ImageView fx:id="windImageView" fitHeight="92.0" fitWidth="109.0"
pickOnBounds="true" preserveRatio="true"
GridPane.halignment="CENTER" GridPane.rowSpan="2"
GridPane.valignment="CENTER"/>
<ImageView fx:id="windImageView" fitHeight="92.0"
fitWidth="109.0" pickOnBounds="true"
preserveRatio="true" GridPane.halignment="CENTER"
GridPane.rowSpan="2" GridPane.valignment="CENTER"/>
<Label fx:id="windSpeedLabel" text="0.0 Knots"
GridPane.halignment="RIGHT" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
GridPane.halignment="RIGHT" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets right="5.0"/>
</GridPane.margin>
</Label>
<Label fx:id="windDirectionLabel" text="180.0°"
GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets left="5.0"/>
</GridPane.margin>
@@ -236,54 +252,61 @@
</GridPane>
<GridPane GridPane.columnIndex="1" GridPane.rowIndex="2">
<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 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>
<rowConstraints>
<RowConstraints maxHeight="152.0" minHeight="10.0" prefHeight="152.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="118.0" minHeight="10.0" prefHeight="98.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="152.0" minHeight="10.0"
prefHeight="152.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="118.0" minHeight="10.0"
prefHeight="98.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<ImageView fx:id="velocityIcon" fitHeight="88.0" fitWidth="106.0"
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.halignment="CENTER" GridPane.rowIndex="1">
<ImageView fx:id="velocityIcon" fitHeight="88.0"
fitWidth="106.0" pickOnBounds="true" preserveRatio="true"
visible="false" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
<image>
<Image url="@../icons/velocity.png"/>
</image>
</ImageView>
<ImageView fx:id="handlingIcon" fitHeight="87.0" fitWidth="98.0"
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="1" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
<image>
<Image url="@../icons/handlingIcon.png"/>
</image>
</ImageView>
<ImageView fx:id="windWalkerIcon" fitHeight="83.0" fitWidth="100.0"
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="2" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
<ImageView fx:id="windWalkerIcon" fitHeight="83.0"
fitWidth="100.0" pickOnBounds="true" preserveRatio="true"
visible="false" GridPane.columnIndex="2"
GridPane.halignment="CENTER" GridPane.rowIndex="1">
<image>
<Image url="@../icons/windWalkerIcon.png"/>
</image>
</ImageView>
<ImageView fx:id="bumperIcon" fitHeight="83.0" fitWidth="88.0"
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="3" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="3" GridPane.halignment="CENTER"
GridPane.rowIndex="1">
<image>
<Image url="@../icons/bumperIcon.png"/>
</image>
</ImageView>
<ImageView fx:id="badRandomIcon" fitHeight="69.0" fitWidth="103.0"
pickOnBounds="true" preserveRatio="true" visible="false"
GridPane.columnIndex="4" GridPane.halignment="CENTER"
GridPane.rowIndex="1" GridPane.valignment="CENTER">
<ImageView fx:id="badRandomIcon" fitHeight="69.0"
fitWidth="103.0" pickOnBounds="true" preserveRatio="true"
visible="false" GridPane.columnIndex="4"
GridPane.halignment="CENTER" GridPane.rowIndex="1"
GridPane.valignment="CENTER">
<image>
<Image url="@../icons/slowedIcon.png"/>
</image>
@@ -294,13 +317,38 @@
</GridPane>
</children>
</StackPane>
<Pane fx:id="miniMapPane" maxHeight="200.0" maxWidth="200.0" minHeight="200.0"
minWidth="200.0" prefHeight="200.0" prefWidth="200.0" StackPane.alignment="TOP_RIGHT">
<StackPane.margin>
<Insets right="15.0" top="15.0" />
</StackPane.margin>
</Pane>
<JFXButton fx:id="miniMapButton" text="—" StackPane.alignment="TOP_RIGHT">
<font>
<Font size="15.0" />
</font>
<StackPane.margin>
<Insets right="15.0" top="15.0" />
</StackPane.margin>
</JFXButton>
<AnchorPane fx:id="loadingScreenPane">
<ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0" pickOnBounds="true" preserveRatio="true" />
<JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0" />
<children>
<ImageView fx:id="loadingScreen" fitHeight="672.0" fitWidth="1200.0"
pickOnBounds="true" preserveRatio="true"/>
<JFXSpinner layoutX="566.0" layoutY="692.0" radius="30.0"/>
</children>
</AnchorPane>
<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>
<String fx:value="/css/Master.css"/>
<String fx:value="/css/RaceView.css"/>
<URL value="@../css/Master.css"/>
<URL value="@../css/RaceView.css"/>
</stylesheets>
</StackPane>
+2 -2
View File
@@ -113,8 +113,8 @@
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="459.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="70.0" minHeight="70.0" prefHeight="70.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="400.0" prefHeight="429.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="100.0" minHeight="100.0" prefHeight="100.0" vgrow="SOMETIMES" />
</rowConstraints>
<stylesheets>
<String fx:value="/css/Master.css" />
+39 -22
View File
@@ -1,33 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXSpinner?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<StackPane id="background" fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="seng302.visualiser.controllers.SplashScreenController">
<StackPane fx:id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.SplashScreenController">
<children>
<ImageView fitHeight="296.0" fitWidth="295.0" pickOnBounds="true" preserveRatio="true" StackPane.alignment="TOP_CENTER">
<image>
<Image url="@../PP.png" />
</image>
<StackPane.margin>
<Insets top="20.0" />
</StackPane.margin>
</ImageView>
<Text fx:id="headText" strokeType="OUTSIDE" strokeWidth="0.0" text="Party Parrots at Sea" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font name="System Bold" size="42.0" />
</font>
<StackPane.margin>
<Insets bottom="20.0" />
</StackPane.margin>
</Text>
<AnchorPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
<children>
<Label fx:id="subHeadLabel" layoutX="225.0" layoutY="370.0"
text="MADE BY :PARTYPARROT:"/>
<StackPane layoutX="150.0" layoutY="10.0" prefHeight="150.0" prefWidth="200.0">
<children>
<ImageView fitHeight="190.0" fitWidth="190.0" pickOnBounds="true"
preserveRatio="true">
<image>
<Image url="@../PP.png"/>
</image>
</ImageView>
<JFXSpinner fx:id="materialDesignRed" radius="150.0" startingAngle="0.0"
styleClass="materialDesign-red"/>
<JFXSpinner radius="140.0" startingAngle="20.0"
styleClass="materialDesign-orange"/>
<JFXSpinner radius="130.0" startingAngle="40.0"
styleClass="materialDesign-yellow"/>
<JFXSpinner radius="120.0" startingAngle="60.0"
styleClass="materialDesign-green"/>
<JFXSpinner radius="110.0" startingAngle="80.0" styleClass="materialDesign-cyan"/>
<JFXSpinner radius="100.0" startingAngle="100.0"
styleClass="materialDesign-blue"/>
<JFXSpinner radius="90.0" startingAngle="120.0"
styleClass="materialDesign-purple"/>
</children>
</StackPane>
<Label fx:id="headText" layoutX="36.0" layoutY="295.0" text="PARTY PARROT AT SEA"/>
</children>
</AnchorPane>
</children>
<stylesheets>
<URL value="@../css/Master.css"/>
<URL value="@../css/SplashScreenView.css"/>
<URL value="@../css/Master.css"/>
<URL value="@../css/SplashScreenView.css"/>
</stylesheets>
</StackPane>
+14 -13
View File
@@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import java.lang.String?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
@@ -8,33 +12,30 @@
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<VBox fx:id="playerCellVBox" maxHeight="-Infinity" maxWidth="1.7976931348623157E308"
minHeight="-Infinity" minWidth="-Infinity" prefHeight="80.0"
xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1">
<VBox fx:id="playerCellVBox" maxHeight="-Infinity" maxWidth="340.0" minHeight="-Infinity" minWidth="340.0" prefHeight="80.0" prefWidth="340.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<stylesheets>
<String fx:value="/css/Master.css"/>
<String fx:value="/css/cells/PlayerCell.css"/>
<String fx:value="/css/Master.css" />
<String fx:value="/css/cells/PlayerCell.css" />
</stylesheets>
<children>
<GridPane fx:id="playerListCell" maxHeight="-Infinity" maxWidth="1.7976931348623157E308"
minHeight="-Infinity" prefHeight="70.0">
<GridPane fx:id="playerListCell" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" prefHeight="70.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="80.0" prefWidth="80.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="290.0" minWidth="290.0"
prefWidth="290.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="80.0" minWidth="80.0" prefWidth="80.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="260.0" minWidth="260.0" prefWidth="260.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label fx:id="playerName" text="Party parrots in space" GridPane.columnIndex="1">
<padding>
<Insets left="20.0" />
</padding></Label>
<Pane fx:id="boatPane" prefHeight="200.0" prefWidth="200.0"/>
<Pane fx:id="boatPane" prefHeight="200.0" prefWidth="200.0" />
</children>
<VBox.margin>
<Insets right="40.0"/>
<Insets right="40.0" />
</VBox.margin>
</GridPane>
</children>
@@ -23,6 +23,7 @@
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0"/>
<ColumnConstraints/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="-Infinity" minHeight="-Infinity" prefHeight="60.0"
@@ -112,7 +113,7 @@
<Insets/>
</GridPane.margin>
</Label>
<JFXButton id="ZOOM IN" fx:id="zoomInbtn" buttonType="RAISED"
<JFXButton id="ZOOM IN" fx:id="zoomInBtn" buttonType="RAISED"
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="35.0"
minWidth="-Infinity" prefWidth="120.0" text="Z"
GridPane.columnIndex="1" GridPane.halignment="CENTER"
@@ -223,8 +224,19 @@
GridPane.valignment="TOP"/>
<JFXButton fx:id="resetBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="45.0"
prefWidth="150.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="CENTER"
GridPane.rowIndex="2" GridPane.valignment="CENTER"/>
prefWidth="140.0" text="RESET" GridPane.columnSpan="2" GridPane.halignment="LEFT"
GridPane.rowIndex="2" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets left="60.0"/>
</GridPane.margin>
</JFXButton>
<JFXButton fx:id="confirmBtn" buttonType="RAISED" maxHeight="-Infinity"
maxWidth="-Infinity" minHeight="45.0" minWidth="140.0" prefHeight="45.0"
prefWidth="140.0" text="CONFIRM" GridPane.halignment="RIGHT" GridPane.rowIndex="2">
<GridPane.margin>
<Insets right="60.0"/>
</GridPane.margin>
</JFXButton>
</children>
</GridPane>
</children>
@@ -1,6 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXDialogLayout?>
<?import java.net.URL?>
@@ -9,6 +14,7 @@
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefWidth="550.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import com.jfoenix.controls.*?>
<?import java.lang.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXDialogLayout?>
<?import java.net.URL?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<JFXDialogLayout maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
minWidth="-Infinity" prefHeight="273.0" prefWidth="436.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="seng302.visualiser.controllers.dialogs.TokenInfoDialogController">
<children>
<GridPane>
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308"/>
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="40.0" minHeight="30.0" prefHeight="40.0"
vgrow="SOMETIMES"/>
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="80.0"
prefHeight="115.0" vgrow="SOMETIMES"/>
<RowConstraints maxHeight="141.0" minHeight="34.0" prefHeight="73.0"
vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<JFXButton fx:id="optionButton" buttonType="RAISED" prefHeight="55.0"
prefWidth="150.0" text="Ok" GridPane.halignment="CENTER" GridPane.rowIndex="2"
GridPane.valignment="CENTER">
<GridPane.margin>
<Insets/>
</GridPane.margin>
</JFXButton>
<Label fx:id="headerLabel" text="Popup header" GridPane.halignment="CENTER">
<font>
<Font size="15.0"/>
</font>
</Label>
<GridPane GridPane.rowIndex="1">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="270.0" minWidth="10.0"
prefWidth="270.0"/>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="225.0" minWidth="-Infinity"
prefWidth="138.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="100.0" vgrow="SOMETIMES"/>
</rowConstraints>
<children>
<Pane fx:id="tokenPane" prefHeight="200.0" prefWidth="200.0"
GridPane.columnIndex="1"/>
<TextArea fx:id="contentText" nodeOrientation="RIGHT_TO_LEFT"
prefHeight="200.0" prefWidth="200.0" promptText="This is some text"
stylesheets="@../../css/TokenInfoDialog.css" wrapText="true">
<font>
<Font size="16.0"/>
</font>
</TextArea>
</children>
</GridPane>
</children>
</GridPane>
</children>
<stylesheets>
<URL value="@../../css/dialogs/Popup.css"/>
<URL value="@../../css/Master.css"/>
</stylesheets>
</JFXDialogLayout>
@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.String?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:id="annotationSelectWindow" maxHeight="270.0" maxWidth="469.0" minHeight="270.0" minWidth="469.0" prefHeight="270.0" prefWidth="469.0" styleClass="background-blue" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Text fill="WHITE" layoutX="26.0" layoutY="52.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Select important annotations">
<font>
<Font size="24.0" />
</font>
</Text>
<CheckBox fx:id="boatWakeSelect" layoutX="26.0" layoutY="80.0" mnemonicParsing="false" style="-fx-border-width: 0; -fx-background-insets: 0;" text="Boat Wakes" textFill="#e7e7e7" />
<CheckBox fx:id="boatSpeedSelect" layoutX="26.0" layoutY="111.0" mnemonicParsing="false" text="Boat Speed" textFill="#e7e7e7" />
<CheckBox fx:id="boatTrackSelect" layoutX="26.0" layoutY="142.0" mnemonicParsing="false" text="Boat Tracks" textFill="#e7e7e7" />
<CheckBox fx:id="boatNameSelect" layoutX="26.0" layoutY="173.0" mnemonicParsing="false" text="Boat Name" textFill="#e7e7e7" />
<CheckBox fx:id="boatEstTimeToNextMarkSelect" layoutX="26.0" layoutY="204.0" mnemonicParsing="false" text="Boat Estimated Time To Next Mark" textFill="#e7e7e7" />
<Button fx:id="closeButton" layoutX="424.0" layoutY="-1.0" mnemonicParsing="false" prefHeight="11.0" prefWidth="49.0" style=": 0;" text="X" textFill="#ffffff4e">
<font>
<Font size="24.0" />
</font>
<styleClass>
<String fx:value="background-blue" />
<String fx:value="clearExitButton" />
</styleClass>
</Button>
<CheckBox fx:id="boatElapsedTimeSelect" layoutX="26.0" layoutY="235.0" mnemonicParsing="false" text="Boat Elapsed Time Since Last Mark" textFill="#e7e7e7" />
</children>
</AnchorPane>
@@ -48,9 +48,10 @@ public class ServerTableTest {
serverTable.addServer(listing);
listing.decrementTtl();
listing.decrementTtl();
Thread.sleep(1000);
Thread.sleep(1500);
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
public void testServerDisconnection () throws Exception {
MainServerThread serverThread = new MainServerThread();
ClientToServerThread clientThread = new ClientToServerThread("localhost", 4942);
ClientToServerThread clientThread = new ClientToServerThread("localhost", serverThread.getPortNumber());
Thread.sleep(1000);
clientThread.addDisconnectionListener(message -> Assert.assertTrue(message != null));
serverThread.terminate();
@@ -20,7 +20,7 @@ public class RegularPacketsTest {
public void setup() throws Exception {
new GameState();
serverThread = new MainServerThread();
clientThread = new ClientToServerThread("localhost", 4942);
clientThread = new ClientToServerThread("localhost", serverThread.getPortNumber());
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.Then;
import java.io.File;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import org.junit.Assert;
import seng302.visualiser.MapMaker;
@@ -16,26 +19,26 @@ public class CustomMapsSteps {
@Given("^that the game has multiple race xml files$")
public void that_the_game_has_multiple_race_xml_files() throws Throwable {
// mapMaker = MapMaker.getInstance();
// String firstMap = mapMaker.getCurrentRacePath();
// int numMaps = 0;
// do {
// mapMaker.next();
// numMaps++;
// } while (!mapMaker.getCurrentRacePath().equals(firstMap));
// Assert.assertTrue(numMaps >= 2);
mapMaker = MapMaker.getInstance();
String firstMap = mapMaker.getCurrentRacePath();
int numMaps = 0;
do {
mapMaker.next();
numMaps++;
} while (!mapMaker.getCurrentRacePath().equals(firstMap));
Assert.assertTrue(numMaps >= 2);
}
@Then("^all of them can be seen$")
public void all_of_them_can_be_seen() throws Throwable {
// File[] files = new File(this.getClass().getResource("/maps/").getPath()).listFiles();
// for (File file : files) {
// if (file.isFile()) {
// Assert.assertTrue(file.getAbsolutePath().equals(mapMaker.getCurrentRacePath()));
// mapMaker.next();
// System.out.println(file.getAbsolutePath());
// }
// }
File[] files = new File(this.getClass().getResource("/maps/").getPath()).listFiles();
Arrays.sort(files);
for (File file : files) {
if (file.isFile()) {
Assert.assertTrue(file.getAbsolutePath().endsWith(mapMaker.getCurrentRacePath()));
mapMaker.next();
}
}
}
@Given("^that I choose a race$")
+2 -2
View File
@@ -45,7 +45,7 @@ public class SendChatSteps {
} catch (InterruptedException ie) {
ie.printStackTrace();
}
host = new ClientToServerThread("localhost", 4942);
host = new ClientToServerThread("localhost", mst.getPortNumber());
host.addStreamObserver(() -> {
while (host.getPacketQueue().peek() != null) {
StreamPacket packet = host.getPacketQueue().poll();
@@ -68,7 +68,7 @@ public class SendChatSteps {
} catch (InterruptedException ie) {
ie.printStackTrace();
}
client = new ClientToServerThread("localhost", 4942);
client = new ClientToServerThread("localhost", mst.getPortNumber());
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
+1 -1
View File
@@ -44,7 +44,7 @@ public class ToggleSailSteps {
} catch (InterruptedException ie) {
ie.printStackTrace();
}
client = new ClientToServerThread("localhost", 4942);
client = new ClientToServerThread("localhost", mst.getPortNumber());
try {
Thread.sleep(100);
} catch (InterruptedException ie) {