mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -59,6 +59,7 @@ public class ClientPacketParser {
|
|||||||
*/
|
*/
|
||||||
public ClientPacketParser() {
|
public ClientPacketParser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks at the type of the packet then sends it to the appropriate parser to extract the
|
* Looks at the type of the packet then sends it to the appropriate parser to extract the
|
||||||
* specific data associated with that packet type
|
* specific data associated with that packet type
|
||||||
@@ -78,7 +79,6 @@ public class ClientPacketParser {
|
|||||||
extractDisplayMessage(packet);
|
extractDisplayMessage(packet);
|
||||||
break;
|
break;
|
||||||
case XML_MESSAGE:
|
case XML_MESSAGE:
|
||||||
newRaceXmlReceived = true;
|
|
||||||
extractXmlMessage(packet);
|
extractXmlMessage(packet);
|
||||||
break;
|
break;
|
||||||
case RACE_START_STATUS:
|
case RACE_START_STATUS:
|
||||||
@@ -108,7 +108,7 @@ public class ClientPacketParser {
|
|||||||
}
|
}
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
System.out.println("Error parsing packet");
|
System.out.println("Error parsing packet");
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,6 @@ public class ClientPacketParser {
|
|||||||
|
|
||||||
int noBoats = payload[22];
|
int noBoats = payload[22];
|
||||||
int raceType = payload[23];
|
int raceType = payload[23];
|
||||||
clientStateBoats = ClientState.getBoats();
|
|
||||||
for (int i = 0; i < noBoats; i++) {
|
for (int i = 0; i < noBoats; i++) {
|
||||||
long boatStatusSourceID = bytesToLong(
|
long boatStatusSourceID = bytesToLong(
|
||||||
Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20)));
|
Arrays.copyOfRange(payload, 24 + (i * 20), 28 + (i * 20)));
|
||||||
@@ -206,7 +205,9 @@ public class ClientPacketParser {
|
|||||||
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
boat.setEstimateTimeAtNextMark(estTimeAtNextMark);
|
||||||
boat.setEstimateTimeAtFinish(estTimeAtFinish);
|
boat.setEstimateTimeAtFinish(estTimeAtFinish);
|
||||||
|
|
||||||
Yacht clientBoat = clientStateBoats.get((int) boatStatusSourceID);
|
// Update Client State boats when receive race status packet.
|
||||||
|
// Potentially could replace boats in ClientPacketParser.
|
||||||
|
Yacht clientBoat = ClientState.getBoats().get((int) boatStatusSourceID);
|
||||||
clientBoat.setBoatStatus((boatStatus));
|
clientBoat.setBoatStatus((boatStatus));
|
||||||
setBoatLegPosition(clientBoat, boatLegNumber);
|
setBoatLegPosition(clientBoat, boatLegNumber);
|
||||||
clientBoat.setPenaltiesAwarded(boatPenaltyAwarded);
|
clientBoat.setPenaltiesAwarded(boatPenaltyAwarded);
|
||||||
@@ -215,26 +216,32 @@ public class ClientPacketParser {
|
|||||||
clientBoat.setEstimateTimeAtFinish(estTimeAtFinish);
|
clientBoat.setEstimateTimeAtFinish(estTimeAtFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3 is race started
|
// 3 is race started.
|
||||||
|
// ClientState race started flag will be set to true if race started, else set false.
|
||||||
if (raceStatus == 3) {
|
if (raceStatus == 3) {
|
||||||
ClientState.setRaceStarted(true);
|
ClientState.setRaceStarted(true);
|
||||||
|
} else {
|
||||||
|
ClientState.setRaceStarted(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setBoatLegPosition(Yacht updatingBoat, Integer leg){
|
private static void setBoatLegPosition(Yacht updatingBoat, Integer leg){
|
||||||
Integer placing = 1;
|
Integer placing = 1;
|
||||||
if (leg != updatingBoat.getLegNumber() && (raceStarted || raceFinished)) {
|
|
||||||
|
if (/* TODO implement when we are getting this data /TODO leg != updatingBoat.getLegNumber() && */(raceStarted || raceFinished)) {
|
||||||
for (Yacht boat : boats.values()) {
|
for (Yacht boat : boats.values()) {
|
||||||
|
placing = boat.getSourceId();
|
||||||
|
/* See above to-do
|
||||||
if (boat.getLegNumber() != null && leg <= boat.getLegNumber()){
|
if (boat.getLegNumber() != null && leg <= boat.getLegNumber()){
|
||||||
placing += 1;
|
placing += 1;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
updatingBoat.setPosition(placing.toString());
|
updatingBoat.setPosition(placing.toString());
|
||||||
updatingBoat.setLegNumber(leg);
|
updatingBoat.setLegNumber(leg);
|
||||||
boatsPos.putIfAbsent(placing, updatingBoat);
|
boatsPos.putIfAbsent(placing, updatingBoat);
|
||||||
boatsPos.replace(placing, updatingBoat);
|
boatsPos.replace(placing, updatingBoat);
|
||||||
} else if(updatingBoat.getLegNumber() == null){
|
} else if(updatingBoat.getLegNumber() == null){
|
||||||
updatingBoat.setPosition("1");
|
updatingBoat.setPosition("-");
|
||||||
updatingBoat.setLegNumber(leg);
|
updatingBoat.setLegNumber(leg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,10 +291,13 @@ public class ClientPacketParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
xmlObject.constructXML(doc, messageType);
|
xmlObject.constructXML(doc, messageType);
|
||||||
|
|
||||||
if (messageType == 7) { //7 is the boat XML
|
if (messageType == 7) { //7 is the boat XML
|
||||||
boats = xmlObject.getBoatXML().getCompetingBoats();
|
boats = xmlObject.getBoatXML().getCompetingBoats();
|
||||||
|
// Set/Update the ClientState boats after receiving new boat xml.
|
||||||
|
// Flag boatsUpdated in ClientState to true.
|
||||||
ClientState.setBoats(xmlObject.getBoatXML().getCompetingBoats());
|
ClientState.setBoats(xmlObject.getBoatXML().getCompetingBoats());
|
||||||
ClientState.setDirtyState(true);
|
ClientState.setBoatsUpdated(true);
|
||||||
}
|
}
|
||||||
if (messageType == 6) { //6 is race info xml
|
if (messageType == 6) { //6 is race info xml
|
||||||
newRaceXmlReceived = true;
|
newRaceXmlReceived = true;
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
package seng302.client;
|
package seng302.client;
|
||||||
|
|
||||||
import com.sun.org.apache.xpath.internal.operations.Bool;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import seng302.models.Yacht;
|
import seng302.models.Yacht;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by the client to store static variables to be used in game.
|
* Used by the client to store static variables, which other threads and classes
|
||||||
|
* observer so that they can update their status accordingly.
|
||||||
*/
|
*/
|
||||||
public class ClientState {
|
public class ClientState {
|
||||||
|
|
||||||
@@ -17,7 +15,7 @@ public class ClientState {
|
|||||||
private static Boolean raceStarted = false;
|
private static Boolean raceStarted = false;
|
||||||
private static Boolean connectedToHost = false;
|
private static Boolean connectedToHost = false;
|
||||||
private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
|
private static Map<Integer, Yacht> boats = new ConcurrentHashMap<>();
|
||||||
private static Boolean dirtyState = true;
|
private static Boolean boatsUpdated = true;
|
||||||
private static String clientSourceId = "";
|
private static String clientSourceId = "";
|
||||||
|
|
||||||
public static String getHostIp() {
|
public static String getHostIp() {
|
||||||
@@ -56,12 +54,12 @@ public class ClientState {
|
|||||||
return boats;
|
return boats;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean isDirtyState() {
|
public static Boolean isBoatsUpdated() {
|
||||||
return dirtyState;
|
return boatsUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setDirtyState(Boolean dirtyState) {
|
public static void setBoatsUpdated(Boolean boatsUpdated) {
|
||||||
ClientState.dirtyState = dirtyState;
|
ClientState.boatsUpdated = boatsUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClientSourceId() {
|
public static String getClientSourceId() {
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ public class ClientStateQueryingRunnable extends Observable implements Runnable
|
|||||||
|
|
||||||
public ClientStateQueryingRunnable() {}
|
public ClientStateQueryingRunnable() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies observers(the lobby controller) that "game started" if ClientState
|
||||||
|
* raceStarted flag is true and terminates itself. Also, it notifies observers
|
||||||
|
* to add/remove players if ClientState boatsUpdated flag is true, then resets
|
||||||
|
* the flag to false;
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while(!terminate) {
|
while(!terminate) {
|
||||||
@@ -29,14 +35,19 @@ public class ClientStateQueryingRunnable extends Observable implements Runnable
|
|||||||
terminate();
|
terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClientState.isDirtyState()) {
|
if (ClientState.isBoatsUpdated()) {
|
||||||
setChanged();
|
setChanged();
|
||||||
notifyObservers("update players");
|
notifyObservers("update players");
|
||||||
ClientState.setDirtyState(false);
|
ClientState.setBoatsUpdated(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to terminate the thread.
|
||||||
|
*
|
||||||
|
* Currently called by the main while loop when game started is detected.
|
||||||
|
*/
|
||||||
public void terminate() {
|
public void terminate() {
|
||||||
terminate = true;
|
terminate = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import seng302.server.messages.BoatActionMessage;
|
|||||||
import seng302.server.messages.Message;
|
import seng302.server.messages.Message;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by kre39 on 13/07/17.
|
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
||||||
|
* its own thread.
|
||||||
*/
|
*/
|
||||||
public class ClientToServerThread implements Runnable {
|
public class ClientToServerThread implements Runnable {
|
||||||
|
|
||||||
@@ -30,8 +31,19 @@ public class ClientToServerThread implements Runnable {
|
|||||||
private OutputStream os;
|
private OutputStream os;
|
||||||
|
|
||||||
private Boolean updateClient = true;
|
private Boolean updateClient = true;
|
||||||
private ByteArrayOutputStream crcBuffer;
|
private ByteArrayOutputStream crcBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for ClientToServerThread which takes in ipAddress and portNumber and attempts to
|
||||||
|
* connect to the specified ipAddress and port.
|
||||||
|
*
|
||||||
|
* Upon successful socket connection, threeWayHandshake will be preformed and the instance will
|
||||||
|
* be put on a thread and run immediately.
|
||||||
|
*
|
||||||
|
* @param ipAddress a string of ip address to be connected to
|
||||||
|
* @param portNumber an integer port number
|
||||||
|
* @throws Exception SocketConnection if fail to connect to ip address and port number combination
|
||||||
|
*/
|
||||||
public ClientToServerThread(String ipAddress, Integer portNumber) throws Exception{
|
public ClientToServerThread(String ipAddress, Integer portNumber) throws Exception{
|
||||||
socket = new Socket(ipAddress, portNumber);
|
socket = new Socket(ipAddress, portNumber);
|
||||||
is = socket.getInputStream();
|
is = socket.getInputStream();
|
||||||
@@ -40,7 +52,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
Integer allocatedID = threeWayHandshake();
|
Integer allocatedID = threeWayHandshake();
|
||||||
if (allocatedID != null) {
|
if (allocatedID != null) {
|
||||||
ourID = allocatedID;
|
ourID = allocatedID;
|
||||||
clientLog("Successful handshake. Allocated ID: " + ourID, 1);
|
clientLog("Successful handshake. Allocated ID: " + ourID, 0);
|
||||||
ClientState.setClientSourceId(String.valueOf(ourID));
|
ClientState.setClientSourceId(String.valueOf(ourID));
|
||||||
} else {
|
} else {
|
||||||
clientLog("Unsuccessful handshake", 1);
|
clientLog("Unsuccessful handshake", 1);
|
||||||
@@ -50,31 +62,31 @@ public class ClientToServerThread implements Runnable {
|
|||||||
|
|
||||||
thread = new Thread(this);
|
thread = new Thread(this);
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints out log messages and the time happened.
|
||||||
|
* Only perform task if log level is below LOG_LEVEL variable.
|
||||||
|
*
|
||||||
|
* @param message a string of message to be printed out
|
||||||
|
* @param logLevel an int for log level
|
||||||
|
*/
|
||||||
static void clientLog(String message, int logLevel){
|
static void clientLog(String message, int logLevel){
|
||||||
if(logLevel <= LOG_LEVEL){
|
if(logLevel <= LOG_LEVEL){
|
||||||
System.out.println("[CLIENT " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
System.out.println("[CLIENT " + LocalDateTime.now().toLocalTime().toString() + "] " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the thread loop. It exits the loop if ClientState connected to host
|
||||||
|
* variable is false.
|
||||||
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
int sync1;
|
int sync1;
|
||||||
int sync2;
|
int sync2;
|
||||||
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
||||||
while(ClientState.isConnectedToHost()) {
|
while(ClientState.isConnectedToHost()) {
|
||||||
try {
|
try {
|
||||||
//Perform a write if it is time to as delegated by the MainServerThread
|
|
||||||
if (updateClient) {
|
|
||||||
// TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
|
|
||||||
// try {
|
|
||||||
// GameState.outputState(os);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// System.out.println("IO error in server thread upon writing to output stream");
|
|
||||||
// }
|
|
||||||
updateClient = false;
|
|
||||||
}
|
|
||||||
crcBuffer = new ByteArrayOutputStream();
|
crcBuffer = new ByteArrayOutputStream();
|
||||||
sync1 = readByte();
|
sync1 = readByte();
|
||||||
sync2 = readByte();
|
sync2 = readByte();
|
||||||
@@ -93,15 +105,13 @@ public class ClientToServerThread implements Runnable {
|
|||||||
if (computedCrc == packetCrc) {
|
if (computedCrc == packetCrc) {
|
||||||
ClientPacketParser
|
ClientPacketParser
|
||||||
.parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload));
|
.parsePacket(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||||
// TODO: 17/07/17 wmu16 - Fix this or maybe we dont need to go through the main server at all!?!?
|
|
||||||
// packetBufferDelegate.addToBuffer(new StreamPacket(type, payloadLength, timeStamp, payload));
|
|
||||||
} else {
|
} else {
|
||||||
clientLog("Packet has been dropped", 1);
|
clientLog("Packet has been dropped", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
closeSocket();
|
closeSocket();
|
||||||
e.printStackTrace();
|
clientLog("Disconnected from server", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +121,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for an allocated sourceID and returns it to the server if recieved
|
* Listens for an allocated sourceID and returns it to the server
|
||||||
* @return the sourceID allocated to us by the server
|
* @return the sourceID allocated to us by the server
|
||||||
*/
|
*/
|
||||||
private Integer threeWayHandshake() {
|
private Integer threeWayHandshake() {
|
||||||
@@ -120,14 +130,15 @@ public class ClientToServerThread implements Runnable {
|
|||||||
try {
|
try {
|
||||||
ourSourceID = is.read();
|
ourSourceID = is.read();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
clientLog("Three way handshake failed", 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (ourSourceID != null) {
|
if (ourSourceID != null) {
|
||||||
try {
|
try {
|
||||||
os.write(ourSourceID);
|
os.write(ourSourceID);
|
||||||
return ourSourceID;
|
return ourSourceID;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
clientLog("Three way handshake failed", 1);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,8 +154,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
try {
|
try {
|
||||||
os.write(boatActionMessage.getBuffer());
|
os.write(boatActionMessage.getBuffer());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
clientLog("COULD NOT WRITE TO SERVER", 0);
|
clientLog("Could not write to server", 1);
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +163,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
try {
|
try {
|
||||||
socket.close();
|
socket.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
clientLog("Failed to close the socket", 0);
|
clientLog("Failed to close the socket", 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +174,7 @@ public class ClientToServerThread implements Runnable {
|
|||||||
currentByte = is.read();
|
currentByte = is.read();
|
||||||
crcBuffer.write(currentByte);
|
crcBuffer.write(currentByte);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
clientLog("Read byte failed", 1);
|
||||||
}
|
}
|
||||||
if (currentByte == -1){
|
if (currentByte == -1){
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import javafx.scene.paint.Color;
|
|||||||
import javafx.scene.shape.Polygon;
|
import javafx.scene.shape.Polygon;
|
||||||
import javafx.scene.text.Text;
|
import javafx.scene.text.Text;
|
||||||
import seng302.client.ClientPacketParser;
|
import seng302.client.ClientPacketParser;
|
||||||
|
import seng302.client.ClientState;
|
||||||
import seng302.fxObjects.BoatGroup;
|
import seng302.fxObjects.BoatGroup;
|
||||||
import seng302.models.Colors;
|
import seng302.models.Colors;
|
||||||
import seng302.models.Yacht;
|
import seng302.models.Yacht;
|
||||||
@@ -57,8 +58,8 @@ public class CanvasController {
|
|||||||
private final int BUFFER_SIZE = 50;
|
private final int BUFFER_SIZE = 50;
|
||||||
private final int PANEL_WIDTH = 1260; // it should be 1280 but, minors 40 to cancel the bias.
|
private final int PANEL_WIDTH = 1260; // it should be 1280 but, minors 40 to cancel the bias.
|
||||||
private final int PANEL_HEIGHT = 960;
|
private final int PANEL_HEIGHT = 960;
|
||||||
private final int CANVAS_WIDTH = 720;
|
private final int CANVAS_WIDTH = 1100;
|
||||||
private final int CANVAS_HEIGHT = 720;
|
private final int CANVAS_HEIGHT = 920;
|
||||||
private boolean horizontalInversion = false;
|
private boolean horizontalInversion = false;
|
||||||
|
|
||||||
private double distanceScaleFactor;
|
private double distanceScaleFactor;
|
||||||
@@ -74,7 +75,7 @@ public class CanvasController {
|
|||||||
|
|
||||||
private List<MarkGroup> markGroups = new ArrayList<>();
|
private List<MarkGroup> markGroups = new ArrayList<>();
|
||||||
private List<BoatGroup> boatGroups = new ArrayList<>();
|
private List<BoatGroup> boatGroups = new ArrayList<>();
|
||||||
private Text FPSdisplay = new Text();
|
private Text FPSDisplay = new Text();
|
||||||
private Polygon raceBorder = new Polygon();
|
private Polygon raceBorder = new Polygon();
|
||||||
|
|
||||||
//FRAME RATE
|
//FRAME RATE
|
||||||
@@ -119,10 +120,10 @@ public class CanvasController {
|
|||||||
gc.setGlobalAlpha(0.5);
|
gc.setGlobalAlpha(0.5);
|
||||||
fitMarksToCanvas();
|
fitMarksToCanvas();
|
||||||
drawGoogleMap();
|
drawGoogleMap();
|
||||||
FPSdisplay.setLayoutX(5);
|
FPSDisplay.setLayoutX(5);
|
||||||
FPSdisplay.setLayoutY(20);
|
FPSDisplay.setLayoutY(20);
|
||||||
FPSdisplay.setStrokeWidth(2);
|
FPSDisplay.setStrokeWidth(2);
|
||||||
group.getChildren().add(FPSdisplay);
|
group.getChildren().add(FPSDisplay);
|
||||||
group.getChildren().add(raceBorder);
|
group.getChildren().add(raceBorder);
|
||||||
initializeMarks();
|
initializeMarks();
|
||||||
initializeBoats();
|
initializeBoats();
|
||||||
@@ -249,11 +250,8 @@ public class CanvasController {
|
|||||||
// some raceObjects will have multiple ID's (for instance gate marks)
|
// some raceObjects will have multiple ID's (for instance gate marks)
|
||||||
//checking if the current "ID" has any updates associated with it
|
//checking if the current "ID" has any updates associated with it
|
||||||
if (ClientPacketParser.boatLocations.containsKey(boatGroup.getRaceId())) {
|
if (ClientPacketParser.boatLocations.containsKey(boatGroup.getRaceId())) {
|
||||||
if (boatGroup.isStopped()) {
|
updateBoatGroup(boatGroup);
|
||||||
updateBoatGroup(boatGroup);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
boatGroup.move();
|
|
||||||
}
|
}
|
||||||
for (MarkGroup markGroup : markGroups) {
|
for (MarkGroup markGroup : markGroups) {
|
||||||
for (Long id : markGroup.getRaceIds()) {
|
for (Long id : markGroup.getRaceIds()) {
|
||||||
@@ -324,10 +322,25 @@ public class CanvasController {
|
|||||||
if (participantIDs.contains(boat.getSourceId())) {
|
if (participantIDs.contains(boat.getSourceId())) {
|
||||||
boat.setColour(Colors.getColor());
|
boat.setColour(Colors.getColor());
|
||||||
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
||||||
boatGroups.add(boatGroup);
|
if (boat.getSourceId().equals(Integer.parseInt(ClientState.getClientSourceId()))) {
|
||||||
|
boatGroup.setAsPlayer();
|
||||||
|
boatGroups.add(boatGroup);
|
||||||
|
annotations.getChildren().add(boatGroup.getAnnotations());
|
||||||
|
} else {
|
||||||
|
//Move annotations and boat to bottom of group keeping player ontop.
|
||||||
|
if (boatGroups.size() > 0) {
|
||||||
|
boatGroups.add(0, boatGroup);
|
||||||
|
} else {
|
||||||
|
boatGroups.add(boatGroup);
|
||||||
|
}
|
||||||
|
if (annotations.getChildren().size() > 0) {
|
||||||
|
annotations.getChildren().add(0, boatGroup.getAnnotations());
|
||||||
|
} else {
|
||||||
|
annotations.getChildren().add(boatGroup.getAnnotations());
|
||||||
|
}
|
||||||
|
}
|
||||||
trails.getChildren().add(boatGroup.getTrail());
|
trails.getChildren().add(boatGroup.getTrail());
|
||||||
wakes.getChildren().add(boatGroup.getWake());
|
wakes.getChildren().add(boatGroup.getWake());
|
||||||
annotations.getChildren().add(boatGroup.getAnnotations());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
group.getChildren().addAll(trails);
|
group.getChildren().addAll(trails);
|
||||||
@@ -391,10 +404,10 @@ public class CanvasController {
|
|||||||
|
|
||||||
private void drawFps(int fps){
|
private void drawFps(int fps){
|
||||||
if (raceViewController.isDisplayFps()){
|
if (raceViewController.isDisplayFps()){
|
||||||
FPSdisplay.setVisible(true);
|
FPSDisplay.setVisible(true);
|
||||||
FPSdisplay.setText(String.format("%d FPS", fps));
|
FPSDisplay.setText(String.format("%d FPS", fps));
|
||||||
} else {
|
} else {
|
||||||
FPSdisplay.setVisible(false);
|
FPSDisplay.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ public class LobbyController implements Initializable, Observer{
|
|||||||
readyButton.setDisable(true);
|
readyButton.setDisable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put all javafx objects in lists, so we can iterate though conveniently
|
||||||
imageViews = new ArrayList<>();
|
imageViews = new ArrayList<>();
|
||||||
Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView,
|
Collections.addAll(imageViews, firstImageView, secondImageView, thirdImageView, fourthImageView,
|
||||||
fifthImageView, sixthImageView, seventhImageView, eighthImageView);
|
fifthImageView, sixthImageView, seventhImageView, eighthImageView);
|
||||||
@@ -134,6 +135,13 @@ public class LobbyController implements Initializable, Observer{
|
|||||||
clientStateQueryingThread.start();
|
clientStateQueryingThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observers "ClientStateQueryingRunnable".
|
||||||
|
* When the clients state has been marked to "race start", the querying thread
|
||||||
|
* will notify this lobby to change the view
|
||||||
|
* @param o
|
||||||
|
* @param arg
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
Platform.runLater(new Runnable() {
|
Platform.runLater(new Runnable() {
|
||||||
@@ -149,6 +157,9 @@ public class LobbyController implements Initializable, Observer{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all ListViews and ImageViews according to the current competitors
|
||||||
|
*/
|
||||||
private void initialiseListView() {
|
private void initialiseListView() {
|
||||||
listViews.forEach(listView -> listView.getItems().clear());
|
listViews.forEach(listView -> listView.getItems().clear());
|
||||||
imageViews.forEach(gif -> gif.setVisible(false));
|
imageViews.forEach(gif -> gif.setVisible(false));
|
||||||
@@ -156,12 +167,15 @@ public class LobbyController implements Initializable, Observer{
|
|||||||
|
|
||||||
List<Integer> ids = new ArrayList<>(ClientState.getBoats().keySet());
|
List<Integer> ids = new ArrayList<>(ClientState.getBoats().keySet());
|
||||||
for (int i = 0; i < ids.size(); i++) {
|
for (int i = 0; i < ids.size(); i++) {
|
||||||
competitors.get(i).add(String.format("Player ID: %d", ids.get(i)));
|
competitors.get(i).add(ClientState.getBoats().get(ids.get(i)).getBoatName());
|
||||||
listViews.get(i).setItems(competitors.get(i));
|
listViews.get(i).setItems(competitors.get(i));
|
||||||
imageViews.get(i).setVisible(true);
|
imageViews.get(i).setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads preset images into imageViews
|
||||||
|
*/
|
||||||
private void initialiseImageView() {
|
private void initialiseImageView() {
|
||||||
for (int i = 0; i < MAX_NUM_PLAYERS; i++) {
|
for (int i = 0; i < MAX_NUM_PLAYERS; i++) {
|
||||||
imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png")));
|
imageViews.get(i).setImage(new Image(getClass().getResourceAsStream("/pics/sail.png")));
|
||||||
@@ -195,31 +209,11 @@ public class LobbyController implements Initializable, Observer{
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void readyButtonPressed() {
|
public void readyButtonPressed() {
|
||||||
// setContentPane("/views/RaceView.fxml");
|
|
||||||
// playTheme();
|
|
||||||
GameState.setCurrentStage(GameStages.RACING);
|
GameState.setCurrentStage(GameStages.RACING);
|
||||||
mainServerThread.startGame();
|
mainServerThread.startGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private static MediaPlayer mediaPlayer;
|
|
||||||
//
|
|
||||||
// private void playTheme() {
|
|
||||||
// Random random = new Random(System.currentTimeMillis());
|
|
||||||
// Integer rand = random.nextInt();
|
|
||||||
// if(rand == 10) {
|
|
||||||
// URL file = getClass().getResource("/music/Disturbed - down with the sickness.mp3");
|
|
||||||
// Media hit = new Media(file.toString());
|
|
||||||
// mediaPlayer = new MediaPlayer(hit);
|
|
||||||
// mediaPlayer.play();
|
|
||||||
// } else if(rand == 9) {
|
|
||||||
// URL file = getClass().getResource("/music/Owl City - Fireflies.mp3");
|
|
||||||
// Media hit = new Media(file.toString());
|
|
||||||
// mediaPlayer = new MediaPlayer(hit);
|
|
||||||
// mediaPlayer.play();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void switchToRaceView() {
|
private void switchToRaceView() {
|
||||||
if (!switchedPane) {
|
if (!switchedPane) {
|
||||||
switchedPane = true;
|
switchedPane = true;
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
updateWindDirection();
|
updateWindDirection();
|
||||||
// updateOrder();
|
// updateOrder();
|
||||||
updateBoatSelectionComboBox();
|
updateBoatSelectionComboBox();
|
||||||
|
updateOrder();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -383,9 +384,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ClientPacketParser.isRaceStarted()) {
|
if (ClientPacketParser.isRaceStarted()) {
|
||||||
|
/*
|
||||||
for (Yacht boat : ClientPacketParser.getBoatsPos().values()) {
|
for (Yacht boat : ClientPacketParser.getBoatsPos().values()) {
|
||||||
if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing
|
System.out.println("Hi tjere" + boat.getBoatName());
|
||||||
if (boat.getBoatStatus() == 3) { // 3 is finish status
|
if (participantIDs.contains(boat.getSourceId()) || true
|
||||||
|
) { // check if the boat is racing
|
||||||
|
if (boat.getBoatStatus() == 69) { // 3 is finish status
|
||||||
Text textToAdd = new Text(boat.getPosition() + ". " +
|
Text textToAdd = new Text(boat.getPosition() + ". " +
|
||||||
boat.getShortName() + " (Finished)");
|
boat.getShortName() + " (Finished)");
|
||||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||||
@@ -397,9 +401,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||||
textToAdd.setStyle("");
|
textToAdd.setStyle("");
|
||||||
positionVbox.getChildren().add(textToAdd);
|
positionVbox.getChildren().add(textToAdd);
|
||||||
|
System.out.println("Adding " + textToAdd.getText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
for (Yacht boat : ClientPacketParser.getBoats().values()){
|
||||||
|
Text textToAdd = new Text(boat.getSourceId() + ". " + boat.getShortName() + " ");
|
||||||
|
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||||
|
textToAdd.setStyle("");
|
||||||
|
positionVbox.getChildren().add(textToAdd);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Yacht boat : ClientPacketParser.getBoats().values()) {
|
for (Yacht boat : ClientPacketParser.getBoats().values()) {
|
||||||
if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing
|
if (participantIDs.contains(boat.getSourceId())) { // check if the boat is racing
|
||||||
|
|||||||
@@ -135,7 +135,11 @@ public class ImportantAnnotationController implements Initializable {
|
|||||||
boatEstTimeToNextMarkSelect.isSelected()));
|
boatEstTimeToNextMarkSelect.isSelected()));
|
||||||
boatElapsedTimeSelect.setOnAction(
|
boatElapsedTimeSelect.setOnAction(
|
||||||
event -> setAnnotation(Annotation.LEGTIME, boatElapsedTimeSelect.isSelected()));
|
event -> setAnnotation(Annotation.LEGTIME, boatElapsedTimeSelect.isSelected()));
|
||||||
|
// TODO: 26/07/17 cir27 - Create a more robust fix for this when the annotation for the game are decided upon.
|
||||||
|
boatEstTimeToNextMarkSelect.setVisible(false);
|
||||||
|
boatEstTimeToNextMarkSelect.setDisable(true);
|
||||||
|
boatElapsedTimeSelect.setVisible(false);
|
||||||
|
boatElapsedTimeSelect.setDisable(true);
|
||||||
closeButton.setOnAction(event -> stage.close());
|
closeButton.setOnAction(event -> stage.close());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class BoatAnnotations extends Group{
|
|||||||
private Text velocityObject;
|
private Text velocityObject;
|
||||||
private Text estTimeToNextMarkObject;
|
private Text estTimeToNextMarkObject;
|
||||||
private Text legTimeObject;
|
private Text legTimeObject;
|
||||||
|
private boolean isPlayer = false;
|
||||||
private Yacht boat;
|
private Yacht boat;
|
||||||
|
|
||||||
BoatAnnotations (Yacht boat, Color theme) {
|
BoatAnnotations (Yacht boat, Color theme) {
|
||||||
@@ -56,12 +56,17 @@ public class BoatAnnotations extends Group{
|
|||||||
|
|
||||||
velocityObject = getTextObject("0 m/s", theme);
|
velocityObject = getTextObject("0 m/s", theme);
|
||||||
velocityObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 2);
|
velocityObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 2);
|
||||||
|
velocityObject.setVisible(false);
|
||||||
|
|
||||||
estTimeToNextMarkObject = getTextObject("Next mark: ", theme);
|
estTimeToNextMarkObject = getTextObject("Next mark: ", theme);
|
||||||
estTimeToNextMarkObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 3);
|
estTimeToNextMarkObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 3);
|
||||||
|
estTimeToNextMarkObject.setVisible(false);
|
||||||
|
|
||||||
legTimeObject = getTextObject("Last mark: -", theme);
|
legTimeObject = getTextObject("Last mark: -", theme);
|
||||||
legTimeObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 4);
|
legTimeObject.relocate(X_OFFSET_TEXT, Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * 4);
|
||||||
|
legTimeObject.setVisible(false);
|
||||||
|
|
||||||
|
this.setVisible(true, false, false, false);
|
||||||
|
|
||||||
super.getChildren().addAll(background, teamNameObject, velocityObject, estTimeToNextMarkObject, legTimeObject);
|
super.getChildren().addAll(background, teamNameObject, velocityObject, estTimeToNextMarkObject, legTimeObject);
|
||||||
}
|
}
|
||||||
@@ -83,6 +88,8 @@ public class BoatAnnotations extends Group{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update () {
|
void update () {
|
||||||
|
teamNameObject.setText("Player: " + boat.getShortName());
|
||||||
|
|
||||||
velocityObject.setText(String.format(String.format("%.2f m/s", boat.getVelocityMMS())));
|
velocityObject.setText(String.format(String.format("%.2f m/s", boat.getVelocityMMS())));
|
||||||
|
|
||||||
if (boat.getTimeTillNext() != null) {
|
if (boat.getTimeTillNext() != null) {
|
||||||
@@ -104,13 +111,19 @@ public class BoatAnnotations extends Group{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVisibile (boolean nameVisibility, boolean speedVisibility,
|
void setVisible(boolean nameVisibility, boolean speedVisibility,
|
||||||
boolean estTimeVisibility, boolean lastMarkVisibility) {
|
boolean estTimeVisibility, boolean lastMarkVisibility) {
|
||||||
int totalVisible = 0;
|
int totalVisible = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is a temporary fix until the new annotation group is added along with the visualiser
|
||||||
|
overhaul.
|
||||||
|
*/
|
||||||
totalVisible = updateVisibility(nameVisibility, teamNameObject, totalVisible);
|
totalVisible = updateVisibility(nameVisibility, teamNameObject, totalVisible);
|
||||||
totalVisible = updateVisibility(speedVisibility, velocityObject, totalVisible);
|
if (isPlayer)
|
||||||
totalVisible = updateVisibility(estTimeVisibility, estTimeToNextMarkObject, totalVisible);
|
totalVisible = updateVisibility(speedVisibility, velocityObject, totalVisible);
|
||||||
totalVisible = updateVisibility(lastMarkVisibility, legTimeObject, totalVisible);
|
// totalVisible = updateVisibility(estTimeVisibility, estTimeToNextMarkObject, totalVisible);
|
||||||
|
// totalVisible = updateVisibility(lastMarkVisibility, legTimeObject, totalVisible);
|
||||||
if (totalVisible != 0) {
|
if (totalVisible != 0) {
|
||||||
background.setVisible(true);
|
background.setVisible(true);
|
||||||
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * totalVisible);
|
background.setHeight(Math.abs(BACKGROUND_X) + TEXT_BUFFER + BACKGROUND_H_PER_TEXT * totalVisible);
|
||||||
@@ -130,4 +143,12 @@ public class BoatAnnotations extends Group{
|
|||||||
}
|
}
|
||||||
return totalVisible;
|
return totalVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets these annotations to show more detailed info.
|
||||||
|
*/
|
||||||
|
public void setAsPlayer () {
|
||||||
|
isPlayer = true;
|
||||||
|
velocityObject.setVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import javafx.geometry.Point2D;
|
|||||||
import javafx.scene.CacheHint;
|
import javafx.scene.CacheHint;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.scene.shape.Line;
|
import javafx.scene.shape.Line;
|
||||||
import javafx.scene.shape.Polygon;
|
import javafx.scene.shape.Polygon;
|
||||||
import javafx.scene.transform.Rotate;
|
import javafx.scene.transform.Rotate;
|
||||||
@@ -48,8 +49,9 @@ public class BoatGroup extends Group {
|
|||||||
private Point2D lastPoint;
|
private Point2D lastPoint;
|
||||||
private boolean destinationSet;
|
private boolean destinationSet;
|
||||||
private BoatAnnotations boatAnnotations;
|
private BoatAnnotations boatAnnotations;
|
||||||
|
private Color color;
|
||||||
private Boolean isSelected = true; //All boats are initialised as selected
|
private Boolean isSelected = true; //All boats are initialised as selected\
|
||||||
|
private boolean isPlayer = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BoatGroup with the default triangular boat polygon.
|
* Creates a BoatGroup with the default triangular boat polygon.
|
||||||
@@ -88,20 +90,21 @@ public class BoatGroup extends Group {
|
|||||||
* polygon.
|
* polygon.
|
||||||
*/
|
*/
|
||||||
private void initChildren(Color color, double... points) {
|
private void initChildren(Color color, double... points) {
|
||||||
|
this.color = color;
|
||||||
boatPoly = new Polygon(points);
|
boatPoly = new Polygon(points);
|
||||||
boatPoly.setFill(color);
|
boatPoly.setFill(this.color);
|
||||||
boatPoly.setOnMouseEntered(event -> {
|
boatPoly.setOnMouseEntered(event -> {
|
||||||
boatPoly.setFill(Color.FLORALWHITE);
|
boatPoly.setFill(Color.FLORALWHITE);
|
||||||
boatPoly.setStroke(Color.RED);
|
boatPoly.setStroke(Color.RED);
|
||||||
});
|
});
|
||||||
boatPoly.setOnMouseExited(event -> {
|
boatPoly.setOnMouseExited(event -> {
|
||||||
boatPoly.setFill(color);
|
boatPoly.setFill(this.color);
|
||||||
boatPoly.setStroke(Color.BLACK);
|
boatPoly.setStroke(Color.BLACK);
|
||||||
});
|
});
|
||||||
boatPoly.setOnMouseClicked(event -> setIsSelected(!isSelected));
|
boatPoly.setOnMouseClicked(event -> setIsSelected(!isSelected));
|
||||||
boatPoly.setCache(true);
|
boatPoly.setCache(true);
|
||||||
boatPoly.setCacheHint(CacheHint.SPEED);
|
boatPoly.setCacheHint(CacheHint.SPEED);
|
||||||
boatAnnotations = new BoatAnnotations(boat, color);
|
boatAnnotations = new BoatAnnotations(boat, this.color);
|
||||||
|
|
||||||
leftLayLine = new Line();
|
leftLayLine = new Line();
|
||||||
rightLayline = new Line();
|
rightLayline = new Line();
|
||||||
@@ -160,42 +163,6 @@ public class BoatGroup extends Group {
|
|||||||
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void move() {
|
|
||||||
double dx = xIncrement * framesToMove;
|
|
||||||
double dy = yIncrement * framesToMove;
|
|
||||||
|
|
||||||
distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
|
||||||
moveGroupBy(xIncrement, yIncrement);
|
|
||||||
framesToMove = framesToMove - 1;
|
|
||||||
|
|
||||||
if (framesToMove <= 0) {
|
|
||||||
isStopped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (distanceTravelled > 70) {
|
|
||||||
// distanceTravelled = 0d;
|
|
||||||
//
|
|
||||||
// if (lastPoint != null) {
|
|
||||||
// Line l = new Line(
|
|
||||||
// lastPoint.getX(),
|
|
||||||
// lastPoint.getY(),
|
|
||||||
// boatPoly.getLayoutX(),
|
|
||||||
// boatPoly.getLayoutY()
|
|
||||||
// );
|
|
||||||
// l.getStrokeDashArray().setAll(3d, 7d);
|
|
||||||
// l.setStroke(boat.getColour());
|
|
||||||
// l.setCache(true);
|
|
||||||
// l.setCacheHint(CacheHint.SPEED);
|
|
||||||
// lineGroup.getChildren().add(l);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (destinationSet) {
|
|
||||||
// lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
wake.updatePosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the destination of the boat and the headng it should have once it reaches
|
* Sets the destination of the boat and the headng it should have once it reaches
|
||||||
*
|
*
|
||||||
@@ -206,26 +173,42 @@ public class BoatGroup extends Group {
|
|||||||
*/
|
*/
|
||||||
public void setDestination(double newXValue, double newYValue, double rotation,
|
public void setDestination(double newXValue, double newYValue, double rotation,
|
||||||
double groundSpeed, long timeValid, double frameRate) {
|
double groundSpeed, long timeValid, double frameRate) {
|
||||||
if (lastTimeValid == 0) {
|
|
||||||
lastTimeValid = timeValid - 200;
|
|
||||||
moveTo(newXValue, newYValue, rotation);
|
|
||||||
}
|
|
||||||
framesToMove = Math.round((frameRate / (1000.0f / (timeValid - lastTimeValid))));
|
|
||||||
double dx = newXValue - boatPoly.getLayoutX();
|
|
||||||
double dy = newYValue - boatPoly.getLayoutY();
|
|
||||||
|
|
||||||
xIncrement = dx / framesToMove;
|
|
||||||
yIncrement = dy / framesToMove;
|
|
||||||
|
|
||||||
destinationSet = true;
|
destinationSet = true;
|
||||||
|
Double dx = Math.abs(boatPoly.getLayoutX() - newXValue);
|
||||||
|
Double dy = Math.abs(boatPoly.getLayoutY() - newYValue);
|
||||||
|
moveTo(newXValue, newYValue, rotation);
|
||||||
|
|
||||||
|
|
||||||
rotateTo(rotation);
|
rotateTo(rotation);
|
||||||
wake.setRotation(rotation, groundSpeed);
|
wake.setRotation(rotation, groundSpeed);
|
||||||
boat.setVelocity(groundSpeed);
|
boat.setVelocity(groundSpeed);
|
||||||
lastTimeValid = timeValid;
|
|
||||||
isStopped = false;
|
isStopped = false;
|
||||||
lastRotation = rotation;
|
lastRotation = rotation;
|
||||||
boatAnnotations.update();
|
boatAnnotations.update();
|
||||||
|
|
||||||
|
distanceTravelled += Math.sqrt((dx * dx) + (dy * dy));
|
||||||
|
|
||||||
|
if (distanceTravelled > 10 && isPlayer) {
|
||||||
|
distanceTravelled = 0d;
|
||||||
|
|
||||||
|
if (lastPoint != null) {
|
||||||
|
Line l = new Line(
|
||||||
|
lastPoint.getX(),
|
||||||
|
lastPoint.getY(),
|
||||||
|
boatPoly.getLayoutX(),
|
||||||
|
boatPoly.getLayoutY()
|
||||||
|
);
|
||||||
|
l.getStrokeDashArray().setAll(3d, 7d);
|
||||||
|
l.setStroke(boat.getColour());
|
||||||
|
l.setCache(true);
|
||||||
|
l.setCacheHint(CacheHint.SPEED);
|
||||||
|
lineGroup.getChildren().add(l);
|
||||||
|
}
|
||||||
|
if (destinationSet) {
|
||||||
|
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -276,7 +259,7 @@ public class BoatGroup extends Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime, boolean trail, boolean wake) {
|
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime, boolean trail, boolean wake) {
|
||||||
boatAnnotations.setVisibile(teamName, velocity, estTime, legTime);
|
boatAnnotations.setVisible(teamName, velocity, estTime, legTime);
|
||||||
this.wake.setVisible(wake);
|
this.wake.setVisible(wake);
|
||||||
this.lineGroup.setVisible(trail);
|
this.lineGroup.setVisible(trail);
|
||||||
}
|
}
|
||||||
@@ -349,4 +332,18 @@ public class BoatGroup extends Group {
|
|||||||
return boat.toString();
|
return boat.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this boat to appear highlighted
|
||||||
|
*/
|
||||||
|
public void setAsPlayer() {
|
||||||
|
boatPoly.getPoints().setAll(
|
||||||
|
-BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75,
|
||||||
|
0.0, -BOAT_HEIGHT / 1.75,
|
||||||
|
BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75
|
||||||
|
);
|
||||||
|
boatPoly.setStroke(Color.BLACK);
|
||||||
|
boatPoly.setStrokeWidth(3);
|
||||||
|
boatAnnotations.setAsPlayer();
|
||||||
|
isPlayer = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -55,29 +55,29 @@ public class Wake extends Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setRotation (double rotation, double velocity) {
|
void setRotation (double rotation, double velocity) {
|
||||||
if (Math.abs(rotations[0] - rotation) > 20) {
|
// if (Math.abs(rotations[0] - rotation) > 20) {
|
||||||
rotate(rotation);
|
rotate(rotation);
|
||||||
} else {
|
// } else {
|
||||||
rotations[0] = rotation;
|
// rotations[0] = rotation;
|
||||||
((Rotate) arcs[0].getTransforms().get(0)).setAngle(rotation);
|
// ((Rotate) arcs[0].getTransforms().get(0)).setAngle(rotation);
|
||||||
for (int i = 1; i < numWakes; i++) {
|
// for (int i = 1; i < numWakes; i++) {
|
||||||
double wakeSeparationRad = Math.toRadians(rotations[i - 1] - rotations[i]);
|
// double wakeSeparationRad = Math.toRadians(rotations[i - 1] - rotations[i]);
|
||||||
double shortestDistance = Math.atan2(
|
// double shortestDistance = Math.atan2(
|
||||||
Math.sin(wakeSeparationRad),
|
// Math.sin(wakeSeparationRad),
|
||||||
Math.cos(wakeSeparationRad)
|
// Math.cos(wakeSeparationRad)
|
||||||
);
|
// );
|
||||||
double distDeg = Math.toDegrees(shortestDistance);
|
// double distDeg = Math.toDegrees(shortestDistance);
|
||||||
if (rotationalVelocities[i - 1] < 0.01 && rotationalVelocities[i - 1] > -0.01) {
|
// 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);
|
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * 2 * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
||||||
|
//
|
||||||
} else {
|
// } else {
|
||||||
if (distDeg < (MAX_DIFF / numWakes)) {
|
// if (distDeg < (MAX_DIFF / numWakes)) {
|
||||||
rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
// rotationalVelocities[i] = distDeg / UNIFICATION_SPEED * Math.log(Math.abs(distDeg) + 1) / Math.log(MAX_DIFF / numWakes);
|
||||||
} else
|
// } else
|
||||||
rotationalVelocities[i] = rotationalVelocities[i - 1];
|
// rotationalVelocities[i] = rotationalVelocities[i - 1];
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
double rad = (14 / numWakes) + velocity;
|
double rad = (14 / numWakes) + velocity;
|
||||||
for (Arc arc : arcs) {
|
for (Arc arc : arcs) {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import seng302.client.ClientPacketParser;
|
import seng302.client.ClientPacketParser;
|
||||||
import seng302.models.Player;
|
import seng302.models.Player;
|
||||||
|
|
||||||
import seng302.models.Yacht;
|
import seng302.models.Yacht;
|
||||||
import seng302.server.messages.BoatActionType;
|
import seng302.server.messages.BoatActionType;
|
||||||
|
|
||||||
@@ -12,7 +13,9 @@ import seng302.server.messages.BoatActionType;
|
|||||||
* A Static class to hold information about the current state of the game (model)
|
* A Static class to hold information about the current state of the game (model)
|
||||||
* Created by wmu16 on 10/07/17.
|
* Created by wmu16 on 10/07/17.
|
||||||
*/
|
*/
|
||||||
public class GameState {
|
public class GameState implements Runnable {
|
||||||
|
|
||||||
|
private static Integer STATE_UPDATES_PER_SECOND = 60;
|
||||||
|
|
||||||
private static Long previousUpdateTime;
|
private static Long previousUpdateTime;
|
||||||
public static Double windDirection;
|
public static Double windDirection;
|
||||||
@@ -24,14 +27,17 @@ public class GameState {
|
|||||||
private static Boolean isRaceStarted;
|
private static Boolean isRaceStarted;
|
||||||
private static GameStages currentStage;
|
private static GameStages currentStage;
|
||||||
|
|
||||||
|
private static long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
||||||
public GameState(String hostIpAddress) {
|
public GameState(String hostIpAddress) {
|
||||||
windDirection = 170d;
|
windDirection = 180d;
|
||||||
windSpeed = 10000d;
|
windSpeed = 10000d;
|
||||||
yachts = new HashMap<>();
|
yachts = new HashMap<>();
|
||||||
players = new ArrayList<>();
|
players = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
GameState.hostIpAddress = hostIpAddress;
|
this.hostIpAddress = hostIpAddress;
|
||||||
players = new ArrayList<>();
|
players = new ArrayList<>();
|
||||||
currentStage = GameStages.LOBBYING;
|
currentStage = GameStages.LOBBYING;
|
||||||
isRaceStarted = false;
|
isRaceStarted = false;
|
||||||
@@ -39,6 +45,9 @@ public class GameState {
|
|||||||
//set this when game stage changes to prerace
|
//set this when game stage changes to prerace
|
||||||
previousUpdateTime = System.currentTimeMillis();
|
previousUpdateTime = System.currentTimeMillis();
|
||||||
yachts = new HashMap<>();
|
yachts = new HashMap<>();
|
||||||
|
|
||||||
|
new Thread(this).start();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getHostIpAddress() {
|
public static String getHostIpAddress() {
|
||||||
@@ -74,9 +83,17 @@ public class GameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setCurrentStage(GameStages currentStage) {
|
public static void setCurrentStage(GameStages currentStage) {
|
||||||
|
if (currentStage == GameStages.RACING){
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
GameState.currentStage = currentStage;
|
GameState.currentStage = currentStage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getStartTime(){
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
public static Double getWindDirection() {
|
public static Double getWindDirection() {
|
||||||
return windDirection;
|
return windDirection;
|
||||||
}
|
}
|
||||||
@@ -100,7 +117,6 @@ public class GameState {
|
|||||||
case VMG:
|
case VMG:
|
||||||
playerYacht.turnToVMG();
|
playerYacht.turnToVMG();
|
||||||
// System.out.println("Snapping to VMG");
|
// System.out.println("Snapping to VMG");
|
||||||
// TODO: 22/07/17 wmu16 - Add in the vmg calculation code here
|
|
||||||
break;
|
break;
|
||||||
case SAILS_IN:
|
case SAILS_IN:
|
||||||
playerYacht.toggleSailIn();
|
playerYacht.toggleSailIn();
|
||||||
@@ -134,7 +150,6 @@ public class GameState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void update() {
|
public static void update() {
|
||||||
|
|
||||||
Long timeInterval = System.currentTimeMillis() - previousUpdateTime;
|
Long timeInterval = System.currentTimeMillis() - previousUpdateTime;
|
||||||
previousUpdateTime = System.currentTimeMillis();
|
previousUpdateTime = System.currentTimeMillis();
|
||||||
for (Yacht yacht : yachts.values()) {
|
for (Yacht yacht : yachts.values()) {
|
||||||
@@ -151,4 +166,28 @@ public class GameState {
|
|||||||
// TODO: 22/07/17 wmu16 - This may not be robust enough and may have to be improved on.
|
// TODO: 22/07/17 wmu16 - This may not be robust enough and may have to be improved on.
|
||||||
return yachts.size() + 1;
|
return yachts.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A thread to have the game state update itself at certain intervals
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000 / STATE_UPDATES_PER_SECOND);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (currentStage == GameStages.PRE_RACE) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
//RACING
|
||||||
|
if (currentStage == GameStages.RACING) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,28 +11,26 @@ import java.io.IOException;
|
|||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class describing the overall server, which creates and collects server threads for each client
|
* A class describing the overall server, which creates and collects server threads for each client
|
||||||
* Created by wmu16 on 13/07/17.
|
* Created by wmu16 on 13/07/17.
|
||||||
*/
|
*/
|
||||||
public class MainServerThread extends Observable implements Runnable, PacketBufferDelegate, ClientConnectionDelegate{
|
public class MainServerThread extends Observable implements Runnable, ClientConnectionDelegate{
|
||||||
|
|
||||||
private static final int PORT = 4942;
|
private static final int PORT = 4942;
|
||||||
private static final Integer MAX_NUM_PLAYERS = 3;
|
private static final Integer CLIENT_UPDATES_PER_SECOND = 10;
|
||||||
private static final Integer UPDATES_PER_SECOND = 2;
|
|
||||||
private static final int LOG_LEVEL = 1;
|
private static final int LOG_LEVEL = 1;
|
||||||
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
|
|
||||||
private ServerSocket serverSocket = null;
|
private ServerSocket serverSocket = null;
|
||||||
private Socket socket;
|
|
||||||
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
|
private ArrayList<ServerToClientThread> serverToClientThreads = new ArrayList<>();
|
||||||
|
|
||||||
private PriorityBlockingQueue<StreamPacket> packetBuffer;
|
|
||||||
|
|
||||||
|
|
||||||
public MainServerThread() {
|
public MainServerThread() {
|
||||||
try {
|
try {
|
||||||
serverSocket = new ServerSocket(PORT);
|
serverSocket = new ServerSocket(PORT);
|
||||||
@@ -40,8 +38,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
serverLog("IO error in server thread handler upon trying to make new server socket", 0);
|
serverLog("IO error in server thread handler upon trying to make new server socket", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
packetBuffer = new PriorityBlockingQueue<>();
|
|
||||||
|
|
||||||
thread = new Thread(this);
|
thread = new Thread(this);
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
@@ -57,22 +53,20 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
heartbeatThread.start();
|
heartbeatThread.start();
|
||||||
serverListenThread.start();
|
serverListenThread.start();
|
||||||
|
|
||||||
|
|
||||||
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
|
//You should handle interrupts in some way, so that the thread won't keep on forever if you exit the app.
|
||||||
while (!thread.isInterrupted()) {
|
while (!thread.isInterrupted()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000 / UPDATES_PER_SECOND);
|
Thread.sleep(1000 / CLIENT_UPDATES_PER_SECOND);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
|
if (GameState.getCurrentStage() == GameStages.PRE_RACE) {
|
||||||
GameState.update();
|
updateClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
//RACING
|
//RACING
|
||||||
if (GameState.getCurrentStage() == GameStages.RACING) {
|
if (GameState.getCurrentStage() == GameStages.RACING) {
|
||||||
GameState.update();
|
|
||||||
updateClients();
|
updateClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,14 +75,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!packetBuffer.isEmpty()){
|
|
||||||
try {
|
|
||||||
StreamPacket packet = packetBuffer.take();
|
|
||||||
ClientPacketParser.parsePacket(packet);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 14/07/17 wmu16 - Send out disconnect packet to clients
|
// TODO: 14/07/17 wmu16 - Send out disconnect packet to clients
|
||||||
@@ -113,11 +99,6 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addToBuffer(StreamPacket streamPacket) {
|
|
||||||
return packetBuffer.add(streamPacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client has tried to connect to the server
|
* A client has tried to connect to the server
|
||||||
* @param serverToClientThread The player that connected
|
* @param serverToClientThread The player that connected
|
||||||
@@ -155,8 +136,16 @@ public class MainServerThread extends Observable implements Runnable, PacketBuff
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startGame() {
|
public void startGame() {
|
||||||
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
Timer t = new Timer();
|
||||||
serverToClientThread.sendRaceStatusMessage();
|
|
||||||
}
|
t.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
for (ServerToClientThread serverToClientThread : serverToClientThreads) {
|
||||||
|
serverToClientThread.sendRaceStatusMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 0, 500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package seng302.gameServer;
|
package seng302.gameServer;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
@@ -12,6 +15,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.zip.CRC32;
|
import java.util.zip.CRC32;
|
||||||
import java.util.zip.Checksum;
|
import java.util.zip.Checksum;
|
||||||
|
|
||||||
@@ -64,17 +70,42 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
|
|
||||||
public ServerToClientThread(Socket socket) {
|
public ServerToClientThread(Socket socket) {
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
|
BufferedReader fn;
|
||||||
|
String fName = "";
|
||||||
|
BufferedReader ln;
|
||||||
|
String lName = "";
|
||||||
try {
|
try {
|
||||||
is = socket.getInputStream();
|
is = socket.getInputStream();
|
||||||
os = socket.getOutputStream();
|
os = socket.getOutputStream();
|
||||||
|
fn = new BufferedReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
ServerToClientThread.class.getResourceAsStream(
|
||||||
|
"/server_config/CSV_Database_of_First_Names.csv"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
List<String> all = fn.lines().collect(Collectors.toList());
|
||||||
|
fName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
|
||||||
|
ln = new BufferedReader(
|
||||||
|
new InputStreamReader(
|
||||||
|
ServerToClientThread.class.getResourceAsStream(
|
||||||
|
"/server_config/CSV_Database_of_Last_Names.csv"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
all = ln.lines().collect(Collectors.toList());
|
||||||
|
lName = all.get(ThreadLocalRandom.current().nextInt(0, all.size()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.out.println("IO error in server thread upon grabbing streams");
|
System.out.println("IO error in server thread upon grabbing streams");
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
//Attempt threeway handshake with connection
|
//Attempt threeway handshake with connection
|
||||||
sourceId = GameState.getUniquePlayerID();
|
sourceId = GameState.getUniquePlayerID();
|
||||||
if (threeWayHandshake(sourceId)) {
|
if (threeWayHandshake(sourceId)) {
|
||||||
serverLog("Successful handshake. Client allocated id: " + sourceId, 1);
|
serverLog("Successful handshake. Client allocated id: " + sourceId, 1);
|
||||||
Yacht yacht = new Yacht("Yacht", sourceId, sourceId.toString(), "Kapa", "Kappa", "NZ");
|
Yacht yacht = new Yacht(
|
||||||
|
"Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ"
|
||||||
|
);
|
||||||
// Yacht yacht = new Yacht("Kappa", "Kap", new GeoPoint(57.6708220, 11.8321340), 90.0);
|
// Yacht yacht = new Yacht("Kappa", "Kap", new GeoPoint(57.6708220, 11.8321340), 90.0);
|
||||||
GameState.addYacht(sourceId, yacht);
|
GameState.addYacht(sourceId, yacht);
|
||||||
GameState.addPlayer(new Player(socket, yacht));
|
GameState.addPlayer(new Player(socket, yacht));
|
||||||
@@ -109,11 +140,6 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
while (socket.isConnected()) {
|
while (socket.isConnected()) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// if (initialisedRace) {
|
|
||||||
// sendSetupMessages();
|
|
||||||
// initialisedRace = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Perform a write if it is time to as delegated by the MainServerThread
|
//Perform a write if it is time to as delegated by the MainServerThread
|
||||||
if (updateClient) {
|
if (updateClient) {
|
||||||
// TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
|
// TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream
|
||||||
@@ -165,7 +191,6 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSetupMessages() {
|
private void sendSetupMessages() {
|
||||||
@@ -180,18 +205,18 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
xml.setRegatta(new Regatta("RaceVision Test Game", 57.6679590, 11.8503233));
|
xml.setRegatta(new Regatta("RaceVision Test Game", 57.6679590, 11.8503233));
|
||||||
xml.setRace(race);
|
xml.setRace(race);
|
||||||
|
|
||||||
XMLMessage xmlMessage = new XMLMessage(xml.getRegattaAsXml(), XMLMessageSubType.REGATTA,
|
XMLMessage xmlMessage;
|
||||||
xml.getRegattaAsXml().length());
|
xmlMessage = new XMLMessage(xml.getRegattaAsXml(), XMLMessageSubType.REGATTA,
|
||||||
|
xml.getRegattaAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
|
|
||||||
xmlMessage = new XMLMessage(xml.getBoatsAsXml(), XMLMessageSubType.BOAT,
|
xmlMessage = new XMLMessage(xml.getBoatsAsXml(), XMLMessageSubType.BOAT,
|
||||||
xml.getBoatsAsXml().length());
|
xml.getBoatsAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
|
|
||||||
xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE,
|
xmlMessage = new XMLMessage(xml.getRaceAsXml(), XMLMessageSubType.RACE,
|
||||||
xml.getRaceAsXml().length());
|
xml.getRaceAsXml().length());
|
||||||
sendMessage(xmlMessage);
|
sendMessage(xmlMessage);
|
||||||
// System.out.println("Sent xml messages for " + thread.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateClient() {
|
public void updateClient() {
|
||||||
@@ -310,8 +335,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
|
|
||||||
public void sendRaceStatusMessage() {
|
public void sendRaceStatusMessage() {
|
||||||
// variables taken from GameServerThread
|
// variables taken from GameServerThread
|
||||||
int TIME_TILL_RACE_START = 20 * 1000;
|
|
||||||
long startTime = System.currentTimeMillis() + TIME_TILL_RACE_START;
|
|
||||||
|
|
||||||
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
List<BoatSubMessage> boatSubMessages = new ArrayList<>();
|
||||||
BoatStatus boatStatus;
|
BoatStatus boatStatus;
|
||||||
@@ -339,7 +363,7 @@ public class ServerToClientThread implements Runnable, Observer {
|
|||||||
raceStatus = RaceStatus.WARNING;
|
raceStatus = RaceStatus.WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(new RaceStatusMessage(1, raceStatus, startTime, GameState.getWindDirection(),
|
sendMessage(new RaceStatusMessage(1, raceStatus, GameState.getStartTime(), GameState.getWindDirection(),
|
||||||
GameState.getWindSpeedMMS().longValue(), GameState.getPlayers().size(),
|
GameState.getWindSpeedMMS().longValue(), GameState.getPlayers().size(),
|
||||||
RaceType.MATCH_RACE, 1, boatSubMessages));
|
RaceType.MATCH_RACE, 1, boatSubMessages));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import java.io.BufferedReader;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Array;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,4 +180,5 @@ public final class PolarTable {
|
|||||||
return closestAngle;
|
return closestAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,7 @@ import static seng302.utilities.GeoUtility.getGeoCoordinate;
|
|||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import seng302.client.ClientPacketParser;
|
import seng302.client.ClientPacketParser;
|
||||||
import seng302.controllers.RaceViewController;
|
import seng302.controllers.RaceViewController;
|
||||||
@@ -119,17 +118,38 @@ public class Yacht {
|
|||||||
* @param timeInterval since last update in milliseconds
|
* @param timeInterval since last update in milliseconds
|
||||||
*/
|
*/
|
||||||
public void update(Long timeInterval) {
|
public void update(Long timeInterval) {
|
||||||
if (sailIn) {
|
|
||||||
Double secondsElapsed = timeInterval / 1000000.0;
|
Double secondsElapsed = timeInterval / 1000000.0;
|
||||||
Double windSpeedKnots = GameState.getWindSpeedKnots();
|
Double windSpeedKnots = GameState.getWindSpeedKnots();
|
||||||
Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
|
Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading);
|
||||||
Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
|
Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle);
|
||||||
velocity = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000;
|
Double maxBoatSpeed = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000;
|
||||||
Double metersCovered = velocity * secondsElapsed;
|
if (sailIn && velocity <= maxBoatSpeed && maxBoatSpeed != 0d) {
|
||||||
location = getGeoCoordinate(location, heading, metersCovered);
|
|
||||||
} else {
|
if (velocity < maxBoatSpeed) {
|
||||||
velocity = 0d;
|
velocity += maxBoatSpeed / 15; // Acceleration
|
||||||
|
}
|
||||||
|
if (velocity > maxBoatSpeed) {
|
||||||
|
velocity = maxBoatSpeed; // Prevent the boats from exceeding top speed
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // Deceleration
|
||||||
|
|
||||||
|
if (velocity > 0d) {
|
||||||
|
if (maxBoatSpeed != 0d) {
|
||||||
|
velocity -= maxBoatSpeed / 600;
|
||||||
|
} else {
|
||||||
|
velocity -= velocity / 100;
|
||||||
|
}
|
||||||
|
if (velocity < 0) {
|
||||||
|
velocity = 0d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Double metersCovered = velocity * secondsElapsed;
|
||||||
|
location = getGeoCoordinate(location, heading, metersCovered);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -145,8 +165,7 @@ public class Yacht {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void tackGybe(Double windDirection) {
|
public void tackGybe(Double windDirection) {
|
||||||
Double normalizedHeading = heading - GameState.windDirection;
|
Double normalizedHeading = normalizeHeading();
|
||||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360);
|
|
||||||
adjustHeading(-2 * normalizedHeading);
|
adjustHeading(-2 * normalizedHeading);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +174,7 @@ public class Yacht {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void turnUpwind() {
|
public void turnUpwind() {
|
||||||
Double normalizedHeading = heading - GameState.windDirection;
|
Double normalizedHeading = normalizeHeading();
|
||||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360);
|
|
||||||
if (normalizedHeading == 0) {
|
if (normalizedHeading == 0) {
|
||||||
if (lastHeading < 180) {
|
if (lastHeading < 180) {
|
||||||
adjustHeading(-TURN_STEP);
|
adjustHeading(-TURN_STEP);
|
||||||
@@ -177,8 +195,7 @@ public class Yacht {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void turnDownwind() {
|
public void turnDownwind() {
|
||||||
Double normalizedHeading = heading - GameState.windDirection;
|
Double normalizedHeading = normalizeHeading();
|
||||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360);
|
|
||||||
if (normalizedHeading == 0) {
|
if (normalizedHeading == 0) {
|
||||||
if (lastHeading < 180) {
|
if (lastHeading < 180) {
|
||||||
adjustHeading(TURN_STEP);
|
adjustHeading(TURN_STEP);
|
||||||
@@ -199,10 +216,43 @@ public class Yacht {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void turnToVMG() {
|
public void turnToVMG() {
|
||||||
// TODO: 25/07/17 wmu16 - Fix this so it grabs the optimal value from the optimal Polar
|
Double normalizedHeading = normalizeHeading();
|
||||||
|
Double optimalHeading;
|
||||||
|
HashMap<Double, Double> optimalPolarMap;
|
||||||
|
|
||||||
|
if (normalizedHeading >= 90 && normalizedHeading <= 270) { // Downwind
|
||||||
|
optimalPolarMap = PolarTable.getOptimalDownwindVMG(GameState.getWindSpeedKnots());
|
||||||
|
optimalHeading = optimalPolarMap.keySet().iterator().next();
|
||||||
|
} else {
|
||||||
|
optimalPolarMap = PolarTable.getOptimalUpwindVMG(GameState.getWindSpeedKnots());
|
||||||
|
optimalHeading = optimalPolarMap.keySet().iterator().next();
|
||||||
|
}
|
||||||
|
// Take optimal heading and turn into correct
|
||||||
|
optimalHeading =
|
||||||
|
optimalHeading + (double) Math.floorMod(GameState.getWindDirection().longValue(), 360L);
|
||||||
|
|
||||||
|
turnTowardsHeading(optimalHeading);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void turnTowardsHeading(Double newHeading) {
|
||||||
|
System.out.println(newHeading);
|
||||||
|
if (heading < 90 && newHeading > 270) {
|
||||||
|
adjustHeading(-TURN_STEP);
|
||||||
|
} else {
|
||||||
|
if (heading < newHeading) {
|
||||||
|
adjustHeading(TURN_STEP);
|
||||||
|
} else {
|
||||||
|
adjustHeading(-TURN_STEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Double normalizeHeading() {
|
||||||
|
Double normalizedHeading = heading - GameState.windDirection;
|
||||||
|
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
|
||||||
|
return normalizedHeading;
|
||||||
|
}
|
||||||
|
|
||||||
public String getBoatType() {
|
public String getBoatType() {
|
||||||
return boatType;
|
return boatType;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Tws,Twa0,Bsp0,Twa1,Bsp1,UpTwa,UpBsp,Twa2,Bsp2,Twa3,Bsp3,Twa4,Bsp4,Twa5,Bsp5,Twa6,Bsp6,DnTwa,DnBsp,Twa7,Bsp7
|
Tws,Twa0,Bsp0,Twa1,Bsp1,UpTwa,UpBsp,Twa2,Bsp2,Twa3,Bsp3,Twa4,Bsp4,Twa5,Bsp5,Twa6,Bsp6,DnTwa,DnBsp,Twa7,Bsp7
|
||||||
4,0,0,30,4,45,8,60,9,75,10,90,10,115,10,145,10,155,10,175,4
|
4,0,0,30,4,45,8,60,9,75,10,90,10,115,10,145,10,155,10,175,4
|
||||||
8,0,0,30,7,43,10,60,11,75,11,90,11,115,12,145,12,153,12,175,10
|
8,0,0,30,7,43,10,60,11,75,11,90,11,115,12,145,12,153,12,175,10
|
||||||
12,0,0,30,11,43,14.4,60,16,75,20,90,23,115,24,145,23,153,21.6,175,14
|
12,0,0,30,11,43,14.4,60,16,75,20,90,23,115,24,145,23,153,21.6,175,14
|
||||||
|
|||||||
|
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
@@ -20,31 +20,31 @@
|
|||||||
<children>
|
<children>
|
||||||
<AnchorPane prefHeight="960.0" prefWidth="250.0" style="-fx-background-color: #2C2c36;" GridPane.rowSpan="3">
|
<AnchorPane prefHeight="960.0" prefWidth="250.0" style="-fx-background-color: #2C2c36;" GridPane.rowSpan="3">
|
||||||
<children>
|
<children>
|
||||||
<Label layoutX="11.0" layoutY="259.0" text="Team Position" textFill="WHITE" />
|
<Label layoutX="11.0" layoutY="283.0" text="Team Position" textFill="WHITE" />
|
||||||
<Label layoutX="13.0" layoutY="432.0" text="Settings" textFill="WHITE" />
|
<Label layoutX="13.0" layoutY="432.0" text="Settings" textFill="WHITE" />
|
||||||
<Label layoutX="11.0" layoutY="14.0" text="Timer" textFill="WHITE" />
|
<Label layoutX="11.0" layoutY="41.0" text="Timer" textFill="WHITE" />
|
||||||
<Label layoutX="11.0" layoutY="88.0" text="Wind direction" textFill="WHITE" />
|
<Label layoutX="11.0" layoutY="112.0" text="Wind direction" textFill="WHITE" />
|
||||||
<Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#3dcdc8" layoutX="110.0" layoutY="166.0" radius="35.0" stroke="#d7d7d7" strokeType="INSIDE" strokeWidth="3.0" />
|
<Circle fx:id="windBackgroundCircle" blendMode="DARKEN" fill="#3dcdc8" layoutX="110.0" layoutY="190.0" radius="35.0" stroke="#d7d7d7" strokeType="INSIDE" strokeWidth="3.0" />
|
||||||
<Text fx:id="windArrowText" fill="#a8a8a8" layoutX="86.0" layoutY="186.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↓">
|
<Text fx:id="windArrowText" fill="#a8a8a8" layoutX="86.0" layoutY="210.0" strokeType="OUTSIDE" strokeWidth="0.0" text="↓">
|
||||||
<font>
|
<font>
|
||||||
<Font name="AdobeArabic-Regular" size="55.0" />
|
<Font name="AdobeArabic-Regular" size="55.0" />
|
||||||
</font>
|
</font>
|
||||||
</Text>
|
</Text>
|
||||||
<Text fx:id="windDirectionText" fill="#d3d3d3" layoutX="171.0" layoutY="214.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0°" textAlignment="RIGHT">
|
<Text fx:id="windDirectionText" fill="#d3d3d3" layoutX="171.0" layoutY="238.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0°" textAlignment="RIGHT">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="13.0" />
|
<Font name="System Bold" size="13.0" />
|
||||||
</font>
|
</font>
|
||||||
</Text>
|
</Text>
|
||||||
<Text fx:id="windSpeedText" fill="#d3d3d3" layoutX="12.0" layoutY="213.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0 Knot" textAlignment="RIGHT">
|
<Text fx:id="windSpeedText" fill="#d3d3d3" layoutX="12.0" layoutY="237.0" strokeType="OUTSIDE" strokeWidth="0.0" text="0.0 Knot" textAlignment="RIGHT">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="13.0" />
|
<Font name="System Bold" size="13.0" />
|
||||||
</font>
|
</font>
|
||||||
</Text>
|
</Text>
|
||||||
<CheckBox fx:id="toggleFps" focusTraversable="false" graphicTextGap="0.0" layoutX="21.0" layoutY="453.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="143.0" selected="true" styleClass="ui-checkbox" text="Show FPS" textFill="WHITE" />
|
<CheckBox fx:id="toggleFps" focusTraversable="false" graphicTextGap="0.0" layoutX="21.0" layoutY="453.0" mnemonicParsing="false" prefHeight="18.0" prefWidth="143.0" selected="true" styleClass="ui-checkbox" text="Show FPS" textFill="WHITE" />
|
||||||
<VBox fx:id="positionVbox" layoutX="12.0" layoutY="280.0" prefHeight="140.0" prefWidth="200.0" styleClass="text-white" />
|
<VBox fx:id="positionVbox" layoutX="12.0" layoutY="304.0" prefHeight="116.0" prefWidth="200.0" styleClass="text-white" />
|
||||||
<Pane layoutX="11.0" layoutY="30.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="193.0">
|
<Pane layoutX="11.0" layoutY="39.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="51.0" prefWidth="193.0">
|
||||||
<children>
|
<children>
|
||||||
<Text fx:id="timerLabel" fill="#f8f8f8" layoutX="-26.0" layoutY="34.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="246.0">
|
<Text fx:id="timerLabel" fill="#f8f8f8" layoutX="-26.0" layoutY="51.0" strokeType="OUTSIDE" strokeWidth="0.0" text="00:00" textAlignment="CENTER" wrappingWidth="246.0">
|
||||||
<font>
|
<font>
|
||||||
<Font size="25.0" />
|
<Font size="25.0" />
|
||||||
</font>
|
</font>
|
||||||
|
|||||||
@@ -24,4 +24,5 @@ public class YachtTest {
|
|||||||
yachts.add(new Yacht("Yacht 3", "Y3", new GeoPoint(-35.0, -15.5), 20.0));
|
yachts.add(new Yacht("Yacht 3", "Y3", new GeoPoint(-35.0, -15.5), 20.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user