mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Changed package heirachy. Merged Controller and StartScreenController.
#refactor
This commit is contained in:
@@ -6,9 +6,9 @@ import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
import seng302.models.PolarTable;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.StreamReceiver;
|
||||
import seng302.model.PolarTable;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.StreamReceiver;
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
@@ -16,11 +16,11 @@ public class App extends Application {
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
PolarTable.parsePolarFile(getClass().getResourceAsStream("/config/acc_polars.csv"));
|
||||
|
||||
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
|
||||
Parent root = FXMLLoader.load(getClass().getResource("/views/StartScreenView.fxml"));
|
||||
primaryStage.setTitle("RaceVision");
|
||||
primaryStage.setScene(new Scene(root, 1530, 960));
|
||||
primaryStage.setMaxWidth(1530);
|
||||
primaryStage.setMaxHeight(960);
|
||||
// primaryStage.setMaxWidth(1530);
|
||||
// primaryStage.setMaxHeight(960);
|
||||
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/PP.png")));
|
||||
// primaryStage.setMaximized(true);
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package seng302.client;
|
||||
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
|
||||
/**
|
||||
* Created by cir27 on 20/07/17.
|
||||
*/
|
||||
public class GameView extends AnchorPane {
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
package seng302.controllers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.client.ClientToServerThread;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
|
||||
public class Controller implements Initializable {
|
||||
|
||||
@FXML
|
||||
private AnchorPane contentPane;
|
||||
private ClientToServerThread clientToServerThread;
|
||||
|
||||
private Object setContentPane(String jfxUrl) {
|
||||
try {
|
||||
contentPane.getChildren().removeAll();
|
||||
contentPane.getChildren().clear();
|
||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||
FXMLLoader fxmlLoader = new FXMLLoader((getClass().getResource(jfxUrl)));
|
||||
Parent view = fxmlLoader.load();
|
||||
contentPane.getChildren().addAll(view);
|
||||
return fxmlLoader.getController();
|
||||
} catch (javafx.fxml.LoadException e) {
|
||||
System.err.println(e.getCause());
|
||||
} catch (IOException e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||
StartScreenController startScreenController = (StartScreenController) setContentPane("/views/StartScreenView.fxml");
|
||||
startScreenController.setController(this);
|
||||
StreamParser.boatLocations.clear();
|
||||
}
|
||||
|
||||
/** Handle the key-pressed event from the text field. */
|
||||
public void keyPressed(KeyEvent e) {
|
||||
BoatActionMessage boatActionMessage;
|
||||
switch (e.getCode()){
|
||||
case SPACE: // align with vmg
|
||||
boatActionMessage = new BoatActionMessage(BoatActionType.VMG);
|
||||
clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
break;
|
||||
case PAGE_UP: // upwind
|
||||
boatActionMessage = new BoatActionMessage(BoatActionType.UPWIND);
|
||||
clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
break;
|
||||
case PAGE_DOWN: // downwind
|
||||
boatActionMessage = new BoatActionMessage(BoatActionType.DOWNWIND);
|
||||
clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
break;
|
||||
case ENTER: // tack/gybe
|
||||
boatActionMessage = new BoatActionMessage(BoatActionType.TACK_GYBE);
|
||||
clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
break;
|
||||
//TODO Allow a zoom in and zoom out methods
|
||||
case Z: // zoom in
|
||||
System.out.println("Zoom in");
|
||||
break;
|
||||
case X: // zoom out
|
||||
System.out.println("Zoom out");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void keyReleased(KeyEvent e) {
|
||||
switch (e.getCode()) {
|
||||
//TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
|
||||
case SHIFT: // sails in/sails out
|
||||
BoatActionMessage boatActionMessage = new BoatActionMessage(BoatActionType.SAILS_IN);
|
||||
clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void setClientToServerThread(ClientToServerThread ctt) {
|
||||
clientToServerThread = ctt;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.models.Player;
|
||||
import seng302.model.Player;
|
||||
|
||||
public interface ClientConnectionDelegate {
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.models.Player;
|
||||
import seng302.model.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.models.Player;
|
||||
import seng302.model.Player;
|
||||
import seng302.server.messages.Heartbeat;
|
||||
import seng302.server.messages.Message;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.models.Player;
|
||||
import seng302.models.stream.PacketBufferDelegate;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.model.Player;
|
||||
import seng302.model.stream.PacketBufferDelegate;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.models.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* A class for a thread to listen to connections
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
import seng302.gameServer.GameState;
|
||||
import seng302.models.Player;
|
||||
import seng302.models.stream.PacketBufferDelegate;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.model.Player;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.Message;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package seng302.models;
|
||||
package seng302.model;
|
||||
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package seng302.models;
|
||||
package seng302.model;
|
||||
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* A Class defining a player and their respective details in the game as held by the model
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models;
|
||||
package seng302.model;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -1,8 +1,8 @@
|
||||
package seng302.models;
|
||||
package seng302.model;
|
||||
|
||||
import javafx.scene.paint.Color;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.controllers.RaceViewController;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.visualiser.controllers.RaceViewController;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.map;
|
||||
package seng302.model.map;
|
||||
|
||||
/**
|
||||
* The Boundary class represents a rectangle territorial boundary on a map. It
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.map;
|
||||
package seng302.model.map;
|
||||
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.image.Image;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.map;
|
||||
package seng302.model.map;
|
||||
|
||||
import javafx.geometry.Point2D;
|
||||
import seng302.utilities.GeoPoint;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.map;
|
||||
package seng302.model.map;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.mark;
|
||||
package seng302.model.mark;
|
||||
|
||||
/**
|
||||
* To represent a gate mark which contains two single marks.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.mark;
|
||||
package seng302.model.mark;
|
||||
|
||||
/**
|
||||
* An abstract class to represent general marks
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.mark;
|
||||
package seng302.model.mark;
|
||||
|
||||
/**
|
||||
* To represent two types of mark
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.mark;
|
||||
package seng302.model.mark;
|
||||
|
||||
/**
|
||||
* Represents the marker as a single mark
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package seng302.models.stream;
|
||||
package seng302.model.stream;
|
||||
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
|
||||
public interface PacketBufferDelegate {
|
||||
boolean addToBuffer(StreamPacket streamPacket);
|
||||
+9
-14
@@ -1,4 +1,4 @@
|
||||
package seng302.models.stream;
|
||||
package seng302.model.stream;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -9,6 +9,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -20,10 +21,10 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.stream.packets.BoatPositionPacket;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.stream.packets.BoatPositionPacket;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
|
||||
/**
|
||||
* The purpose of this class is to take in the stream of divided packets so they can be read
|
||||
@@ -35,8 +36,6 @@ public class StreamParser{
|
||||
|
||||
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> markLocations = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatLocations = new ConcurrentHashMap<>();
|
||||
private String threadName;
|
||||
private Thread t;
|
||||
private static boolean newRaceXmlReceived = false;
|
||||
private static boolean raceStarted = false;
|
||||
private static XMLParser xmlObject;
|
||||
@@ -49,7 +48,6 @@ public class StreamParser{
|
||||
private static Double windSpeed = 0d;
|
||||
private static Long currentTimeLong;
|
||||
private static String currentTimeString;
|
||||
private static boolean appRunning;
|
||||
|
||||
|
||||
//CONVERSION CONSTANTS
|
||||
@@ -436,6 +434,8 @@ public class StreamParser{
|
||||
boats.get((int)subjectId).setLastMarkRounded(mark);
|
||||
}
|
||||
}
|
||||
|
||||
Long[] array = new Long[]{subjectId, timeStamp, (long) markId};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,7 +448,7 @@ public class StreamParser{
|
||||
int messageVersionNo = payload[0];
|
||||
int selectedWindId = payload[1];
|
||||
int loopCount = payload[2];
|
||||
ArrayList<String> windInfo = new ArrayList<>();
|
||||
List<String> windInfo = new ArrayList<>();
|
||||
for (int i = 0; i < loopCount; i++) {
|
||||
String wind = "WindId: " + payload[3 + (20 * i)];
|
||||
wind +=
|
||||
@@ -507,7 +507,6 @@ public class StreamParser{
|
||||
} else if (actionType == 6) {
|
||||
System.out.println("DOWNWIND");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -630,10 +629,6 @@ public class StreamParser{
|
||||
return currentTimeLong;
|
||||
}
|
||||
|
||||
public static void appClose() {
|
||||
appRunning = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to check if a new un-processed xml has been found, if so will return true before
|
||||
* toggling off so that the next check will return false.
|
||||
+2
-10
@@ -1,19 +1,11 @@
|
||||
package seng302.models.stream;
|
||||
package seng302.model.stream;
|
||||
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.server.messages.Heartbeat;
|
||||
import seng302.server.messages.Message;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Comparator;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
|
||||
public class StreamReceiver extends Thread {
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
package seng302.models.stream;
|
||||
package seng302.model.stream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -8,11 +8,11 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.mark.MarkType;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.MarkType;
|
||||
import seng302.model.mark.SingleMark;
|
||||
|
||||
/**
|
||||
* Class to create an XML object from the XML Packet Messages.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.stream.packets;
|
||||
package seng302.model.stream.packets;
|
||||
|
||||
public class BoatPositionPacket {
|
||||
private long boatId;
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
package seng302.models.stream.packets;
|
||||
package seng302.model.stream.packets;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Created by Kusal on 4/24/2017.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.models.stream.packets;
|
||||
package seng302.model.stream.packets;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 23/04/17.
|
||||
+28
-18
@@ -1,23 +1,36 @@
|
||||
package seng302.client;
|
||||
package seng302.visualiser;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.packets.StreamPacket;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser;
|
||||
import seng302.model.stream.packets.BoatPositionPacket;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.server.messages.Message;
|
||||
|
||||
/**
|
||||
* Created by kre39 on 13/07/17.
|
||||
*/
|
||||
public class ClientToServerThread extends Thread {
|
||||
private Queue<StreamPacket> streamPackets = new ConcurrentLinkedQueue<>();
|
||||
private List<ListChangeListener<Queue<StreamPacket>>> boatPacketListeners = new ArrayList<>();
|
||||
|
||||
private Socket socket;
|
||||
private InputStream is;
|
||||
private OutputStream os;
|
||||
@@ -49,17 +62,6 @@ public class ClientToServerThread extends Thread {
|
||||
// TODO: 14/07/17 wmu16 - Work out how to fix this while loop
|
||||
while(true) {
|
||||
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();
|
||||
sync1 = readByte();
|
||||
sync2 = readByte();
|
||||
@@ -76,9 +78,10 @@ public class ClientToServerThread extends Thread {
|
||||
long computedCrc = checksum.getValue();
|
||||
long packetCrc = Message.bytesToLong(getBytes(4));
|
||||
if (computedCrc == packetCrc) {
|
||||
StreamParser.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));
|
||||
streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload));
|
||||
for (ListChangeListener cl : boatPacketListeners) {
|
||||
cl.onChanged();
|
||||
}
|
||||
} else {
|
||||
System.err.println("Packet has been dropped");
|
||||
}
|
||||
@@ -111,6 +114,13 @@ public class ClientToServerThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
public void addStreamObserver (ListChangeListener<Queue<StreamPacket>> listChangeListener) {
|
||||
boatPacketListeners.add(listChangeListener);
|
||||
}
|
||||
|
||||
public void removeStreamObserver (ListChangeListener<Queue<StreamPacket>> listChangeListener) {
|
||||
boatPacketListeners.remove(listChangeListener);
|
||||
}
|
||||
|
||||
private int readByte() throws Exception {
|
||||
int currentByte = -1;
|
||||
+61
-76
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers;
|
||||
package seng302.visualiser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -8,46 +8,40 @@ import java.util.Map;
|
||||
import java.util.concurrent.PriorityBlockingQueue;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.text.Text;
|
||||
import seng302.fxObjects.BoatGroup;
|
||||
import seng302.models.Colors;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.fxObjects.MarkGroup;
|
||||
import seng302.models.mark.MarkType;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.models.map.Boundary;
|
||||
import seng302.models.map.CanvasMap;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.XMLParser;
|
||||
import seng302.models.stream.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.models.stream.packets.BoatPositionPacket;
|
||||
import seng302.visualiser.controllers.RaceViewController;
|
||||
import seng302.visualiser.fxObjects.BoatGroup;
|
||||
import seng302.visualiser.fxObjects.MarkGroup;
|
||||
import seng302.model.Colors;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.map.Boundary;
|
||||
import seng302.model.map.CanvasMap;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.MarkType;
|
||||
import seng302.model.mark.SingleMark;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Limit;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.model.stream.packets.BoatPositionPacket;
|
||||
import seng302.utilities.GeoPoint;
|
||||
import seng302.utilities.GeoUtility;
|
||||
|
||||
/**
|
||||
* Created by ptg19 on 15/03/17.
|
||||
* Modified by Haoming Yin (hyi25) on 20/3/2017.
|
||||
* Created by cir27 on 20/07/17.
|
||||
*/
|
||||
public class GameViewController {
|
||||
|
||||
@FXML
|
||||
private AnchorPane mainPane;
|
||||
|
||||
public class GameView extends Pane {
|
||||
private RaceViewController raceViewController;
|
||||
private ObservableList<Node> gameObjects;
|
||||
private ImageView mapImage;
|
||||
@@ -94,12 +88,12 @@ public class GameViewController {
|
||||
|
||||
public void initialize() {
|
||||
raceViewController = new RaceViewController();
|
||||
gameObjects = mainPane.getChildren();
|
||||
gameObjects = this.getChildren();
|
||||
// create image view for map, bind panel size to image
|
||||
mapImage = new ImageView();
|
||||
mainPane.getChildren().add(mapImage);
|
||||
mapImage.fitWidthProperty().bind(mainPane.widthProperty());
|
||||
mapImage.fitHeightProperty().bind(mainPane.heightProperty());
|
||||
gameObjects.add(mapImage);
|
||||
mapImage.fitWidthProperty().bind(this.widthProperty());
|
||||
mapImage.fitHeightProperty().bind(this.heightProperty());
|
||||
}
|
||||
|
||||
void initializeCanvas() {
|
||||
@@ -113,9 +107,9 @@ public class GameViewController {
|
||||
gameObjects.add(raceBorder);
|
||||
initializeMarks();
|
||||
initializeBoats();
|
||||
mainPane.widthProperty().addListener(resize -> {
|
||||
canvasWidth = mainPane.getWidth();
|
||||
canvasHeight = mainPane.getHeight();
|
||||
this.widthProperty().addListener(resize -> {
|
||||
canvasWidth = this.getWidth();
|
||||
canvasHeight = this.getHeight();
|
||||
fitMarksToCanvas();
|
||||
});
|
||||
|
||||
@@ -125,34 +119,33 @@ public class GameViewController {
|
||||
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
if (lastTime == 0) {
|
||||
lastTime = now;
|
||||
} else {
|
||||
if (now - lastTime >= (1e8 / 60)) { //Fix for framerate going above 60 when minimized
|
||||
long oldFrameTime = frameTimes[frameTimeIndex];
|
||||
frameTimes[frameTimeIndex] = now;
|
||||
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length;
|
||||
if (frameTimeIndex == 0) {
|
||||
arrayFilled = true;
|
||||
}
|
||||
long elapsedNanos;
|
||||
if (arrayFilled) {
|
||||
elapsedNanos = now - oldFrameTime;
|
||||
long elapsedNanosPerFrame = elapsedNanos / frameTimes.length;
|
||||
frameRate = 1_000_000_000.0 / elapsedNanosPerFrame;
|
||||
if (FPSCount-- == 0) {
|
||||
FPSCount = 30;
|
||||
drawFps(frameRate.intValue());
|
||||
}
|
||||
raceViewController.updateSparkLine();
|
||||
}
|
||||
updateGroups();
|
||||
if (StreamParser.isRaceFinished()) {
|
||||
this.stop();
|
||||
}
|
||||
lastTime = now;
|
||||
if (lastTime == 0) {
|
||||
lastTime = now;
|
||||
} else {
|
||||
if (now - lastTime >= (1e8 / 60)) { //Fix for framerate going above 60 when minimized
|
||||
long oldFrameTime = frameTimes[frameTimeIndex];
|
||||
frameTimes[frameTimeIndex] = now;
|
||||
frameTimeIndex = (frameTimeIndex + 1) % frameTimes.length;
|
||||
if (frameTimeIndex == 0) {
|
||||
arrayFilled = true;
|
||||
}
|
||||
long elapsedNanos;
|
||||
if (arrayFilled) {
|
||||
elapsedNanos = now - oldFrameTime;
|
||||
long elapsedNanosPerFrame = elapsedNanos / frameTimes.length;
|
||||
frameRate = 1_000_000_000.0 / elapsedNanosPerFrame;
|
||||
if (FPSCount-- == 0) {
|
||||
FPSCount = 30;
|
||||
// drawFps(frameRate.intValue());
|
||||
}
|
||||
}
|
||||
updateGroups();
|
||||
if (StreamParser.isRaceFinished()) {
|
||||
this.stop();
|
||||
}
|
||||
lastTime = now;
|
||||
}
|
||||
}
|
||||
if (StreamParser.isRaceFinished()) {
|
||||
this.stop();
|
||||
switchToFinishScreen();
|
||||
@@ -164,7 +157,7 @@ public class GameViewController {
|
||||
private void switchToFinishScreen() {
|
||||
try {
|
||||
// canvas view -> anchor pane -> grid pane -> main view
|
||||
GridPane gridPane = (GridPane) mainPane.getParent().getParent();
|
||||
GridPane gridPane = (GridPane) this.getParent().getParent();
|
||||
AnchorPane contentPane = (AnchorPane) gridPane.getParent();
|
||||
contentPane.getChildren().removeAll();
|
||||
contentPane.getChildren().clear();
|
||||
@@ -343,14 +336,14 @@ public class GameViewController {
|
||||
gameObjects.addAll(markGroups);
|
||||
}
|
||||
|
||||
private void drawFps(int fps){
|
||||
if (raceViewController.isDisplayFps()){
|
||||
FPSdisplay.setVisible(true);
|
||||
FPSdisplay.setText(String.format("%d FPS", fps));
|
||||
} else {
|
||||
FPSdisplay.setVisible(false);
|
||||
}
|
||||
}
|
||||
// private void drawFps(int fps){
|
||||
// if (raceViewController.isDisplayFps()){
|
||||
// FPSdisplay.setVisible(true);
|
||||
// FPSdisplay.setText(String.format("%d FPS", fps));
|
||||
// } else {
|
||||
// FPSdisplay.setVisible(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Calculates x and y location for every marker that fits it to the canvas the race will be
|
||||
@@ -519,12 +512,4 @@ public class GameViewController {
|
||||
metersPerPixelY = dVertical / dy;
|
||||
}
|
||||
|
||||
List<BoatGroup> getBoatGroups() {
|
||||
return boatGroups;
|
||||
}
|
||||
|
||||
List<MarkGroup> getMarkGroups() {
|
||||
return markGroups;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers;
|
||||
package seng302.visualiser.controllers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
@@ -15,9 +15,9 @@ import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
|
||||
|
||||
public class FinishScreenViewController implements Initializable {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers;
|
||||
package seng302.visualiser.controllers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
+14
-17
@@ -1,10 +1,9 @@
|
||||
package seng302.controllers;
|
||||
package seng302.visualiser.controllers;
|
||||
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Point2D;
|
||||
@@ -17,7 +16,6 @@ import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.VBox;
|
||||
@@ -29,24 +27,23 @@ import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
import seng302.client.ClientToServerThread;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.controllers.annotations.Annotation;
|
||||
import seng302.controllers.annotations.ImportantAnnotationController;
|
||||
import seng302.controllers.annotations.ImportantAnnotationDelegate;
|
||||
import seng302.controllers.annotations.ImportantAnnotationsState;
|
||||
import seng302.fxObjects.BoatGroup;
|
||||
import seng302.fxObjects.MarkGroup;
|
||||
import seng302.models.*;
|
||||
import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.models.stream.XMLParser;
|
||||
import seng302.visualiser.controllers.annotations.Annotation;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
|
||||
import seng302.visualiser.fxObjects.BoatGroup;
|
||||
import seng302.visualiser.fxObjects.MarkGroup;
|
||||
import seng302.model.*;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.SingleMark;
|
||||
import seng302.model.stream.StreamParser;
|
||||
import seng302.model.stream.XMLParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import seng302.models.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import seng302.model.stream.XMLParser.RaceXMLObject.Participant;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
+2
-12
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers;
|
||||
package seng302.visualiser.controllers;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
@@ -6,7 +6,7 @@ import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import seng302.client.ClientToServerThread;
|
||||
import seng302.visualiser.ClientToServerThread;
|
||||
import seng302.gameServer.GameState;
|
||||
import seng302.gameServer.MainServerThread;
|
||||
|
||||
@@ -25,8 +25,6 @@ public class StartScreenController {
|
||||
@FXML
|
||||
private GridPane startScreen2;
|
||||
|
||||
private Controller controller;
|
||||
|
||||
/**
|
||||
* Loads the fxml content into the parent pane
|
||||
* @param jfxUrl
|
||||
@@ -40,10 +38,7 @@ public class StartScreenController {
|
||||
contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(jfxUrl));
|
||||
contentPane.getChildren().addAll((Pane) fxmlLoader.load());
|
||||
|
||||
return fxmlLoader.getController();
|
||||
} catch (javafx.fxml.LoadException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -80,15 +75,10 @@ public class StartScreenController {
|
||||
String ipAddress = ipTextField.getText().trim().toLowerCase();
|
||||
try {
|
||||
ClientToServerThread clientToServerThread = new ClientToServerThread(ipAddress, 4950);
|
||||
controller.setClientToServerThread(clientToServerThread);
|
||||
clientToServerThread.start();
|
||||
setContentPane("/views/LobbyView.fxml");
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setController(Controller controller) {
|
||||
this.controller = controller;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers.annotations;
|
||||
package seng302.visualiser.controllers.annotations;
|
||||
|
||||
/**
|
||||
* Annotations the user can select as important
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers.annotations;
|
||||
package seng302.visualiser.controllers.annotations;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers.annotations;
|
||||
package seng302.visualiser.controllers.annotations;
|
||||
|
||||
/**
|
||||
* An ImportantAnnotationDelegate handles updating the important annotations
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package seng302.controllers.annotations;
|
||||
package seng302.visualiser.controllers.annotations;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -0,0 +1,120 @@
|
||||
package seng302.visualiser.controllers.client;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import seng302.model.stream.XMLParser;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.server.messages.BoatActionMessage;
|
||||
import seng302.server.messages.BoatActionType;
|
||||
import seng302.visualiser.ClientToServerThread;
|
||||
|
||||
/**
|
||||
* Created by cir27 on 20/07/17.
|
||||
*/
|
||||
public class ClientController {
|
||||
|
||||
Pane holderPane;
|
||||
ClientToServerThread socketThread;
|
||||
|
||||
public ClientController (String ipAddress, Pane holder) {
|
||||
this.holderPane = holder;
|
||||
socketThread = new ClientToServerThread(ipAddress, 4950);
|
||||
socketThread.start();
|
||||
socketThread.waitForXML(event -> storeXMLData());
|
||||
}
|
||||
|
||||
private void parsePacket(StreamPacket packet) {
|
||||
try {
|
||||
switch (packet.getType()) {
|
||||
case HEARTBEAT:
|
||||
extractHeartBeat(packet);
|
||||
break;
|
||||
case RACE_STATUS:
|
||||
extractRaceStatus(packet);
|
||||
break;
|
||||
case DISPLAY_TEXT_MESSAGE:
|
||||
extractDisplayMessage(packet);
|
||||
break;
|
||||
case XML_MESSAGE:
|
||||
newRaceXmlReceived = true;
|
||||
extractXmlMessage(packet);
|
||||
break;
|
||||
case RACE_START_STATUS:
|
||||
extractRaceStartStatus(packet);
|
||||
break;
|
||||
case YACHT_EVENT_CODE:
|
||||
extractYachtEventCode(packet);
|
||||
break;
|
||||
case YACHT_ACTION_CODE:
|
||||
extractYachtActionCode(packet);
|
||||
break;
|
||||
case CHATTER_TEXT:
|
||||
extractChatterText(packet);
|
||||
break;
|
||||
case BOAT_LOCATION:
|
||||
extractBoatLocation(packet);
|
||||
break;
|
||||
case MARK_ROUNDING:
|
||||
extractMarkRounding(packet);
|
||||
break;
|
||||
case COURSE_WIND:
|
||||
extractCourseWind(packet);
|
||||
break;
|
||||
case AVG_WIND:
|
||||
extractAvgWind(packet);
|
||||
break;
|
||||
case BOAT_ACTION:
|
||||
extractBoatAction(packet);
|
||||
break;
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("Error parsing packet");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// /** Handle the key-pressed event from the text field. */
|
||||
// public void keyPressed(KeyEvent e) {
|
||||
// BoatActionMessage boatActionMessage;
|
||||
// switch (e.getCode()){
|
||||
// case SPACE: // align with vmg
|
||||
// boatActionMessage = new BoatActionMessage(BoatActionType.VMG);
|
||||
// clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
// break;
|
||||
// case PAGE_UP: // upwind
|
||||
// boatActionMessage = new BoatActionMessage(BoatActionType.UPWIND);
|
||||
// clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
// break;
|
||||
// case PAGE_DOWN: // downwind
|
||||
// boatActionMessage = new BoatActionMessage(BoatActionType.DOWNWIND);
|
||||
// clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
// break;
|
||||
// case ENTER: // tack/gybe
|
||||
// boatActionMessage = new BoatActionMessage(BoatActionType.TACK_GYBE);
|
||||
// clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
// break;
|
||||
// //TODO Allow a zoom in and zoom out methods
|
||||
// case Z: // zoom in
|
||||
// System.out.println("Zoom in");
|
||||
// break;
|
||||
// case X: // zoom out
|
||||
// System.out.println("Zoom out");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void keyReleased(KeyEvent e) {
|
||||
// switch (e.getCode()) {
|
||||
// //TODO 12/07/17 Determine the sail state and send the appropriate packet (eg. if sails are in, send a sail out packet)
|
||||
// case SHIFT: // sails in/sails out
|
||||
// BoatActionMessage boatActionMessage = new BoatActionMessage(BoatActionType.SAILS_IN);
|
||||
// clientToServerThread.sendBoatActionMessage(boatActionMessage);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// onKeyPressed="#keyPressed" onKeyReleased="#keyReleased"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package seng302.visualiser.controllers.host;
|
||||
|
||||
import javafx.scene.layout.Pane;
|
||||
|
||||
/**
|
||||
* Created by cir27 on 20/07/17.
|
||||
*/
|
||||
public class HostController {
|
||||
Pane mainHolder;
|
||||
public HostController (Pane holder) {
|
||||
this.mainHolder = holder;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
package seng302.fxObjects;
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Rectangle;
|
||||
import javafx.scene.text.Text;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.model.stream.StreamParser;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
package seng302.fxObjects;
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -9,13 +9,13 @@ import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Line;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import seng302.controllers.GameViewController;
|
||||
import seng302.models.Yacht;
|
||||
import seng302.visualiser.controllers.GameViewController;
|
||||
import seng302.model.Yacht;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.models.stream.StreamParser;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.SingleMark;
|
||||
import seng302.model.stream.StreamParser;
|
||||
|
||||
/**
|
||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
package seng302.fxObjects;
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -8,10 +8,10 @@ import javafx.scene.Node;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Line;
|
||||
import seng302.models.mark.GateMark;
|
||||
import seng302.models.mark.Mark;
|
||||
import seng302.models.mark.MarkType;
|
||||
import seng302.models.mark.SingleMark;
|
||||
import seng302.model.mark.GateMark;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.mark.MarkType;
|
||||
import seng302.model.mark.SingleMark;
|
||||
|
||||
/**
|
||||
* Grouping of javaFX objects needed to represent a Mark on screen.
|
||||
+1
-2
@@ -1,4 +1,4 @@
|
||||
package seng302.fxObjects;
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
@@ -7,7 +7,6 @@ import javafx.scene.shape.Arc;
|
||||
import javafx.scene.shape.ArcType;
|
||||
import javafx.scene.shape.StrokeLineCap;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
|
||||
/**
|
||||
* A group containing objects used to represent wakes onscreen. Contains functionality for their animation.
|
||||
Reference in New Issue
Block a user