mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Fixed connecting to hosts. Fixed issue34 and 35 to the point where they can be developed off of.
#refactor #bug #issue[34, 35]
This commit is contained in:
@@ -9,7 +9,7 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import seng302.model.Player;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.gameServer.server.messages.BoatActionType;
|
||||
|
||||
/**
|
||||
* A Static class to hold information about the current state of the game (model)
|
||||
|
||||
@@ -5,8 +5,8 @@ import java.util.Stack;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import seng302.model.Player;
|
||||
import seng302.server.messages.Heartbeat;
|
||||
import seng302.server.messages.Message;
|
||||
import seng302.gameServer.server.messages.Heartbeat;
|
||||
import seng302.gameServer.server.messages.Message;
|
||||
|
||||
/**
|
||||
* Send Heartbeat messages to connected player at a specified interval
|
||||
|
||||
@@ -2,7 +2,7 @@ package seng302.gameServer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.gameServer.server.messages.BoatActionType;
|
||||
|
||||
|
||||
public class ServerPacketParser {
|
||||
|
||||
@@ -25,16 +25,16 @@ import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.model.stream.xml.generator.Race;
|
||||
import seng302.model.stream.xml.generator.Regatta;
|
||||
import seng302.utilities.XMLGenerator;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.server.messages.BoatLocationMessage;
|
||||
import seng302.server.messages.BoatStatus;
|
||||
import seng302.server.messages.BoatSubMessage;
|
||||
import seng302.server.messages.Message;
|
||||
import seng302.server.messages.RaceStatus;
|
||||
import seng302.server.messages.RaceStatusMessage;
|
||||
import seng302.server.messages.RaceType;
|
||||
import seng302.server.messages.XMLMessage;
|
||||
import seng302.server.messages.XMLMessageSubType;
|
||||
import seng302.gameServer.server.messages.BoatActionType;
|
||||
import seng302.gameServer.server.messages.BoatLocationMessage;
|
||||
import seng302.gameServer.server.messages.BoatStatus;
|
||||
import seng302.gameServer.server.messages.BoatSubMessage;
|
||||
import seng302.gameServer.server.messages.Message;
|
||||
import seng302.gameServer.server.messages.RaceStatus;
|
||||
import seng302.gameServer.server.messages.RaceStatusMessage;
|
||||
import seng302.gameServer.server.messages.RaceType;
|
||||
import seng302.gameServer.server.messages.XMLMessage;
|
||||
import seng302.gameServer.server.messages.XMLMessageSubType;
|
||||
|
||||
/**
|
||||
* A class describing a single connection to a Client for the purposes of sending and receiving on
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 12/07/17.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public class BoatLocationMessage extends Message {
|
||||
private final int MESSAGE_SIZE = 56;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* The current status of a boat
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 20/07/17.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public enum DeviceType {
|
||||
UNKNOWN(0),
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public class Heartbeat extends Message {
|
||||
private final int MESSAGE_SIZE = 4;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public class MarkRoundingMessage extends Message{
|
||||
private final long MESSAGE_VERSION_NUMBER = 1;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Types of marks boats can round
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of messages
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* The types of race start status messages
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public class RaceStartStatusMessage extends Message {
|
||||
private final int MESSAGE_SIZE = 20;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* The current status of the race
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.zip.CRC32;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of races
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* The status of a boat rounding a mark
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* The side the boat rounded the mark
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
public class XMLMessage extends Message{
|
||||
private final MessageType MESSAGE_TYPE = MessageType.XML_MESSAGE;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.messages;
|
||||
package seng302.gameServer.server.messages;
|
||||
|
||||
/**
|
||||
* Enum containing the types of XML messages
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator;
|
||||
package seng302.gameServer.server.simulator;
|
||||
|
||||
import seng302.model.GeoPoint;
|
||||
import seng302.utilities.GeoUtility;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator;
|
||||
package seng302.gameServer.server.simulator;
|
||||
|
||||
import seng302.model.mark.CompoundMark;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator;
|
||||
package seng302.gameServer.server.simulator;
|
||||
|
||||
public enum RoundingType {
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
package seng302.server.simulator;
|
||||
package seng302.gameServer.server.simulator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.server.simulator.parsers.RaceParser;
|
||||
import seng302.gameServer.server.simulator.parsers.RaceParser;
|
||||
import seng302.model.GeoPoint;
|
||||
import seng302.utilities.GeoUtility;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator.parsers;
|
||||
package seng302.gameServer.server.simulator.parsers;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator.parsers;
|
||||
package seng302.gameServer.server.simulator.parsers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -9,9 +9,9 @@ import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import seng302.model.mark.CompoundMark;
|
||||
import seng302.server.simulator.Corner;
|
||||
import seng302.gameServer.server.simulator.Corner;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.server.simulator.RoundingType;
|
||||
import seng302.gameServer.server.simulator.RoundingType;
|
||||
|
||||
/**
|
||||
* Parses the race xml file to get course details
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator.parsers;
|
||||
package seng302.gameServer.server.simulator.parsers;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
package seng302.server.simulator.parsers;
|
||||
package seng302.gameServer.server.simulator.parsers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -6,8 +6,8 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import seng302.server.simulator.Boat;
|
||||
import seng302.server.simulator.Corner;
|
||||
import seng302.gameServer.server.simulator.Boat;
|
||||
import seng302.gameServer.server.simulator.Corner;
|
||||
|
||||
/**
|
||||
* Parses the race xml file to get course details
|
||||
@@ -9,7 +9,7 @@ import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import seng302.model.stream.xml.generator.Race;
|
||||
import seng302.model.stream.xml.generator.Regatta;
|
||||
import seng302.server.messages.XMLMessageSubType;
|
||||
import seng302.gameServer.server.messages.XMLMessageSubType;
|
||||
|
||||
/**
|
||||
* An XML generator to generate the Race, Boat, and Regatta XML dynamically
|
||||
|
||||
@@ -16,8 +16,8 @@ import javafx.application.Platform;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.Message;
|
||||
import seng302.gameServer.server.messages.BoatActionMessage;
|
||||
import seng302.gameServer.server.messages.Message;
|
||||
|
||||
/**
|
||||
* A class describing a single connection to a Server for the purposes of sending and receiving on
|
||||
@@ -130,7 +130,7 @@ public class ClientToServerThread implements Runnable {
|
||||
} else {
|
||||
streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
for (ClientSocketListener csl : listeners)
|
||||
Platform.runLater(csl::newPacket);
|
||||
csl.newPacket();
|
||||
}
|
||||
} else {
|
||||
clientLog("Packet has been dropped", 1);
|
||||
@@ -147,6 +147,7 @@ public class ClientToServerThread implements Runnable {
|
||||
clientLog(e.getMessage(), 1);
|
||||
return;
|
||||
}
|
||||
// System.out.println("streamPackets = " + streamPackets.size());
|
||||
}
|
||||
closeSocket();
|
||||
clientLog("Closed connection to Server", 0);
|
||||
|
||||
@@ -5,13 +5,13 @@ import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.Pane;
|
||||
import seng302.gameServer.GameState;
|
||||
import seng302.gameServer.MainServerThread;
|
||||
import seng302.model.RaceState;
|
||||
import seng302.model.Yacht;
|
||||
@@ -22,8 +22,8 @@ import seng302.model.stream.parser.PositionUpdateData.DeviceType;
|
||||
import seng302.model.stream.parser.RaceStatusData;
|
||||
import seng302.model.stream.xml.parser.RaceXMLData;
|
||||
import seng302.model.stream.xml.parser.RegattaXMLData;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.gameServer.server.messages.BoatActionMessage;
|
||||
import seng302.gameServer.server.messages.BoatActionType;
|
||||
import seng302.utilities.StreamParser;
|
||||
import seng302.utilities.XMLParser;
|
||||
import seng302.visualiser.controllers.LobbyController;
|
||||
@@ -62,12 +62,12 @@ public class GameClient {
|
||||
ioe.printStackTrace();
|
||||
System.out.println("Unable to connect to host...");
|
||||
}
|
||||
LobbyController lobbyController = loadLobby("/views/LobbyView.fxml");
|
||||
socketThread.addStreamObserver(this::parsePackets);
|
||||
LobbyController lobbyController = loadLobby();
|
||||
lobbyController.setPlayerListSource(clientLobbyList);
|
||||
lobbyController.disableReadyButton();
|
||||
lobbyController.setTitle("Connected to host - IP : " + ipAddress + " Port : " + portNumber);
|
||||
lobbyController.addCloseListener((exitCause) -> this.loadStartScreen());
|
||||
socketThread.addStreamObserver(this::parsePackets);
|
||||
}
|
||||
|
||||
public void runAsHost(String ipAddress, Integer portNumber) {
|
||||
@@ -79,8 +79,8 @@ public class GameClient {
|
||||
System.out.println("Unable to make local connection to host...");
|
||||
}
|
||||
socketThread.addStreamObserver(this::parsePackets);
|
||||
LobbyController lobbyController = loadLobby("/views/LobbyView.fxml");
|
||||
lobbyController.setPlayerListSource(GameState.getObservablePlayers());
|
||||
LobbyController lobbyController = loadLobby();
|
||||
lobbyController.setPlayerListSource(clientLobbyList);
|
||||
lobbyController.setTitle("Hosting Lobby - IP : " + ipAddress + " Port : " + portNumber);
|
||||
lobbyController.addCloseListener(exitCause -> {
|
||||
if (exitCause == CloseStatus.READY) {
|
||||
@@ -112,11 +112,10 @@ public class GameClient {
|
||||
/**
|
||||
* Loads a view of the lobby into the clients pane
|
||||
*
|
||||
* @param lobbyView fxml file for the desired lobby
|
||||
* @return the lobby controller.
|
||||
*/
|
||||
private LobbyController loadLobby(String lobbyView) {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(GameClient.class.getResource(lobbyView));
|
||||
private LobbyController loadLobby() {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(GameClient.class.getResource("/views/LobbyView.fxml"));
|
||||
try {
|
||||
holderPane.getChildren().clear();
|
||||
holderPane.getChildren().add(fxmlLoader.load());
|
||||
@@ -130,9 +129,11 @@ public class GameClient {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(
|
||||
RaceViewController.class.getResource("/views/RaceView.fxml"));
|
||||
try {
|
||||
Node node = fxmlLoader.load();
|
||||
holderPane.getChildren().clear();
|
||||
holderPane.getChildren().add(node);
|
||||
final Node node = fxmlLoader.load();
|
||||
Platform.runLater(() -> {
|
||||
holderPane.getChildren().clear();
|
||||
holderPane.getChildren().add(node);
|
||||
});
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -173,13 +174,14 @@ public class GameClient {
|
||||
break;
|
||||
|
||||
case BOAT_XML:
|
||||
System.out.println("GOT SUM BOATS YAY :)");
|
||||
allBoatsMap = XMLParser.parseBoats(
|
||||
StreamParser.extractXmlMessage(packet)
|
||||
);
|
||||
clientLobbyList.clear();
|
||||
allBoatsMap.forEach((id, boat) -> {
|
||||
clientLobbyList.add(id + " " + boat.getBoatName());
|
||||
System.out.println(id + " " + boat.getBoatName());
|
||||
// System.out.println(id + " " + boat.getBoatName());
|
||||
|
||||
});
|
||||
// startRaceIfAllDataReceived();
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
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.collections.ObservableList;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Group;
|
||||
@@ -70,12 +72,13 @@ public class GameView extends Pane {
|
||||
private ImageView mapImage = new ImageView();
|
||||
|
||||
//FRAME RATE
|
||||
private Double frameRate = 60.0;
|
||||
private final long[] frameTimes = new long[30];
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
|
||||
private AnimationTimer timer;
|
||||
private int NUM_SAMPLES = 10;
|
||||
private final long[] frameTimes = new long[NUM_SAMPLES];
|
||||
private Double frameRate = 60.0;
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
|
||||
private enum ScaleDirection {
|
||||
HORIZONTAL,
|
||||
@@ -98,9 +101,14 @@ public class GameView extends Pane {
|
||||
}
|
||||
|
||||
private void initializeTimer () {
|
||||
Arrays.fill(frameTimes, 1_000_000_000 / 60);
|
||||
timer = new AnimationTimer() {
|
||||
private long lastTime = 0;
|
||||
private int FPSCount = 30;
|
||||
private Double frameRate = 60.0;
|
||||
private int index = 0;
|
||||
private boolean arrayFilled = false;
|
||||
private long sum = 1_000_000_000 / 3;
|
||||
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
@@ -121,13 +129,15 @@ public class GameView extends Pane {
|
||||
frameRate = 1_000_000_000.0 / elapsedNanosPerFrame;
|
||||
if (FPSCount-- == 0) {
|
||||
FPSCount = 30;
|
||||
drawFps(frameRate.intValue());
|
||||
drawFps(frameRate);
|
||||
}
|
||||
}
|
||||
boatObjects.forEach((boat, boatObject) -> boatObject.updateLocation());
|
||||
lastTime = now;
|
||||
}
|
||||
}
|
||||
// Platform.runLater(() ->
|
||||
// boatObjects.forEach((boat, boatObject) -> boatObject.updateLocation())
|
||||
// );
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -175,10 +185,9 @@ public class GameView extends Pane {
|
||||
*/
|
||||
public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) {
|
||||
markerObjects = new HashMap<>();
|
||||
final List<Gate> gates = new ArrayList<>();
|
||||
Paint colour = Color.BLACK;
|
||||
markers.getChildren().clear();
|
||||
//Creates new markers
|
||||
System.out.println(newCourse.size());
|
||||
for (CompoundMark cMark : newCourse) {
|
||||
//Set start and end colour
|
||||
if (cMark.getId() == sequence.get(0).getCompoundMarkID()) {
|
||||
@@ -189,26 +198,24 @@ public class GameView extends Pane {
|
||||
//Create mark dots
|
||||
for (Mark mark : cMark.getMarks()) {
|
||||
makeAndBindMarker(mark, colour);
|
||||
System.out.println("hi" + mark.getName());
|
||||
}
|
||||
//Create gate line
|
||||
if (cMark.isGate()) {
|
||||
for (int i = 1; i < cMark.getMarks().size(); i++) {
|
||||
makeAndBindGate(
|
||||
markerObjects.get(cMark.getSubMark(i)),
|
||||
markerObjects.get(cMark.getSubMark(i+1)),
|
||||
colour
|
||||
gates.add(
|
||||
makeAndBindGate(
|
||||
markerObjects.get(cMark.getSubMark(i)),
|
||||
markerObjects.get(cMark.getSubMark(i+1)),
|
||||
colour
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
colour = Color.BLACK;
|
||||
System.out.println("cMark.toString() = " + cMark.toString());
|
||||
}
|
||||
//Set X,Y co-ordinates
|
||||
//Scale race to markers if there is no border.
|
||||
if (borderPoints == null) {
|
||||
rescaleRace(new ArrayList<>(markerObjects.keySet()));
|
||||
} else {
|
||||
rescaleRace(new ArrayList<>(borderPoints));
|
||||
}
|
||||
//Move the Markers to initial position.
|
||||
markerObjects.forEach(((mark, marker) -> {
|
||||
@@ -216,7 +223,11 @@ public class GameView extends Pane {
|
||||
marker.setCenterX(p2d.getX());
|
||||
marker.setCenterY(p2d.getY());
|
||||
}));
|
||||
markers.getChildren().addAll(markerObjects.values());
|
||||
Platform.runLater(() -> {
|
||||
markers.getChildren().clear();
|
||||
markers.getChildren().addAll(gates);
|
||||
markers.getChildren().addAll(markerObjects.values());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,8 +252,9 @@ public class GameView extends Pane {
|
||||
* @param m1 The first Mark of the gate.
|
||||
* @param m2 The second Mark of the gate.
|
||||
* @param colour The desired colour of the gate.
|
||||
* @return the new gate.
|
||||
*/
|
||||
private void makeAndBindGate(Marker m1, Marker m2, Paint colour) {
|
||||
private Gate makeAndBindGate(Marker m1, Marker m2, Paint colour) {
|
||||
Gate gate = new Gate(colour);
|
||||
gate.startXProperty().bind(
|
||||
m1.centerXProperty()
|
||||
@@ -256,7 +268,7 @@ public class GameView extends Pane {
|
||||
gate.endYProperty().bind(
|
||||
m2.centerYProperty()
|
||||
);
|
||||
markers.getChildren().addAll(gate);
|
||||
return gate;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,20 +309,22 @@ public class GameView extends Pane {
|
||||
*/
|
||||
public void setBoats(List<Yacht> yachts) {
|
||||
BoatObject newBoat;
|
||||
final List<Group> wakes = new ArrayList<>();
|
||||
for (Yacht yacht : yachts) {
|
||||
Paint colour = Colors.getColor();
|
||||
newBoat = new BoatObject();
|
||||
newBoat.setFill(colour);
|
||||
boatObjects.put(yacht, newBoat);
|
||||
createAndBindAnnotationBox(yacht, colour);
|
||||
wakesGroup.getChildren().add(newBoat.getWake());
|
||||
// wakesGroup.getChildren().add(newBoat.getWake());
|
||||
wakes.add(newBoat.getWake());
|
||||
boatObjectGroup.getChildren().add(newBoat);
|
||||
trails.getChildren().add(newBoat.getTrail());
|
||||
// TODO: 1/08/17 Make this less vile to look at.
|
||||
yacht.addLocationListener((boat, lat, lon, heading, velocity) ->{
|
||||
BoatObject bo = boatObjects.get(boat);
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
bo.moveTo(p2d.getX(), p2d.getY(), heading);
|
||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity);
|
||||
// annotations.get(boat).setLayoutX(p2d.getX());
|
||||
// annotations.get(boat).setLayoutY(p2d.getY());
|
||||
// annotations.get(boat).setLocation(100d, 100d);
|
||||
@@ -323,24 +337,14 @@ public class GameView extends Pane {
|
||||
});
|
||||
}
|
||||
annotationsGroup.getChildren().addAll(annotations.values());
|
||||
gameObjects.addAll(trails);
|
||||
gameObjects.add(wakesGroup);
|
||||
gameObjects.addAll(annotationsGroup);
|
||||
gameObjects.addAll(boatObjectGroup);
|
||||
Platform.runLater(() -> {
|
||||
gameObjects.addAll(trails);
|
||||
gameObjects.addAll(wakes);
|
||||
gameObjects.addAll(annotationsGroup);
|
||||
gameObjects.addAll(boatObjectGroup);
|
||||
});
|
||||
}
|
||||
|
||||
// private void updateBoatObject (Yacht correspondingYacht) {
|
||||
// BoatObject bo = boatObjects.get(correspondingYacht);
|
||||
// Point2D p2d = findScaledXY(lat, lon);
|
||||
// bo.moveTo(p2d.getX(), p2d.getY(), heading);
|
||||
// annotations.get(boat).moveTo(p2d.getX(), p2d.getY());
|
||||
// bo.setTrajectory(
|
||||
// heading,
|
||||
// velocity,
|
||||
// metersPerPixelX,
|
||||
// metersPerPixelY);
|
||||
// }
|
||||
|
||||
private void createAndBindAnnotationBox (Yacht yacht, Paint colour) {
|
||||
AnnotationBox newAnnotation = new AnnotationBox();
|
||||
newAnnotation.setFill(colour);
|
||||
@@ -371,8 +375,8 @@ public class GameView extends Pane {
|
||||
annotations.put(yacht, newAnnotation);
|
||||
}
|
||||
|
||||
private void drawFps(int fps){
|
||||
fpsDisplay.setText(String.format("%d FPS", fps));
|
||||
private void drawFps(Double fps){
|
||||
Platform.runLater(() -> fpsDisplay.setText(String.format("%d FPS", Math.round(fps))));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,9 +387,6 @@ public class GameView extends Pane {
|
||||
private void findMinMaxPoint(List<GeoPoint> points) {
|
||||
List<GeoPoint> sortedPoints = new ArrayList<>(points);
|
||||
sortedPoints.sort(Comparator.comparingDouble(GeoPoint::getLat));
|
||||
for (GeoPoint gp : sortedPoints) {
|
||||
System.out.println(gp.getLat());
|
||||
}
|
||||
minLatPoint = new GeoPoint(sortedPoints.get(0).getLat(), sortedPoints.get(0).getLng());
|
||||
GeoPoint maxLat = sortedPoints.get(sortedPoints.size()-1);
|
||||
maxLatPoint = new GeoPoint(maxLat.getLat(), maxLat.getLng());
|
||||
@@ -572,5 +573,11 @@ public class GameView extends Pane {
|
||||
playerYacht.getVelocityProperty(),
|
||||
(velocity) -> String.format("Speed: %.2f ms", velocity.doubleValue())
|
||||
);
|
||||
Platform.runLater(() -> {
|
||||
boatObjectGroup.getChildren().remove(boatObjects.get(playerYacht));
|
||||
gameObjects.add(boatObjects.get(playerYacht));
|
||||
annotationsGroup.getChildren().remove(annotations.get(playerYacht));
|
||||
gameObjects.add(annotations.get(playerYacht));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package seng302.visualiser.controllers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
@@ -187,13 +188,12 @@ public class LobbyController {
|
||||
lobbyListeners.add(listener);
|
||||
}
|
||||
|
||||
// TODO: 1/08/17 could definitely do this in a cleaner way.
|
||||
public void setPlayerListSource (ObservableList<String> players) {
|
||||
this.players = players;
|
||||
players.addListener((ListChangeListener<? super String>) (lcl) ->
|
||||
initialiseListView()
|
||||
Platform.runLater(this::initialiseListView)
|
||||
);
|
||||
initialiseListView();
|
||||
Platform.runLater(this::initialiseListView);
|
||||
}
|
||||
|
||||
public void disableReadyButton () {
|
||||
|
||||
@@ -3,14 +3,14 @@ package seng302.visualiser.controllers;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Point2D;
|
||||
@@ -33,7 +33,6 @@ import javafx.scene.shape.Line;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
import seng302.model.RaceState;
|
||||
import seng302.model.Yacht;
|
||||
@@ -81,7 +80,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
private RaceState raceState;
|
||||
|
||||
private Timeline timerTimeline;
|
||||
private HashMap<Integer, Series<String, Double>> sparkLineData = new HashMap<>();
|
||||
private Timer timer = new Timer();
|
||||
private List<Series<String, Double>> sparkLineData = new ArrayList<>();
|
||||
private ImportantAnnotationsState importantAnnotations;
|
||||
|
||||
public void initialize() {
|
||||
@@ -112,9 +112,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
initialiseFPSCheckBox();
|
||||
initialiseAnnotationSlider();
|
||||
initialiseBoatSelectionComboBox();
|
||||
initialiseSparkLine();
|
||||
|
||||
gameView = new GameView();
|
||||
contentAnchorPane.getChildren().add(gameView);
|
||||
Platform.runLater(() -> contentAnchorPane.getChildren().add(gameView));
|
||||
gameView.setBoats(new ArrayList<>(participants.values()));
|
||||
gameView.updateBorder(raceData.getCourseLimit());
|
||||
gameView.updateCourse(
|
||||
@@ -210,32 +211,28 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
* Used to add any new yachts into the race that may have started late or not have had data received yet
|
||||
*/
|
||||
private void updateSparkLine(){
|
||||
// TODO: 2/08/17 there is about 0 chance of this working. Once we are keeping track of boat positions it can be fixed.
|
||||
// Collect the racing yachts that aren't already in the chart
|
||||
List<Yacht> sparkLineCandidates = new ArrayList<>();
|
||||
// participants.forEach((id, yacht) ->{
|
||||
// if (!sparkLineData.containsKey(id) && yacht.getPosition() != null && !yacht.getPosition().equals("-"))
|
||||
// sparkLineCandidates.add(yacht);
|
||||
// });
|
||||
participants.forEach((id, yacht) -> sparkLineCandidates.add(yacht));
|
||||
|
||||
sparklineYAxis.setUpperBound(participants.size() + 1);
|
||||
|
||||
sparkLineData.clear();
|
||||
List<Yacht> sparkLineCandidates = new ArrayList<>(participants.values());
|
||||
// Create a new data series for new yachts
|
||||
sparkLineCandidates.stream().filter(yacht -> yacht.getPositionInteger() != null).forEach(yacht -> {
|
||||
Series<String, Double> yachtData = new Series<>();
|
||||
yachtData.setName(yacht.getSourceId().toString());
|
||||
yachtData.getData().add(
|
||||
new XYChart.Data<>(
|
||||
Integer.toString(yacht.getLegNumber()),
|
||||
1.0 + participants.size() - yacht.getPositionInteger()
|
||||
)
|
||||
);
|
||||
sparkLineData.put(yacht.getSourceId(), yachtData);
|
||||
});
|
||||
sparkLineCandidates
|
||||
.stream()
|
||||
.filter(yacht -> yacht.getPositionInteger() != null)
|
||||
.forEach(yacht -> {
|
||||
Series<String, Double> yachtData = new Series<>();
|
||||
yachtData.setName(yacht.getSourceId().toString());
|
||||
yachtData.getData().add(
|
||||
new XYChart.Data<>(
|
||||
Integer.toString(yacht.getLegNumber()),
|
||||
1.0 + participants.size() - yacht.getPositionInteger()
|
||||
)
|
||||
);
|
||||
sparkLineData.add(yachtData);
|
||||
});
|
||||
|
||||
// Lambda function to sort the series in order of leg (later legs shown more to the right)
|
||||
List<XYChart.Series<String, Double>> positions = new ArrayList<>(sparkLineData.values());
|
||||
positions.sort((o1, o2) -> {
|
||||
sparkLineData.sort((o1, o2) -> {
|
||||
Integer leg1 = Integer.parseInt(o1.getData().get(o1.getData().size()-1).getXValue());
|
||||
Integer leg2 = Integer.parseInt(o2.getData().get(o2.getData().size()-1).getXValue());
|
||||
if (leg2 < leg1){
|
||||
@@ -244,26 +241,30 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
return -1;
|
||||
}
|
||||
});
|
||||
|
||||
// Adds the new data series to the sparkline (and set the colour of the series)
|
||||
raceSparkLine.setCreateSymbols(false);
|
||||
positions
|
||||
.stream()
|
||||
.filter(spark -> !raceSparkLine.getData().contains(spark))
|
||||
.forEach(spark -> {
|
||||
raceSparkLine.getData().add(spark);
|
||||
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
|
||||
});
|
||||
Platform.runLater(() -> {
|
||||
sparkLineData
|
||||
.stream()
|
||||
.filter(spark -> !raceSparkLine.getData().contains(spark))
|
||||
.forEach(spark -> {
|
||||
raceSparkLine.getData().add(spark);
|
||||
spark.getNode().lookup(".chart-series-line").setStyle("-fx-stroke:" + getBoatColorAsRGB(spark.getName()));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void initialiseSparkLine() {
|
||||
sparklineYAxis.setUpperBound(participants.size() + 1);
|
||||
raceSparkLine.setCreateSymbols(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the yachts sparkline of the desired yacht and using the new leg number
|
||||
* @param yacht The yacht to be updated on the sparkline
|
||||
* @param legNumber the leg number that the position will be assigned to
|
||||
*/
|
||||
public void updateYachtPositionSparkline(Yacht yacht, Integer legNumber){
|
||||
for (XYChart.Series<String, Double> positionData : sparkLineData.values()) {
|
||||
void updateYachtPositionSparkline(Yacht yacht, Integer legNumber){
|
||||
for (XYChart.Series<String, Double> positionData : sparkLineData) {
|
||||
positionData.getData().add(
|
||||
new Data<>(
|
||||
Integer.toString(legNumber),
|
||||
@@ -305,24 +306,17 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
* Updates of each of these attributes are called ONCE EACH SECOND
|
||||
*/
|
||||
private void initializeUpdateTimer() {
|
||||
timerTimeline = new Timeline();
|
||||
timerTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||
// Run timer update every second
|
||||
timerTimeline.getKeyFrames().add(
|
||||
new KeyFrame(Duration.seconds(1),
|
||||
event -> {
|
||||
updateRaceTime();
|
||||
updateWindDirection();
|
||||
updateOrder();
|
||||
updateBoatSelectionComboBox();
|
||||
updateSparkLine();
|
||||
})
|
||||
);
|
||||
// Start the timer
|
||||
timerTimeline.playFromStart();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateRaceTime();
|
||||
updateWindDirection();
|
||||
updateOrder();
|
||||
updateSparkLine();
|
||||
}
|
||||
}, 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
|
||||
@@ -331,6 +325,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
* @return The next Mark or null if none found
|
||||
*/
|
||||
private Mark getNextMark(BoatObject bg) {
|
||||
// TODO: 1/08/17 Move to GameView
|
||||
//
|
||||
// Integer legNumber = bg.getYacht().getLegNumber();
|
||||
// List<Corner> markSequence = courseData.getMarkSequence();
|
||||
@@ -346,6 +341,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
// return courseData.getCompoundMarks().get(corner.getCompoundMarkID());
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -376,13 +372,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
* section
|
||||
*/
|
||||
private void updateOrder() {
|
||||
positionVbox.getChildren().clear();
|
||||
// positionVbox.getChildren().removeAll();
|
||||
// positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||
|
||||
// list of racing yacht id
|
||||
List<Yacht> sorted = new ArrayList<>(participants.values());
|
||||
sorted.sort(Comparator.comparingInt(Yacht::getPositionInteger));
|
||||
List<Text> vboxEntries = new ArrayList<>();
|
||||
|
||||
for (Yacht yacht : sorted) {
|
||||
// System.out.println("yacht == null " + String.valueOf(yacht == null));
|
||||
@@ -390,17 +386,20 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
Text textToAdd = new Text(yacht.getPositionInteger() + ". " +
|
||||
yacht.getShortName() + " (Finished)");
|
||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||
positionVbox.getChildren().add(textToAdd);
|
||||
vboxEntries.add(textToAdd);
|
||||
|
||||
} else {
|
||||
Text textToAdd = new Text(yacht.getPositionInteger() + ". " +
|
||||
yacht.getShortName() + " ");
|
||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||
textToAdd.setStyle("");
|
||||
positionVbox.getChildren().add(textToAdd);
|
||||
vboxEntries.add(textToAdd);
|
||||
}
|
||||
// System.out.println("finished a loop :))))))))))))");
|
||||
}
|
||||
Platform.runLater(() ->
|
||||
positionVbox.getChildren().setAll(vboxEntries)
|
||||
);
|
||||
// participants.forEach((id, yacht) ->{
|
||||
// Text textToAdd = new Text(yacht.getPosition() + ". " +
|
||||
// yacht.getShortName() + " ");
|
||||
@@ -411,7 +410,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
}
|
||||
|
||||
|
||||
// private void updateLaylines(BoatObject bg) {
|
||||
private void updateLaylines(BoatObject bg) {
|
||||
// TODO: 1/08/17 move to GameView
|
||||
//
|
||||
// Mark nextMark = getNextMark(bg);
|
||||
// Boolean isUpwind = null;
|
||||
@@ -472,7 +472,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
private Point2D getPointRotation(Point2D ref, Double distance, Double angle){
|
||||
@@ -517,17 +517,6 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the yachts currently in the race as from the StreamParser and sets them to be selectable
|
||||
* in the yacht selection combo box
|
||||
*/
|
||||
private void updateBoatSelectionComboBox() {
|
||||
ObservableList<Yacht> observableYachts = FXCollections.observableArrayList();
|
||||
observableYachts.addAll(participants.values());
|
||||
yachtSelectionComboBox.setItems(observableYachts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display the list of yachts in the order they finished the race
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ package seng302.visualiser.fxObjects;
|
||||
|
||||
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;
|
||||
@@ -13,7 +14,7 @@ import javafx.scene.text.Text;
|
||||
/**
|
||||
* Grouping of string objects over a semi transparent background.
|
||||
*/
|
||||
public class AnnotationBox extends Group{
|
||||
public class AnnotationBox extends Group {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AnnotationFormatter<T> {
|
||||
@@ -41,7 +42,7 @@ public class AnnotationBox extends Group{
|
||||
this.source = source;
|
||||
this.format = formatter;
|
||||
source.addListener((obs, oldVal, newVal) ->
|
||||
text.setText(format.transformString(newVal))
|
||||
Platform.runLater(() -> text.setText(format.transformString(newVal)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -79,6 +80,9 @@ public class AnnotationBox extends Group{
|
||||
|
||||
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);
|
||||
@@ -95,34 +99,51 @@ public class AnnotationBox extends Group{
|
||||
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);
|
||||
this.getChildren().add(annotation.getText());
|
||||
visibleAnnotations++;
|
||||
update();
|
||||
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();
|
||||
annotationsByName.put(annotationName, new Annotation(text, annotationText));
|
||||
this.getChildren().add(text);
|
||||
visibleAnnotations++;
|
||||
update();
|
||||
}
|
||||
|
||||
public <E> void addAnnotation (String annotationName, ObservableValue<E> observable) {
|
||||
addAnnotation(annotationName, observable, E::toString);
|
||||
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();
|
||||
annotationsByName.put(annotationName, new Annotation<>(newText, observable, formatter));
|
||||
this.getChildren().add(newText);
|
||||
visibleAnnotations++;
|
||||
update();
|
||||
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;
|
||||
@@ -138,68 +159,54 @@ public class AnnotationBox extends Group{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
this.getChildren().remove(annotationsByName.remove(annotationName).getText());
|
||||
annotationsByName.remove(annotationName);
|
||||
visibleAnnotations--;
|
||||
update();
|
||||
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) {
|
||||
// double dx = x - this.getLayoutX();
|
||||
// double dy = y - this.getLayoutY();
|
||||
// this.relocate(x, y);
|
||||
//// this.relocate(x, y);
|
||||
// for (Node n : this.getChildren()) {
|
||||
// n.relocate(
|
||||
// n.getLayoutX() + dx,
|
||||
// n.getLayoutY() + dy
|
||||
// );
|
||||
//// n.setLayoutX(n.getLayoutX() + dx);
|
||||
//// n.setLayoutY(n.getLayoutY() + dy);
|
||||
// }
|
||||
// update();
|
||||
this.relocate(x + BACKGROUND_X, y + BACKGROUND_Y);
|
||||
// for (int i = 1; i <= visibleAnnotations; i++) {
|
||||
// Text text = (Text) this.getChildren().get(i);
|
||||
// if (text.visibleProperty().get()) {
|
||||
// text.setLayoutX(x + X_OFFSET_TEXT);
|
||||
// text.setLayoutY(y + Y_OFFSET_TEXT_INIT * Y_OFFSET_PER_TEXT * (i + 1));
|
||||
// }
|
||||
// }
|
||||
// moveTexts(x, y);
|
||||
// for (Node n : this.getChildren()) {
|
||||
// n.relocate(x, 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;
|
||||
background.setWidth(backgroundWidth);
|
||||
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);
|
||||
// System.out.println("visibleAnnotations = " + visibleAnnotations);
|
||||
for (int i = 1; i <= visibleAnnotations; i++) {
|
||||
Text text = (Text) this.getChildren().get(i);
|
||||
if (text.visibleProperty().get()) {
|
||||
// System.out.println("AYY LMAO");
|
||||
// System.out.println("text.getText() = " + text.getText());
|
||||
//// System.out
|
||||
//// .println("text.visibleProperty().get() = " + text.visibleProperty().get());
|
||||
// System.out.println(text.getLayoutX());
|
||||
// System.out.println(background.getLayoutX());
|
||||
text.setX(X_OFFSET_TEXT);
|
||||
text.setY(Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * i);
|
||||
text.setX(X_OFFSET_TEXT);
|
||||
text.setY(Y_OFFSET_TEXT_INIT + Y_OFFSET_PER_TEXT * i);
|
||||
// });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a text object with caching and a color applied
|
||||
*
|
||||
* Returns a text object for an annotation.
|
||||
* @return The text object
|
||||
*/
|
||||
private Text getTextObject() {
|
||||
@@ -211,6 +218,10 @@ public class AnnotationBox extends Group{
|
||||
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);
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.Line;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.shape.Polyline;
|
||||
import javafx.scene.transform.Rotate;
|
||||
|
||||
/**
|
||||
@@ -28,15 +31,16 @@ public class BoatObject extends Group {
|
||||
private double yVelocity;
|
||||
private double lastHeading;
|
||||
//Graphical objects
|
||||
private Group lineGroup = new Group();
|
||||
private Polyline trail = new Polyline();
|
||||
private Polygon boatPoly;
|
||||
private Wake wake;
|
||||
private Line leftLayLine;
|
||||
private Line rightLayline;
|
||||
private Double distanceTravelled = 0.0;
|
||||
private double distanceTravelled, lastRotation;
|
||||
private Point2D lastPoint;
|
||||
private Paint colour = Color.BLACK;
|
||||
private Boolean isSelected = true; //All boats are initialised as selected
|
||||
private Boolean isSelected, destinationSet; //All boats are initialised as selected
|
||||
private boolean isPlayer = false;
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the default triangular boat polygon.
|
||||
@@ -55,7 +59,6 @@ public class BoatObject extends Group {
|
||||
* polygon.
|
||||
*/
|
||||
public BoatObject(double... points) {
|
||||
this.colour = colour;
|
||||
initChildren(points);
|
||||
}
|
||||
|
||||
@@ -66,7 +69,6 @@ public class BoatObject extends Group {
|
||||
* polygon.
|
||||
*/
|
||||
private void initChildren(double... points) {
|
||||
// this.colour = color;
|
||||
boatPoly = new Polygon(points);
|
||||
boatPoly.setFill(colour);
|
||||
boatPoly.setFill(this.colour);
|
||||
@@ -88,44 +90,54 @@ public class BoatObject extends Group {
|
||||
|
||||
leftLayLine = new Line();
|
||||
rightLayline = new Line();
|
||||
|
||||
trail.getStrokeDashArray().setAll(5d, 10d);
|
||||
trail.setCache(true);
|
||||
wake = new Wake(0, -BOAT_HEIGHT);
|
||||
wake.setVisible(true);
|
||||
super.getChildren().addAll(boatPoly);//, annotationBox);
|
||||
}
|
||||
|
||||
public void setFill (Paint value) {
|
||||
this.colour = value;
|
||||
boatPoly.setFill(colour);
|
||||
trail.setStroke(colour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the boat and its children annotations from its current coordinates by specified
|
||||
* amounts.
|
||||
*
|
||||
* @param dx The amount to move the X coordinate by
|
||||
* @param dy The amount to move the Y coordinate by
|
||||
*/
|
||||
private void moveGroupBy(double dx, double dy) {
|
||||
boatPoly.setLayoutX(boatPoly.getLayoutX() + dx);
|
||||
boatPoly.setLayoutY(boatPoly.getLayoutY() + dy);
|
||||
wake.setLayoutX(wake.getLayoutX() + dx);
|
||||
wake.setLayoutY(wake.getLayoutY() + dy);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the boat and its children annotations to coordinates specified
|
||||
*
|
||||
* @param x The X coordinate to move the boat to
|
||||
* @param y The Y coordinate to move the boat to
|
||||
*/
|
||||
public void moveTo(double x, double y, double rotation) {
|
||||
rotateTo(rotation);
|
||||
boatPoly.setLayoutX(x);
|
||||
boatPoly.setLayoutY(y);
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
wake.rotate(rotation);
|
||||
public void moveTo(double x, double y, double rotation, double velocity) {
|
||||
Double dx = Math.abs(boatPoly.getLayoutX() - x);
|
||||
Double dy = Math.abs(boatPoly.getLayoutY() - y);
|
||||
Platform.runLater(() -> {
|
||||
rotateTo(rotation);
|
||||
boatPoly.setLayoutX(x);
|
||||
boatPoly.setLayoutY(y);
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
});
|
||||
wake.setRotation(rotation, velocity);
|
||||
// rotateTo(rotation);
|
||||
// boatPoly.setLayoutX(x);
|
||||
// boatPoly.setLayoutY(y);
|
||||
// wake.setLayoutX(x);
|
||||
// wake.setLayoutY(y);
|
||||
// wake.rotate(rotation);
|
||||
|
||||
// wake.setRotation(rotation, groundSpeed);
|
||||
// isStopped = false;
|
||||
// destinationSet = true;
|
||||
lastRotation = rotation;
|
||||
|
||||
distanceTravelled += Math.sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
if (distanceTravelled > 15 && isPlayer) {
|
||||
distanceTravelled = 0d;
|
||||
Platform.runLater(() -> trail.getPoints().addAll(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
private void rotateTo(double rotation) {
|
||||
@@ -133,31 +145,31 @@ public class BoatObject extends Group {
|
||||
}
|
||||
|
||||
public void updateLocation() {
|
||||
double dx = xVelocity / 60;
|
||||
double dy = yVelocity / 60;
|
||||
|
||||
distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
||||
moveGroupBy(dx, dy);
|
||||
|
||||
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(colour);
|
||||
l.setCache(true);
|
||||
l.setCacheHint(CacheHint.SPEED);
|
||||
lineGroup.getChildren().add(l);
|
||||
}
|
||||
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
||||
}
|
||||
wake.updatePosition();
|
||||
// double dx = xVelocity / 60;
|
||||
// double dy = yVelocity / 60;
|
||||
//
|
||||
// distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
||||
// moveGroupBy(dx, dy);
|
||||
//
|
||||
// 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(colour);
|
||||
// l.setCache(true);
|
||||
// l.setCacheHint(CacheHint.SPEED);
|
||||
// lineGroup.getChildren().add(l);
|
||||
// }
|
||||
// lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
||||
// }
|
||||
// wake.updatePosition();
|
||||
}
|
||||
|
||||
// /**
|
||||
@@ -203,16 +215,16 @@ public class BoatObject extends Group {
|
||||
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime,
|
||||
boolean trail, boolean wake) {
|
||||
// boatAnnotations.setVisible(teamName, velocity, estTime, legTime);
|
||||
this.wake.setVisible(wake);
|
||||
this.lineGroup.setVisible(trail);
|
||||
// this.wake.setVisible(wake);
|
||||
this.trail.setVisible(trail);
|
||||
}
|
||||
|
||||
public void setLineGroupVisible(Boolean visible) {
|
||||
lineGroup.setVisible(visible);
|
||||
trail.setVisible(visible);
|
||||
}
|
||||
|
||||
public void setWakeVisible(Boolean visible) {
|
||||
wake.setVisible(visible);
|
||||
// wake.setVisible(visible);
|
||||
}
|
||||
|
||||
public void setLayLinesVisible(Boolean visible) {
|
||||
@@ -236,8 +248,8 @@ public class BoatObject extends Group {
|
||||
return wake;
|
||||
}
|
||||
|
||||
public Group getTrail() {
|
||||
return lineGroup;
|
||||
public Node getTrail() {
|
||||
return trail;
|
||||
}
|
||||
|
||||
public Double getBoatLayoutX() {
|
||||
@@ -260,6 +272,7 @@ public class BoatObject extends Group {
|
||||
);
|
||||
boatPoly.setStroke(Color.BLACK);
|
||||
boatPoly.setStrokeWidth(3);
|
||||
isPlayer = true;
|
||||
}
|
||||
|
||||
public void setTrajectory(double heading, double velocity) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
@@ -41,7 +42,11 @@ public class Wake extends Group {
|
||||
arc.setCache(true);
|
||||
arc.setCacheHint(CacheHint.ROTATE);
|
||||
arc.setType(ArcType.OPEN);
|
||||
arc.setStroke(new Color(0.18, 0.7, 1.0, 1.0 + (-0.99 / numWakes * i)));
|
||||
arc.setStroke(
|
||||
new Color(
|
||||
0.18, 0.7, 1.0, 1.0 + (-0.99 / numWakes * i)
|
||||
)
|
||||
);
|
||||
arc.setStrokeWidth(3.0);
|
||||
arc.setStrokeLineCap(StrokeLineCap.ROUND);
|
||||
arc.setFill(new Color(0.0, 0.0, 0.0, 0.0));
|
||||
@@ -55,7 +60,15 @@ public class Wake extends Group {
|
||||
|
||||
void setRotation (double rotation, double velocity) {
|
||||
// if (Math.abs(rotations[0] - rotation) > 20) {
|
||||
rotate(rotation);
|
||||
Platform.runLater(() -> {
|
||||
rotate(rotation);
|
||||
double rad = (14 / numWakes) + velocity;
|
||||
for (Arc arc : arcs) {
|
||||
arc.setRadiusX(rad);
|
||||
arc.setRadiusY(rad);
|
||||
rad += (14 / numWakes) + (velocity / 2.5);
|
||||
}
|
||||
});
|
||||
// } else {
|
||||
// rotations[0] = rotation;
|
||||
// ((Rotate) arcs[0].getTransforms().get(0)).setAngle(rotation);
|
||||
@@ -78,12 +91,12 @@ public class Wake extends Group {
|
||||
// }
|
||||
// }
|
||||
|
||||
double rad = (14 / numWakes) + velocity;
|
||||
for (Arc arc : arcs) {
|
||||
arc.setRadiusX(rad);
|
||||
arc.setRadiusY(rad);
|
||||
rad += (14 / numWakes) + (velocity / 2.5);
|
||||
}
|
||||
// double rad = (14 / numWakes) + velocity;
|
||||
// for (Arc arc : arcs) {
|
||||
// arc.setRadiusX(rad);
|
||||
// arc.setRadiusY(rad);
|
||||
// rad += (14 / numWakes) + (velocity / 2.5);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user