From eb83e9dcc570718f96c8e2261cd67b1286d4d0fc Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Thu, 3 Aug 2017 14:50:56 +1200 Subject: [PATCH 01/82] Working idle sail animation. Need to work on getting sails to toggle properly. Have the 2 animations almost working but unable to switch between the two. #story[1111] --- .../seng302/controllers/LobbyController.java | 2 + .../java/seng302/fxObjects/BoatGroup.java | 42 ++++++++++++++++++- src/main/java/seng302/models/Yacht.java | 5 ++- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/java/seng302/controllers/LobbyController.java b/src/main/java/seng302/controllers/LobbyController.java index b9d407fe..09425708 100644 --- a/src/main/java/seng302/controllers/LobbyController.java +++ b/src/main/java/seng302/controllers/LobbyController.java @@ -97,7 +97,9 @@ public class LobbyController implements Initializable, Observer{ .addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl))); } catch (javafx.fxml.LoadException e) { System.out.println("[Controller] FXML load exception"); + e.printStackTrace(); } catch (IOException e) { + System.out.println("[Controller] IO exception"); } catch (NullPointerException e) { // System.out.println("[Controller] Null Pointer Exception"); diff --git a/src/main/java/seng302/fxObjects/BoatGroup.java b/src/main/java/seng302/fxObjects/BoatGroup.java index 2446f9d4..efbdb499 100644 --- a/src/main/java/seng302/fxObjects/BoatGroup.java +++ b/src/main/java/seng302/fxObjects/BoatGroup.java @@ -11,6 +11,8 @@ import javafx.scene.shape.Line; import javafx.scene.shape.Polygon; import javafx.scene.transform.Rotate; import seng302.client.ClientPacketParser; +import seng302.gameServer.GameStages; +import seng302.gameServer.GameState; import seng302.models.Yacht; import seng302.utilities.GeoUtility; import seng302.controllers.CanvasController; @@ -43,6 +45,7 @@ public class BoatGroup extends Group { private Group lineGroup = new Group(); private Polygon boatPoly; private Wake wake; + private Polygon sail; private Line leftLayLine; private Line rightLayline; private Double distanceTravelled = 0.0; @@ -52,6 +55,7 @@ public class BoatGroup extends Group { private Color color; private Boolean isSelected = true; //All boats are initialised as selected\ private boolean isPlayer = false; + private Double sailState = 0.0; /** * Creates a BoatGroup with the default triangular boat polygon. @@ -105,14 +109,32 @@ public class BoatGroup extends Group { boatPoly.setCache(true); boatPoly.setCacheHint(CacheHint.SPEED); boatAnnotations = new BoatAnnotations(boat, this.color); - + sail = new Polygon(0.0,BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + animateSail(); + sail.setStrokeWidth(2.0); + sail.setStroke(Color.SILVER); leftLayLine = new Line(); rightLayline = new Line(); wake = new Wake(0, -BOAT_HEIGHT); - super.getChildren().addAll(boatPoly, boatAnnotations); + super.getChildren().addAll(boatPoly, boatAnnotations, sail); } + + private void animateSail(){ + Double[] points = new Double[100]; + for (int i = 0; i < 50; i++) { + points[i * 2] = 5 * Math.sin(((Math.PI * i) / 25 + sailState)); + points[i * 2 + 1] = (BOAT_HEIGHT * i) / 50 + BOAT_HEIGHT / 4; + } + sailState = sailState + Math.PI / 25; + sail.getPoints().clear(); + sail.getPoints().addAll(points); + + } + + /** * Creates the javafx objects that will be the in the group by default. * @@ -154,6 +176,16 @@ public class BoatGroup extends Group { boatPoly.setLayoutY(y); boatAnnotations.setLayoutX(x); boatAnnotations.setLayoutY(y); + sail.setLayoutX(x); + sail.setLayoutY(y); + if (!boat.getSailIn()) { + animateSail(); + } else { + sail.getPoints().clear(); + sail.getPoints().addAll(0.0,BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + + } wake.setLayoutX(x); wake.setLayoutY(y); wake.rotate(rotation); @@ -161,6 +193,12 @@ public class BoatGroup extends Group { private void rotateTo(double rotation) { boatPoly.getTransforms().setAll(new Rotate(rotation)); + //TODO kre39 - Make the sails out angle depend on the facing of the boat + if (!boat.getSailIn()) { + sail.getTransforms().setAll(new Rotate(GameState.getWindDirection() + 95.0)); + } else { + sail.getTransforms().setAll(new Rotate(GameState.getWindDirection())); + } } /** diff --git a/src/main/java/seng302/models/Yacht.java b/src/main/java/seng302/models/Yacht.java index 67ab3373..7738837f 100644 --- a/src/main/java/seng302/models/Yacht.java +++ b/src/main/java/seng302/models/Yacht.java @@ -124,6 +124,7 @@ public class Yacht { Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading); Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle); Double maxBoatSpeed = boatSpeedInKnots / ClientPacketParser.MS_TO_KNOTS * 1000; + System.out.println("sailIn = " + sailIn); if (sailIn && velocity <= maxBoatSpeed && maxBoatSpeed != 0d) { if (velocity < maxBoatSpeed) { @@ -170,7 +171,8 @@ public class Yacht { } public void toggleSailIn() { - sailIn = !sailIn; + this.sailIn = !sailIn; + System.out.println("sailIn = " + sailIn); } public void turnUpwind() { @@ -389,6 +391,7 @@ public class Yacht { } public Boolean getSailIn() { + System.out.println("sailIn = " + sailIn); return sailIn; } From 99d5545ed36b418d6260351e1ea48032a3aad80a Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Thu, 3 Aug 2017 16:33:51 +1200 Subject: [PATCH 02/82] Made the sails work properly by toggling. Need to remove the unneeded code I added. #story[1111] --- src/main/java/seng302/model/Yacht.java | 16 ++++-- .../java/seng302/visualiser/GameClient.java | 1 + .../java/seng302/visualiser/GameView.java | 10 +++- .../controllers/RaceViewController.java | 4 ++ .../visualiser/fxObjects/BoatObject.java | 52 ++++++++++++++++--- 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index aba80d1a..df6c1810 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -23,9 +23,10 @@ import seng302.model.mark.CompoundMark; */ public class Yacht { + @FunctionalInterface public interface YachtLocationListener { - void notifyLocation(Yacht yacht, double lat, double lon, double heading, double velocity); + void notifyLocation(Yacht yacht, double lat, double lon, double heading, double velocity, boolean sailIn); } //BOTH AFAIK @@ -48,7 +49,7 @@ public class Yacht { //SERVER SIDE private final Double TURN_STEP = 5.0; private Double lastHeading; - private Boolean sailIn; + private Boolean sailIn = false; private GeoPoint location; private Integer boatStatus; private Double velocity; @@ -61,6 +62,7 @@ public class Yacht { private CompoundMark lastMarkRounded; private Integer positionInt = 0; private Color colour; + private Boolean clientSailsIn = false; public Yacht(String boatType, Integer sourceId, String hullID, String shortName, String boatName, String country) { @@ -70,7 +72,6 @@ public class Yacht { this.shortName = shortName; this.boatName = boatName; this.country = country; - this.sailIn = false; this.location = new GeoPoint(57.670341, 11.826856); this.heading = 120.0; //In degrees this.velocity = 0d; //in mms-1 @@ -281,6 +282,10 @@ public class Yacht { this.velocityProperty.set(velocity); } + public void updateSailsInProperty(Boolean clientSails) { + this.clientSailsIn = clientSails; + } + public void setMarkRoundingTime(Long markRoundingTime) { this.markRoundTime = markRoundingTime; } @@ -383,6 +388,9 @@ public class Yacht { this.colour = colour; } + public void toggleClientSail() { + clientSailsIn = !clientSailsIn; + } public Double getVelocity() { return velocity; @@ -399,7 +407,7 @@ public class Yacht { this.velocity = velocity; updateVelocityProperty(velocity); for (YachtLocationListener yll : locationListeners) { - yll.notifyLocation(this, lat, lon, heading, velocity); + yll.notifyLocation(this, lat, lon, heading, velocity, this.clientSailsIn); } } diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index 915eef37..35b05615 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -319,6 +319,7 @@ public class GameClient { BoatActionMessage boatActionMessage = new BoatActionMessage( BoatActionType.SAILS_IN); socketThread.sendBoatActionMessage(boatActionMessage); + raceView.getGameView().getPlayerYacht().toggleClientSail(); break; } } diff --git a/src/main/java/seng302/visualiser/GameView.java b/src/main/java/seng302/visualiser/GameView.java index 73d49b89..37507035 100644 --- a/src/main/java/seng302/visualiser/GameView.java +++ b/src/main/java/seng302/visualiser/GameView.java @@ -80,6 +80,7 @@ public class GameView extends Pane { private Double frameRate = 60.0; private int frameTimeIndex = 0; private boolean arrayFilled = false; + private Yacht playerYacht; private enum ScaleDirection { HORIZONTAL, @@ -324,10 +325,10 @@ public class GameView extends Pane { 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) ->{ + yacht.addLocationListener((boat, lat, lon, heading, velocity, sailIn) ->{ BoatObject bo = boatObjects.get(boat); Point2D p2d = findScaledXY(lat, lon); - bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity); + bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn); // annotations.get(boat).setLayoutX(p2d.getX()); // annotations.get(boat).setLayoutY(p2d.getY()); // annotations.get(boat).setLocation(100d, 100d); @@ -569,7 +570,12 @@ public class GameView extends Pane { timer.start(); } + public Yacht getPlayerYacht() { + return playerYacht; + } + public void setBoatAsPlayer (Yacht playerYacht) { + this.playerYacht = playerYacht; boatObjects.get(playerYacht).setAsPlayer(); annotations.get(playerYacht).addAnnotation( "velocity", diff --git a/src/main/java/seng302/visualiser/controllers/RaceViewController.java b/src/main/java/seng302/visualiser/controllers/RaceViewController.java index a6df4f61..63ce668a 100644 --- a/src/main/java/seng302/visualiser/controllers/RaceViewController.java +++ b/src/main/java/seng302/visualiser/controllers/RaceViewController.java @@ -595,4 +595,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel this.courseData = raceData; gameView.updateBorder(raceData.getCourseLimit()); } + + public GameView getGameView() { + return gameView; + } } \ No newline at end of file diff --git a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java index 3441ba2d..5c8e6f15 100644 --- a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java +++ b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java @@ -12,6 +12,7 @@ import javafx.scene.shape.Line; import javafx.scene.shape.Polygon; import javafx.scene.shape.Polyline; import javafx.scene.transform.Rotate; +import seng302.gameServer.GameState; /** * BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 @@ -30,9 +31,11 @@ public class BoatObject extends Group { private double xVelocity; private double yVelocity; private double lastHeading; + private double sailState; //Graphical objects private Polyline trail = new Polyline(); private Polygon boatPoly; + private Polygon sail; private Wake wake; private Line leftLayLine; private Line rightLayline; @@ -87,14 +90,21 @@ public class BoatObject extends Group { // annotationBox = new AnnotationBox(); // annotationBox.setFill(colour); - + sail = new Polygon(0.0, BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + sailState = 0; + sail.setStrokeWidth(2.0); + sail.setStroke(Color.SILVER); + sail.setFill(Color.TRANSPARENT); + sail.setCache(true); + animateSail(); 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); + super.getChildren().addAll(boatPoly, sail);//, annotationBox); } public void setFill (Paint value) { @@ -105,19 +115,29 @@ public class BoatObject extends Group { /** * Moves the boat and its children annotations to coordinates specified - * - * @param x The X coordinate to move the boat to + * @param x The X coordinate to move the boat to * @param y The Y coordinate to move the boat to * @param rotation The rotation by which the boat moves * @param velocity The velocity the boat is moving + * @param sailIn */ - public void moveTo(double x, double y, double rotation, double velocity) { + public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn) { Double dx = Math.abs(boatPoly.getLayoutX() - x); Double dy = Math.abs(boatPoly.getLayoutY() - y); Platform.runLater(() -> { - rotateTo(rotation); + rotateTo(rotation, sailIn); boatPoly.setLayoutX(x); boatPoly.setLayoutY(y); + sail.setLayoutX(x); + sail.setLayoutY(y); + if (!sailIn) { + animateSail(); + } else { + sail.getPoints().clear(); + sail.getPoints().addAll(0.0,BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + + } wake.setLayoutX(x); wake.setLayoutY(y); }); @@ -142,8 +162,24 @@ public class BoatObject extends Group { } } - private void rotateTo(double rotation) { + private void rotateTo(double rotation, boolean sailsIn) { boatPoly.getTransforms().setAll(new Rotate(rotation)); + if (sailsIn) { + sail.getTransforms().setAll(new Rotate(GameState.getWindDirection() + 95.0)); + } else { + sail.getTransforms().setAll(new Rotate(GameState.getWindDirection())); + } + } + private void animateSail(){ + Double[] points = new Double[100]; + for (int i = 0; i < 50; i++) { + points[i * 2] = 5 * Math.sin(((Math.PI * i) / 25 + sailState)); + points[i * 2 + 1] = (BOAT_HEIGHT * i) / 25 + BOAT_HEIGHT / 4; + } + sailState = sailState + Math.PI / 10; + sail.getPoints().clear(); + sail.getPoints().addAll(points); + } public void updateLocation() { @@ -279,7 +315,7 @@ public class BoatObject extends Group { public void setTrajectory(double heading, double velocity) { wake.setRotation(lastHeading - heading, velocity); - rotateTo(heading); + rotateTo(heading, false); xVelocity = Math.cos(Math.toRadians(heading)) * velocity; yVelocity = Math.sin(Math.toRadians(heading)) * velocity; lastHeading = heading; From 8af80e6c3a934df041eb8c1a1c89fcaa4e5ec731 Mon Sep 17 00:00:00 2001 From: Zhi You Tan Date: Thu, 3 Aug 2017 18:39:15 +1200 Subject: [PATCH 03/82] WIP: Connected game client to main server thread to pass compound mark variable. Boats are initialised in main server thread behind start line before game starts. #story[1117] --- .../seng302/gameServer/MainServerThread.java | 48 +++++ .../gameServer/ServerToClientThread.java | 8 +- .../java/seng302/visualiser/GameClient.java | 8 +- src/main/resources/server_config/boats1.xml | 171 ------------------ src/main/resources/server_config/boats2.xml | 161 ----------------- src/main/resources/server_config/boats3.xml | 171 ------------------ src/main/resources/views/StartScreenView.fxml | 8 +- 7 files changed, 69 insertions(+), 506 deletions(-) delete mode 100644 src/main/resources/server_config/boats1.xml delete mode 100644 src/main/resources/server_config/boats2.xml delete mode 100644 src/main/resources/server_config/boats3.xml diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 6e827d95..23041a75 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -7,7 +7,14 @@ import java.util.ArrayList; import java.util.Observable; import java.util.Timer; import java.util.TimerTask; +import seng302.model.GeoPoint; import seng302.model.Player; +import seng302.model.Yacht; +import seng302.model.mark.CompoundMark; +import seng302.model.mark.Mark; +import seng302.model.stream.xml.parser.RaceXMLData; +import seng302.utilities.GeoUtility; +import seng302.visualiser.GameClient; /** * A class describing the overall server, which creates and collects server threads for each client @@ -25,6 +32,8 @@ public class MainServerThread extends Observable implements Runnable, ClientConn private ServerSocket serverSocket = null; private ArrayList serverToClientThreads = new ArrayList<>(); + private GameClient gameClient; + public MainServerThread() { try { serverSocket = new ServerSocket(PORT); @@ -130,6 +139,8 @@ public class MainServerThread extends Observable implements Runnable, ClientConn } public void startGame() { + initialiseBoatPosition(); + Timer t = new Timer(); t.schedule(new TimerTask() { @@ -146,4 +157,41 @@ public class MainServerThread extends Observable implements Runnable, ClientConn public void terminate() { terminated = true; } + + /** + * Pass GameClient to main server thread so it can access the properties inside. + * + * @param gameClient gameClient + */ + public void setGameClient(GameClient gameClient) { + this.gameClient = gameClient; + } + + /** + * Initialise boats to specific spaced out geopoint behind starting line. + */ + private void initialiseBoatPosition() { + System.out.println("ran"); + RaceXMLData raceXMLData = gameClient.getCourseData(); + CompoundMark cm = raceXMLData.getCompoundMarks().get(1); + GeoPoint geoPoint1 = new GeoPoint(cm.getMarks().get(0).getLat(), cm.getMarks().get(0).getLng()); + GeoPoint geoPoint2 = new GeoPoint(cm.getMarks().get(1).getLat(), cm.getMarks().get(1).getLng()); + Double perpendicularAngle = GeoUtility.getBearing(geoPoint1, geoPoint2); + + Double x = geoPoint1.getLat() + Math.sin(perpendicularAngle) * 1000; + Double y = geoPoint1.getLng() + Math.cos(perpendicularAngle) * 1000; + + ServerToClientThread stct0 = serverToClientThreads.get(0); + Yacht yacht0 = GameState.getYachts().get(stct0.getYacht().getSourceId()); + ServerToClientThread stct1 = serverToClientThreads.get(1); + Yacht yacht1 = GameState.getYachts().get(stct1.getYacht().getSourceId()); + yacht1.updateLocation(x,y, yacht1.getHeading(), yacht1.getVelocity()); + + System.out.println(yacht0.getLat() + " " + yacht0.getLon()); + System.out.println(yacht1.getLat() + " " + yacht1.getLon()); + + for (Yacht yacht : GameState.getYachts().values()) { + System.out.println("GS: " + yacht.getLat() + " " + yacht.getLon()); + } + } } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index ff2c4f23..c41f7ed0 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -64,6 +64,8 @@ public class ServerToClientThread implements Runnable, Observer { private XMLGenerator xml; + private Yacht yacht; + public ServerToClientThread(Socket socket) { this.socket = socket; BufferedReader fn; @@ -98,7 +100,7 @@ public class ServerToClientThread implements Runnable, Observer { sourceId = GameState.getUniquePlayerID(); if (threeWayHandshake(sourceId)) { serverLog("Successful handshake. Client allocated id: " + sourceId, 0); - Yacht yacht = new Yacht( + yacht = new Yacht( "Yacht", sourceId, sourceId.toString(), fName, fName + " " + lName, "NZ" ); // Yacht yacht = new Yacht("Kappa", "Kap", new GeoPoint(57.6708220, 11.8321340), 90.0); @@ -366,4 +368,8 @@ public class ServerToClientThread implements Runnable, Observer { public Socket getSocket() { return socket; } + + public Yacht getYacht() { + return yacht; + } } diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index 915eef37..6278e06f 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -89,6 +89,8 @@ public class GameClient { loadStartScreen(); } }); + + server.setGameClient(this); } private void loadStartScreen() { @@ -174,7 +176,7 @@ public class GameClient { break; case BOAT_XML: - System.out.println("GOT SUM BOATS YAY :)"); +// System.out.println("GOT SUM BOATS YAY :)"); allBoatsMap = XMLParser.parseBoats( StreamParser.extractXmlMessage(packet) ); @@ -322,4 +324,8 @@ public class GameClient { break; } } + + public RaceXMLData getCourseData() { + return courseData; + } } diff --git a/src/main/resources/server_config/boats1.xml b/src/main/resources/server_config/boats1.xml deleted file mode 100644 index 401e7bf6..00000000 --- a/src/main/resources/server_config/boats1.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - 2015-08-28T17:32:59+0100 - 12 - 219 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/server_config/boats2.xml b/src/main/resources/server_config/boats2.xml deleted file mode 100644 index c7255771..00000000 --- a/src/main/resources/server_config/boats2.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - 2015-08-28T17:32:59+0100 - 12 - 219 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/server_config/boats3.xml b/src/main/resources/server_config/boats3.xml deleted file mode 100644 index 401e7bf6..00000000 --- a/src/main/resources/server_config/boats3.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - 2015-08-28T17:32:59+0100 - 12 - 219 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/views/StartScreenView.fxml b/src/main/resources/views/StartScreenView.fxml index ec629307..4bd0a808 100644 --- a/src/main/resources/views/StartScreenView.fxml +++ b/src/main/resources/views/StartScreenView.fxml @@ -1,5 +1,10 @@ + + + + + @@ -10,6 +15,7 @@ + @@ -25,7 +31,7 @@ - + From f8af9cc259bddc417ea3e31d1a6bf210b5e9d1c4 Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Thu, 3 Aug 2017 19:07:30 +1200 Subject: [PATCH 04/82] Works for clients and server. Due to the information being sent and received, it only currently works on client side boats. #story[1111] --- src/main/java/seng302/model/Yacht.java | 5 +-- .../visualiser/fxObjects/BoatObject.java | 40 ++++++++++--------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index df6c1810..7ed1a5d3 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -282,9 +282,6 @@ public class Yacht { this.velocityProperty.set(velocity); } - public void updateSailsInProperty(Boolean clientSails) { - this.clientSailsIn = clientSails; - } public void setMarkRoundingTime(Long markRoundingTime) { this.markRoundTime = markRoundingTime; @@ -407,7 +404,7 @@ public class Yacht { this.velocity = velocity; updateVelocityProperty(velocity); for (YachtLocationListener yll : locationListeners) { - yll.notifyLocation(this, lat, lon, heading, velocity, this.clientSailsIn); + yll.notifyLocation(this, lat, lon, heading, velocity, clientSailsIn); } } diff --git a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java index 5c8e6f15..097658a9 100644 --- a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java +++ b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java @@ -90,21 +90,14 @@ public class BoatObject extends Group { // annotationBox = new AnnotationBox(); // annotationBox.setFill(colour); - sail = new Polygon(0.0, BOAT_HEIGHT / 4, - 0.0, BOAT_HEIGHT); - sailState = 0; - sail.setStrokeWidth(2.0); - sail.setStroke(Color.SILVER); - sail.setFill(Color.TRANSPARENT); - sail.setCache(true); - animateSail(); + 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, sail);//, annotationBox); + super.getChildren().addAll(boatPoly); } public void setFill (Paint value) { @@ -128,15 +121,16 @@ public class BoatObject extends Group { rotateTo(rotation, sailIn); boatPoly.setLayoutX(x); boatPoly.setLayoutY(y); - sail.setLayoutX(x); - sail.setLayoutY(y); - if (!sailIn) { + if (isPlayer && !sailIn) { animateSail(); - } else { + sail.setLayoutX(x); + sail.setLayoutY(y); + } else if (isPlayer){ sail.getPoints().clear(); sail.getPoints().addAll(0.0,BOAT_HEIGHT / 4, 0.0, BOAT_HEIGHT); - + sail.setLayoutX(x); + sail.setLayoutY(y); } wake.setLayoutX(x); wake.setLayoutY(y); @@ -164,10 +158,10 @@ public class BoatObject extends Group { private void rotateTo(double rotation, boolean sailsIn) { boatPoly.getTransforms().setAll(new Rotate(rotation)); - if (sailsIn) { - sail.getTransforms().setAll(new Rotate(GameState.getWindDirection() + 95.0)); - } else { - sail.getTransforms().setAll(new Rotate(GameState.getWindDirection())); + if (isPlayer && sailsIn) { + sail.getTransforms().setAll(new Rotate(95.0)); + } else if (isPlayer){ + sail.getTransforms().setAll(new Rotate(90.0)); } } private void animateSail(){ @@ -311,6 +305,16 @@ public class BoatObject extends Group { boatPoly.setStroke(Color.BLACK); boatPoly.setStrokeWidth(3); isPlayer = true; + sail = new Polygon(0.0, BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + sailState = 0; + sail.setStrokeWidth(2.0); + sail.setStroke(Color.BLACK); + sail.setFill(Color.TRANSPARENT); + sail.setCache(true); + super.getChildren().clear(); + super.getChildren().addAll(boatPoly, sail); + animateSail(); } public void setTrajectory(double heading, double velocity) { From ae28ccf2283c1b71b914499aee60a1a5bd88a46e Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Fri, 4 Aug 2017 16:24:34 +1200 Subject: [PATCH 05/82] Made sails luff in the right direction. #story[1111] --- .../java/seng302/visualiser/fxObjects/BoatObject.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java index 097658a9..bb6d6b64 100644 --- a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java +++ b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java @@ -125,7 +125,7 @@ public class BoatObject extends Group { animateSail(); sail.setLayoutX(x); sail.setLayoutY(y); - } else if (isPlayer){ + } else if (isPlayer) { sail.getPoints().clear(); sail.getPoints().addAll(0.0,BOAT_HEIGHT / 4, 0.0, BOAT_HEIGHT); @@ -170,7 +170,11 @@ public class BoatObject extends Group { points[i * 2] = 5 * Math.sin(((Math.PI * i) / 25 + sailState)); points[i * 2 + 1] = (BOAT_HEIGHT * i) / 25 + BOAT_HEIGHT / 4; } - sailState = sailState + Math.PI / 10; + if (sailState == - 2 * Math.PI) { + sailState = 0; + } else { + sailState = sailState - Math.PI / 10; + } sail.getPoints().clear(); sail.getPoints().addAll(points); From a727014fcbc37e6990d946b73f480c1264ed1016 Mon Sep 17 00:00:00 2001 From: Zhi You Tan Date: Sat, 5 Aug 2017 00:31:36 +1200 Subject: [PATCH 06/82] Implemented boats spawning in parallel at the start line with spacing. Added two more colours to support up to eight boats. #story[1117] --- .../seng302/gameServer/MainServerThread.java | 59 +++++++++++-------- src/main/java/seng302/model/Colors.java | 4 +- src/main/java/seng302/model/Yacht.java | 4 ++ 3 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 23041a75..56a954f4 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -20,7 +20,7 @@ import seng302.visualiser.GameClient; * A class describing the overall server, which creates and collects server threads for each client * Created by wmu16 on 13/07/17. */ -public class MainServerThread extends Observable implements Runnable, ClientConnectionDelegate{ +public class MainServerThread extends Observable implements Runnable, ClientConnectionDelegate { private static final int PORT = 4942; private static final Integer CLIENT_UPDATES_PER_SECOND = 10; @@ -96,14 +96,16 @@ public class MainServerThread extends Observable implements Runnable, ClientConn } - static void serverLog(String message, int logLevel){ - if(logLevel <= LOG_LEVEL){ - System.out.println("[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message); + static void serverLog(String message, int logLevel) { + if (logLevel <= LOG_LEVEL) { + System.out.println( + "[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message); } } /** * A client has tried to connect to the server + * * @param serverToClientThread The player that connected */ @Override @@ -117,6 +119,7 @@ public class MainServerThread extends Observable implements Runnable, ClientConn /** * A player has left the game, remove the player from the GameState + * * @param player The player that left */ @Override @@ -168,30 +171,40 @@ public class MainServerThread extends Observable implements Runnable, ClientConn } /** - * Initialise boats to specific spaced out geopoint behind starting line. + * Initialise boats to specific spaced out geopoints behind starting line. */ private void initialiseBoatPosition() { - System.out.println("ran"); - RaceXMLData raceXMLData = gameClient.getCourseData(); - CompoundMark cm = raceXMLData.getCompoundMarks().get(1); - GeoPoint geoPoint1 = new GeoPoint(cm.getMarks().get(0).getLat(), cm.getMarks().get(0).getLng()); - GeoPoint geoPoint2 = new GeoPoint(cm.getMarks().get(1).getLat(), cm.getMarks().get(1).getLng()); - Double perpendicularAngle = GeoUtility.getBearing(geoPoint1, geoPoint2); + // Getting the start line compound marks + CompoundMark cm = gameClient.getCourseData().getCompoundMarks().get(1); + GeoPoint startMark1 = new GeoPoint(cm.getMarks().get(0).getLat(), + cm.getMarks().get(0).getLng()); + GeoPoint startMark2 = new GeoPoint(cm.getMarks().get(1).getLat(), + cm.getMarks().get(1).getLng()); - Double x = geoPoint1.getLat() + Math.sin(perpendicularAngle) * 1000; - Double y = geoPoint1.getLng() + Math.cos(perpendicularAngle) * 1000; - - ServerToClientThread stct0 = serverToClientThreads.get(0); - Yacht yacht0 = GameState.getYachts().get(stct0.getYacht().getSourceId()); - ServerToClientThread stct1 = serverToClientThreads.get(1); - Yacht yacht1 = GameState.getYachts().get(stct1.getYacht().getSourceId()); - yacht1.updateLocation(x,y, yacht1.getHeading(), yacht1.getVelocity()); - - System.out.println(yacht0.getLat() + " " + yacht0.getLon()); - System.out.println(yacht1.getLat() + " " + yacht1.getLon()); + // Calculating midpoint + Double perpendicularAngle = GeoUtility.getBearing(startMark1, startMark2); + Double length = GeoUtility.getDistance(startMark1, startMark2); + GeoPoint midpoint = GeoUtility.getGeoCoordinate(startMark1, perpendicularAngle, length / 2); + // Setting each boats position side by side + double distanceApart = 0.0005; // magic number for boat spawn distance apart + int boatIndex = 0; + int boatSpawnDirection = -1; // positive for left and negative for right for (Yacht yacht : GameState.getYachts().values()) { - System.out.println("GS: " + yacht.getLat() + " " + yacht.getLon()); + Double x = + midpoint.getLat() + boatSpawnDirection * boatIndex * Math.sin(perpendicularAngle) + * distanceApart; + Double y = + midpoint.getLng() + boatSpawnDirection * boatIndex * Math.cos(perpendicularAngle) + * distanceApart; + yacht.setLocation(new GeoPoint(x, y)); + + if (boatSpawnDirection == -1) { + boatSpawnDirection = 1; + boatIndex++; + } else { + boatSpawnDirection = -1; + } } } } diff --git a/src/main/java/seng302/model/Colors.java b/src/main/java/seng302/model/Colors.java index 72ff3ba5..81829262 100644 --- a/src/main/java/seng302/model/Colors.java +++ b/src/main/java/seng302/model/Colors.java @@ -6,12 +6,12 @@ import javafx.scene.paint.Color; * Enum for generating colours. */ public enum Colors { - RED, PERU, SEAGREEN, GREEN, BLUE, PURPLE; + RED, PERU, GOLD, GREEN, BLUE, PURPLE, DEEPPINK, GRAY; static Integer index = 0; public static Color getColor() { - if (index == 6) { + if (index == 8) { index = 0; } return Color.valueOf(values()[index++].toString()); diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index aba80d1a..caf7afd3 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -406,4 +406,8 @@ public class Yacht { public void addLocationListener (YachtLocationListener listener) { locationListeners.add(listener); } + + public void setLocation(GeoPoint geoPoint) { + location = geoPoint; + } } From 81c2a8e0fd343bfe2765a1460b95598b74ab355a Mon Sep 17 00:00:00 2001 From: Zhi You Tan Date: Sat, 5 Aug 2017 23:59:58 +1200 Subject: [PATCH 07/82] WIP: Added test initialise boat position test. Corrected ColorsTest after addition of two new colours. --- src/test/java/seng302/ColorsTest.java | 6 +++--- .../server/TestInitialiseBoatPosition.java | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java diff --git a/src/test/java/seng302/ColorsTest.java b/src/test/java/seng302/ColorsTest.java index d9f1ee4f..0b4b4238 100644 --- a/src/test/java/seng302/ColorsTest.java +++ b/src/test/java/seng302/ColorsTest.java @@ -9,9 +9,9 @@ public class ColorsTest { @Test public void testNextColor() { - Color expectedColors[] = {Color.RED, Color.PERU, Color.SEAGREEN, Color.GREEN, Color.BLUE, Color.PURPLE}; - for (int i = 0; i<6; i++) - { + Color expectedColors[] = {Color.RED, Color.PERU, Color.GOLD, Color.GREEN, Color.BLUE, + Color.PURPLE, Color.DEEPPINK, Color.GRAY}; + for (int i = 0; i < 8; i++) { Assert.assertEquals(expectedColors[i], Colors.getColor()); } } diff --git a/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java b/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java new file mode 100644 index 00000000..d27739a2 --- /dev/null +++ b/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java @@ -0,0 +1,15 @@ +package seng302.gameServer.server; + +import static junit.framework.TestCase.assertTrue; + +import org.junit.Test; + +/** + * Created by ryantan on 5/08/2017. + */ +public class TestInitialiseBoatPosition { + @Test + public void testInitialiseBoatPosition(){ + + } +} From ecf2c52cfa1f7a7e2125496426ba052e3afb6e59 Mon Sep 17 00:00:00 2001 From: Kusal Ekanayake Date: Sun, 6 Aug 2017 15:43:22 +1200 Subject: [PATCH 08/82] Added tests, and sails to all clients. #story[1111] --- src/main/java/seng302/model/Yacht.java | 6 ++- .../java/seng302/visualiser/GameView.java | 3 +- .../visualiser/fxObjects/BoatObject.java | 45 +++++++++---------- .../map/BoatSailAnimationToggleTest.java | 35 +++++++++++++++ 4 files changed, 64 insertions(+), 25 deletions(-) create mode 100644 src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index 7ed1a5d3..16df9123 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -62,7 +62,7 @@ public class Yacht { private CompoundMark lastMarkRounded; private Integer positionInt = 0; private Color colour; - private Boolean clientSailsIn = false; + private Boolean clientSailsIn = true; public Yacht(String boatType, Integer sourceId, String hullID, String shortName, String boatName, String country) { @@ -397,6 +397,10 @@ public class Yacht { this.velocity = velocity; } + public Boolean getClientSailsIn(){ + return clientSailsIn; + } + public void updateLocation (double lat, double lon, double heading, double velocity) { this.lat = lat; this.lon = lon; diff --git a/src/main/java/seng302/visualiser/GameView.java b/src/main/java/seng302/visualiser/GameView.java index 37507035..45abc37a 100644 --- a/src/main/java/seng302/visualiser/GameView.java +++ b/src/main/java/seng302/visualiser/GameView.java @@ -328,7 +328,7 @@ public class GameView extends Pane { yacht.addLocationListener((boat, lat, lon, heading, velocity, sailIn) ->{ BoatObject bo = boatObjects.get(boat); Point2D p2d = findScaledXY(lat, lon); - bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn); + bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, 95.0); // annotations.get(boat).setLayoutX(p2d.getX()); // annotations.get(boat).setLayoutY(p2d.getY()); // annotations.get(boat).setLocation(100d, 100d); @@ -576,6 +576,7 @@ public class GameView extends Pane { public void setBoatAsPlayer (Yacht playerYacht) { this.playerYacht = playerYacht; + this.playerYacht.toggleClientSail(); boatObjects.get(playerYacht).setAsPlayer(); annotations.get(playerYacht).addAnnotation( "velocity", diff --git a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java index bb6d6b64..2527fca1 100644 --- a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java +++ b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java @@ -12,7 +12,6 @@ import javafx.scene.shape.Line; import javafx.scene.shape.Polygon; import javafx.scene.shape.Polyline; import javafx.scene.transform.Rotate; -import seng302.gameServer.GameState; /** * BoatGroup is a javafx group that by default contains a graphical objects for representing a 2 @@ -97,7 +96,16 @@ public class BoatObject extends Group { trail.setCache(true); wake = new Wake(0, -BOAT_HEIGHT); wake.setVisible(true); - super.getChildren().addAll(boatPoly); + + sail = new Polygon(0.0,BOAT_HEIGHT / 4, + 0.0, BOAT_HEIGHT); + sailState = 0; + sail.setStrokeWidth(2.0); + sail.setStroke(Color.BLACK); + sail.setFill(Color.TRANSPARENT); + sail.setCache(true); + super.getChildren().clear(); + super.getChildren().addAll(boatPoly, sail); } public void setFill (Paint value) { @@ -114,23 +122,23 @@ public class BoatObject extends Group { * @param velocity The velocity the boat is moving * @param sailIn */ - public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn) { + public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) { Double dx = Math.abs(boatPoly.getLayoutX() - x); Double dy = Math.abs(boatPoly.getLayoutY() - y); Platform.runLater(() -> { - rotateTo(rotation, sailIn); + rotateTo(rotation, sailIn, windDir); boatPoly.setLayoutX(x); boatPoly.setLayoutY(y); - if (isPlayer && !sailIn) { - animateSail(); - sail.setLayoutX(x); - sail.setLayoutY(y); - } else if (isPlayer) { + if (sailIn) { sail.getPoints().clear(); sail.getPoints().addAll(0.0,BOAT_HEIGHT / 4, 0.0, BOAT_HEIGHT); sail.setLayoutX(x); sail.setLayoutY(y); + } else { + animateSail(); + sail.setLayoutX(x); + sail.setLayoutY(y); } wake.setLayoutX(x); wake.setLayoutY(y); @@ -156,11 +164,11 @@ public class BoatObject extends Group { } } - private void rotateTo(double rotation, boolean sailsIn) { + private void rotateTo(double rotation, boolean sailsIn, double windDir) { boatPoly.getTransforms().setAll(new Rotate(rotation)); - if (isPlayer && sailsIn) { + if (sailsIn) { sail.getTransforms().setAll(new Rotate(95.0)); - } else if (isPlayer){ + } else { sail.getTransforms().setAll(new Rotate(90.0)); } } @@ -309,21 +317,12 @@ public class BoatObject extends Group { boatPoly.setStroke(Color.BLACK); boatPoly.setStrokeWidth(3); isPlayer = true; - sail = new Polygon(0.0, BOAT_HEIGHT / 4, - 0.0, BOAT_HEIGHT); - sailState = 0; - sail.setStrokeWidth(2.0); - sail.setStroke(Color.BLACK); - sail.setFill(Color.TRANSPARENT); - sail.setCache(true); - super.getChildren().clear(); - super.getChildren().addAll(boatPoly, sail); animateSail(); } - public void setTrajectory(double heading, double velocity) { + public void setTrajectory(double heading, double velocity, double windDir) { wake.setRotation(lastHeading - heading, velocity); - rotateTo(heading, false); + rotateTo(heading, false, windDir); xVelocity = Math.cos(Math.toRadians(heading)) * velocity; yVelocity = Math.sin(Math.toRadians(heading)) * velocity; lastHeading = heading; diff --git a/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java b/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java new file mode 100644 index 00000000..0f353701 --- /dev/null +++ b/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java @@ -0,0 +1,35 @@ +package seng302.visualiser.map; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import seng302.model.Yacht; +import seng302.visualiser.fxObjects.BoatObject; + +/** + * Created by kre39 on 6/08/17. + */ +public class BoatSailAnimationToggleTest { + + private Yacht yacht; + + + @Before + public void setup() throws Exception{ + yacht = new Yacht("Yacht", 1, "YACHT", "YAC", "Test Yacht", "NZ"); + } + + + @Test + public void sailToggleTest() throws Exception { + assertFalse(yacht.getClientSailsIn()); + assertFalse(yacht.getSailIn()); + yacht.toggleClientSail(); + assertTrue(yacht.getClientSailsIn()); + assertFalse(yacht.getSailIn()); + } + +} From a470cb66a2f6ea17a9d22ac04f0c2326786e3f06 Mon Sep 17 00:00:00 2001 From: Zhi You Tan Date: Sun, 6 Aug 2017 21:16:14 +1200 Subject: [PATCH 09/82] Updated initialise boat function so it can now initialise boats with distance apart in meters. Created a second prototype function which is more testable compared to the initial design. New function takes in parameters (starting marks, yacht starting position, yacht) and initialise yacht correctly with position. #story[1117] --- .../java/seng302/gameServer/GameState.java | 55 ++++++++++++++++--- .../seng302/gameServer/MainServerThread.java | 25 ++++----- .../server/TestInitialiseBoatPosition.java | 35 +++++++++++- 3 files changed, 93 insertions(+), 22 deletions(-) diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java index bb6f0c16..0a0cc7c0 100644 --- a/src/main/java/seng302/gameServer/GameState.java +++ b/src/main/java/seng302/gameServer/GameState.java @@ -7,9 +7,12 @@ import java.util.Map; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; +import seng302.model.GeoPoint; import seng302.model.Player; import seng302.model.Yacht; import seng302.gameServer.server.messages.BoatActionType; +import seng302.model.mark.CompoundMark; +import seng302.utilities.GeoUtility; /** * A Static class to hold information about the current state of the game (model) @@ -71,17 +74,20 @@ public class GameState implements Runnable { return players; } - public static ObservableList getObservablePlayers () { + public static ObservableList getObservablePlayers() { return observablePlayers; } public static void addPlayer(Player player) { players.add(player); - String playerText = player.getYacht().getSourceId() + " " + player.getYacht().getBoatName() + " " + player.getYacht().getCountry(); - Platform.runLater(() -> observablePlayers.add(playerText)); //Had to add this to handle javaFX window using array + String playerText = + player.getYacht().getSourceId() + " " + player.getYacht().getBoatName() + " " + player + .getYacht().getCountry(); + Platform.runLater(() -> observablePlayers + .add(playerText)); //Had to add this to handle javaFX window using array playerStringMap.put(player, playerText); } - + public static void removePlayer(Player player) { players.remove(player); observablePlayers.remove(playerStringMap.get(player)); @@ -105,14 +111,14 @@ public class GameState implements Runnable { } public static void setCurrentStage(GameStages currentStage) { - if (currentStage == GameStages.RACING){ + if (currentStage == GameStages.RACING) { startTime = System.currentTimeMillis(); } GameState.currentStage = currentStage; } - public static long getStartTime(){ + public static long getStartTime() { return startTime; } @@ -175,6 +181,7 @@ public class GameState implements Runnable { /** * Generates a new ID based off the size of current players + 1 + * * @return a playerID to be allocated to a new connetion */ public static Integer getUniquePlayerID() { @@ -189,7 +196,7 @@ public class GameState implements Runnable { @Override public void run() { - while(true) { + while (true) { try { Thread.sleep(1000 / STATE_UPDATES_PER_SECOND); } catch (InterruptedException e) { @@ -215,4 +222,38 @@ public class GameState implements Runnable { System.out.println("Lng: " + playerYacht.getLocation().getLng()); System.out.println("-----------------------\n"); } + +// /** +// * Calculates and initialise a yacht given its index in the starting position. Position is +// * calculated starting with 0 being the first boat. Position 0 will spawn in the MIDDLE of mark1 +// * and mark2, position 1 will spawn 50m LEFT of position 0, position 2 will spawn 50m RIGHT of +// * position 0, position 3 will spawn 100m LEFT of position 0, and so forth. +// * +// * @param mark1 first mark of the starting composite mark +// * @param mark2 second mark of the starting composite mark +// * @param boatIndex boat starting position +// * @param yacht yacht to be reposition +// */ +// public static void startBoatInPosition(GeoPoint mark1, GeoPoint mark2, Integer boatIndex, +// Yacht yacht) { +// // TODO: 6/08/2017 zyt10 - check for mark1 being the right side from heading +// // Calculating midpoint +// Double perpendicularAngle = GeoUtility.getBearing(mark1, mark2); +// Double length = GeoUtility.getDistance(mark1, mark2); +// GeoPoint midpoint = GeoUtility.getGeoCoordinate(mark1, perpendicularAngle, length / 2); +// +// // Setting each boats position side by side +// double DISTANCEFACTOR = 50.0; // distance apart in meters +// int distanceApart = boatIndex / 2; +// +// if (boatIndex % 2 == 1 && boatIndex != 0) { +// distanceApart++; +// distanceApart *= 1; +// } +// +// GeoPoint spawnMark = GeoUtility +// .getGeoCoordinate(midpoint, perpendicularAngle, distanceApart * DISTANCEFACTOR); +// +// yacht.setLocation(spawnMark); +// } } diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 56a954f4..6179b083 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -187,24 +187,21 @@ public class MainServerThread extends Observable implements Runnable, ClientConn GeoPoint midpoint = GeoUtility.getGeoCoordinate(startMark1, perpendicularAngle, length / 2); // Setting each boats position side by side - double distanceApart = 0.0005; // magic number for boat spawn distance apart + double DISTANCEFACTOR = 50.0; // distance apart in meters int boatIndex = 0; - int boatSpawnDirection = -1; // positive for left and negative for right for (Yacht yacht : GameState.getYachts().values()) { - Double x = - midpoint.getLat() + boatSpawnDirection * boatIndex * Math.sin(perpendicularAngle) - * distanceApart; - Double y = - midpoint.getLng() + boatSpawnDirection * boatIndex * Math.cos(perpendicularAngle) - * distanceApart; - yacht.setLocation(new GeoPoint(x, y)); + int distanceApart = boatIndex / 2; - if (boatSpawnDirection == -1) { - boatSpawnDirection = 1; - boatIndex++; - } else { - boatSpawnDirection = -1; + if (boatIndex % 2 == 1 && boatIndex != 0) { + distanceApart++; + distanceApart *= -1; } + + GeoPoint spawnMark = GeoUtility + .getGeoCoordinate(midpoint, perpendicularAngle, distanceApart * DISTANCEFACTOR); + + yacht.setLocation(spawnMark); + boatIndex++; } } } diff --git a/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java b/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java index d27739a2..14d33db2 100644 --- a/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java +++ b/src/test/java/seng302/gameServer/server/TestInitialiseBoatPosition.java @@ -3,13 +3,46 @@ package seng302.gameServer.server; import static junit.framework.TestCase.assertTrue; import org.junit.Test; +import seng302.gameServer.GameState; +import seng302.gameServer.MainServerThread; +import seng302.model.GeoPoint; +import seng302.model.Yacht; +import seng302.utilities.GeoUtility; /** * Created by ryantan on 5/08/2017. */ public class TestInitialiseBoatPosition { + private GeoPoint mark1 = new GeoPoint(50, 50); + private GeoPoint mark2 = new GeoPoint(0, 0); + + private GameState gameState = new GameState(""); + @Test public void testInitialiseBoatPosition(){ - +// // Calculating midpoint +// Double perpendicularAngle = GeoUtility.getBearing(mark1, mark2); +// Double length = GeoUtility.getDistance(mark1, mark2); +// GeoPoint midpoint = GeoUtility.getGeoCoordinate(mark1, perpendicularAngle, length / 2); +// +// // Create 8 yacht in game state +// for (int i = 0; i < 8; i++) { +// GameState.addYacht(i, new Yacht("Yacht", i, "1", "Yacht" + i, "Yacht" + i, "Test" )); +// } +// +// int i = 0; +// for (Yacht yacht : GameState.getYachts().values()) { +// GameState.startBoatInPosition(mark1, mark2, i, yacht); +// double distance = GeoUtility.getDistance(midpoint, yacht.getLocation()); +// System.out.println(i + " " + distance); +// +// double distanceApart = i / 2; +// if (i % 2 == 1 && i != 0) { +// distanceApart++; +// } +// +// assertTrue(distance <= (distanceApart * 50.01) && distance >= (distanceApart * 49.99)); +// i++; +// } } } From 8a40119a9857ff31d178cbc1efcc65fe63e82791 Mon Sep 17 00:00:00 2001 From: Calum Date: Sun, 6 Aug 2017 22:17:08 +1200 Subject: [PATCH 10/82] Action packets now sent at regular 20ms intervals #issue[38] #implement --- pom.xml | 15 +++ .../server/messages/BoatActionType.java | 3 +- src/main/java/seng302/model/Yacht.java | 2 +- .../{visualiser => v}/map/Boundary.java | 2 +- .../{visualiser => v}/map/CanvasMap.java | 2 +- .../map/MercatorProjection.java | 4 +- .../map/TestMapController.java | 2 +- .../visualiser/ClientToServerThread.java | 62 +++++++-- .../java/seng302/visualiser/GameClient.java | 75 ++++------- .../java/seng302/visualiser/GameView.java | 4 +- .../controllers/LobbyController.java | 125 ++++++------------ src/main/resources/views/LobbyView.fxml | 51 +++---- src/main/resources/views/TestMapView.fxml | 2 +- .../RegularPacketsTest.java | 123 +++++++++++++++++ .../TestImportantAnnotationState.java | 2 +- .../map/MercatorProjectionTest.java | 1 + 16 files changed, 286 insertions(+), 189 deletions(-) rename src/main/java/seng302/{visualiser => v}/map/Boundary.java (96%) rename src/main/java/seng302/{visualiser => v}/map/CanvasMap.java (98%) rename src/main/java/seng302/{visualiser => v}/map/MercatorProjection.java (96%) rename src/main/java/seng302/{visualiser => v}/map/TestMapController.java (95%) create mode 100644 src/test/java/seng302/visualiser/ClientToServerTests/RegularPacketsTest.java rename src/test/java/seng302/{visualizer => visualiser}/annotations/TestImportantAnnotationState.java (97%) diff --git a/pom.xml b/pom.xml index aac3b0c7..b329e067 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,21 @@ commons-cli 1.4 + + + org.testfx + testfx-core + 4.0.1-alpha + test + + + + org.testfx + testfx-junit + 4.0.6-alpha + test + + diff --git a/src/main/java/seng302/gameServer/server/messages/BoatActionType.java b/src/main/java/seng302/gameServer/server/messages/BoatActionType.java index 53fc6018..1b9fdd58 100644 --- a/src/main/java/seng302/gameServer/server/messages/BoatActionType.java +++ b/src/main/java/seng302/gameServer/server/messages/BoatActionType.java @@ -13,7 +13,8 @@ public enum BoatActionType { SAILS_OUT(3), TACK_GYBE(4), UPWIND(5), - DOWNWIND(6); + DOWNWIND(6), + MAINTAIN_HEADING(7); private final int type; private static final Map intToTypeMap = new HashMap<>(); diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index d7cd1f9e..9afe778a 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -48,7 +48,7 @@ public class Yacht { private Integer legNumber = 0; //SERVER SIDE - private final Double TURN_STEP = 5.0; + static public final Double TURN_STEP = 1.0; //This should be in some utils class somewhere 2bh. Public for tests sake. private Double lastHeading; private Boolean sailIn; private GeoPoint location; diff --git a/src/main/java/seng302/visualiser/map/Boundary.java b/src/main/java/seng302/v/map/Boundary.java similarity index 96% rename from src/main/java/seng302/visualiser/map/Boundary.java rename to src/main/java/seng302/v/map/Boundary.java index 21f2661d..68085ec7 100644 --- a/src/main/java/seng302/visualiser/map/Boundary.java +++ b/src/main/java/seng302/v/map/Boundary.java @@ -1,4 +1,4 @@ -package seng302.visualiser.map; +package seng302.v.map; /** * The Boundary class represents a rectangle territorial boundary on a map. It diff --git a/src/main/java/seng302/visualiser/map/CanvasMap.java b/src/main/java/seng302/v/map/CanvasMap.java similarity index 98% rename from src/main/java/seng302/visualiser/map/CanvasMap.java rename to src/main/java/seng302/v/map/CanvasMap.java index e79805e4..10cd60c3 100644 --- a/src/main/java/seng302/visualiser/map/CanvasMap.java +++ b/src/main/java/seng302/v/map/CanvasMap.java @@ -1,4 +1,4 @@ -package seng302.visualiser.map; +package seng302.v.map; import java.net.URL; import javafx.geometry.Point2D; diff --git a/src/main/java/seng302/visualiser/map/MercatorProjection.java b/src/main/java/seng302/v/map/MercatorProjection.java similarity index 96% rename from src/main/java/seng302/visualiser/map/MercatorProjection.java rename to src/main/java/seng302/v/map/MercatorProjection.java index 3f86e628..28bd341f 100644 --- a/src/main/java/seng302/visualiser/map/MercatorProjection.java +++ b/src/main/java/seng302/v/map/MercatorProjection.java @@ -1,4 +1,4 @@ -package seng302.visualiser.map; +package seng302.v.map; import javafx.geometry.Point2D; import seng302.model.GeoPoint; @@ -28,7 +28,7 @@ public class MercatorProjection { * @param geo GeoPoint (lat, lng) location to be projected * @return the projection Point2D (x, y) on planar */ - static Point2D toMapPoint(GeoPoint geo) { + public static Point2D toMapPoint(GeoPoint geo) { double x, y; Point2D origin = new Point2D(MERCATOR_RANGE / 2.0, MERCATOR_RANGE / 2.0); x = (origin.getX() + geo.getLng() * pixelsPerLngDegree); diff --git a/src/main/java/seng302/visualiser/map/TestMapController.java b/src/main/java/seng302/v/map/TestMapController.java similarity index 95% rename from src/main/java/seng302/visualiser/map/TestMapController.java rename to src/main/java/seng302/v/map/TestMapController.java index cd0b4c60..520a1e3b 100644 --- a/src/main/java/seng302/visualiser/map/TestMapController.java +++ b/src/main/java/seng302/v/map/TestMapController.java @@ -1,4 +1,4 @@ -package seng302.visualiser.map; +package seng302.v.map; import java.net.URL; import java.util.ResourceBundle; diff --git a/src/main/java/seng302/visualiser/ClientToServerThread.java b/src/main/java/seng302/visualiser/ClientToServerThread.java index 414696c8..1bfaa10d 100644 --- a/src/main/java/seng302/visualiser/ClientToServerThread.java +++ b/src/main/java/seng302/visualiser/ClientToServerThread.java @@ -9,12 +9,15 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Queue; +import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.zip.CRC32; import java.util.zip.Checksum; import javafx.application.Platform; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; +import seng302.gameServer.server.messages.BoatActionType; import seng302.model.stream.packets.StreamPacket; import seng302.gameServer.server.messages.BoatActionMessage; import seng302.gameServer.server.messages.Message; @@ -47,11 +50,15 @@ public class ClientToServerThread implements Runnable { private Socket socket; private InputStream is; + + //Output stream private OutputStream os; + private Timer osTimer = new Timer(); + private Queue eventQueue = new ConcurrentLinkedQueue<>(); + private boolean upwindFlag = false, downwindFlag = false; + static public final int PACKET_SENDING_INTERVAL_MS = 20; private int clientId; - -// private Boolean updateClient = true; private ByteArrayOutputStream crcBuffer; private boolean socketOpen = true; @@ -83,6 +90,15 @@ public class ClientToServerThread implements Runnable { thread = new Thread(this); thread.start(); + + osTimer.scheduleAtFixedRate( + new TimerTask() { + @Override + public void run() { + processBoatActionQueue(); + } + }, 0, PACKET_SENDING_INTERVAL_MS + ); } /** @@ -181,18 +197,42 @@ public class ClientToServerThread implements Runnable { /** - * Send the post-start race course information - * @param boatActionMessage The message to send + * Processes next element in the queue of events to send. */ - public void sendBoatActionMessage(BoatActionMessage boatActionMessage) { + private void processBoatActionQueue() { + BoatActionType action = eventQueue.poll(); + if (action != null) { + switch (action) { + case MAINTAIN_HEADING: + downwindFlag = upwindFlag = false; break; + case DOWNWIND: + downwindFlag = true; break; + case UPWIND: + upwindFlag = true; break; + default: + sendBoatAction(new BoatActionMessage(action)); break; + } + } + if (downwindFlag) { + sendBoatAction(new BoatActionMessage(BoatActionType.DOWNWIND)); + } + if (upwindFlag) { + sendBoatAction(new BoatActionMessage(BoatActionType.UPWIND)); + } + } + + /** + * Sends a boat action of the given message type. + * @param message The given message type. + */ + private void sendBoatAction(BoatActionMessage message) { try { - os.write(boatActionMessage.getBuffer()); + os.write(message.getBuffer()); } catch (IOException e) { clientLog("Could not write to server", 1); } } - private void closeSocket() { try { socket.close(); @@ -245,11 +285,11 @@ public class ClientToServerThread implements Runnable { } } - public Thread getThread() { - return thread; - } - public int getClientId () { return clientId; } + + public void sendBoatEvent(BoatActionType actionType) { + eventQueue.add(actionType); + } } diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index 915eef37..0b52a3a4 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -13,6 +13,7 @@ import javafx.scene.Node; import javafx.scene.input.KeyEvent; import javafx.scene.layout.Pane; import seng302.gameServer.MainServerThread; +import seng302.gameServer.server.messages.BoatActionType; import seng302.model.RaceState; import seng302.model.Yacht; import seng302.model.stream.packets.StreamPacket; @@ -22,8 +23,6 @@ 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.gameServer.server.messages.BoatActionMessage; -import seng302.gameServer.server.messages.BoatActionType; import seng302.utilities.StreamParser; import seng302.utilities.XMLParser; import seng302.visualiser.controllers.LobbyController; @@ -48,9 +47,6 @@ public class GameClient { private ObservableList clientLobbyList = FXCollections.observableArrayList(); - private long lastSendingTime; - private int KEY_STROKE_SENDING_FREQUENCY = 50; - public GameClient(Pane holder) { this.holderPane = holder; } @@ -174,17 +170,13 @@ 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()); - }); -// startRaceIfAllDataReceived(); break; case RACE_START_STATUS: @@ -279,47 +271,34 @@ public class GameClient { * Handle the key-pressed event from the text field. * @param e The key event triggering this call */ - public void keyPressed(KeyEvent e) { - BoatActionMessage boatActionMessage; - long currentTime = System.currentTimeMillis(); - if (currentTime - lastSendingTime > KEY_STROKE_SENDING_FREQUENCY) { - lastSendingTime = currentTime; - switch (e.getCode()) { - case SPACE: // align with vmg - boatActionMessage = new BoatActionMessage(BoatActionType.VMG); - socketThread.sendBoatActionMessage(boatActionMessage); - break; - case PAGE_UP: // upwind - boatActionMessage = new BoatActionMessage(BoatActionType.UPWIND); - socketThread.sendBoatActionMessage(boatActionMessage); - break; - case PAGE_DOWN: // downwind - boatActionMessage = new BoatActionMessage(BoatActionType.DOWNWIND); - socketThread.sendBoatActionMessage(boatActionMessage); - break; - case ENTER: // tack/gybe - boatActionMessage = new BoatActionMessage(BoatActionType.TACK_GYBE); - socketThread.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) { + private void keyPressed(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); - socketThread.sendBoatActionMessage(boatActionMessage); + case SPACE: // align with vmg + socketThread.sendBoatEvent(BoatActionType.VMG); break; + case PAGE_UP: // upwind + socketThread.sendBoatEvent(BoatActionType.UPWIND); break; + case PAGE_DOWN: // downwind + socketThread.sendBoatEvent(BoatActionType.DOWNWIND); break; + case ENTER: // tack/gybe + socketThread.sendBoatEvent(BoatActionType.TACK_GYBE); 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; } } + + private 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 + socketThread.sendBoatEvent(BoatActionType.SAILS_IN); break; + case PAGE_UP: + case PAGE_DOWN: + socketThread.sendBoatEvent(BoatActionType.MAINTAIN_HEADING); break; + } + } } diff --git a/src/main/java/seng302/visualiser/GameView.java b/src/main/java/seng302/visualiser/GameView.java index 73d49b89..180f85ca 100644 --- a/src/main/java/seng302/visualiser/GameView.java +++ b/src/main/java/seng302/visualiser/GameView.java @@ -32,8 +32,8 @@ import seng302.visualiser.fxObjects.BoatObject; import seng302.visualiser.fxObjects.CourseBoundary; import seng302.visualiser.fxObjects.Gate; import seng302.visualiser.fxObjects.Marker; -import seng302.visualiser.map.Boundary; -import seng302.visualiser.map.CanvasMap; +import seng302.v.map.Boundary; +import seng302.v.map.CanvasMap; /** * Created by cir27 on 20/07/17. diff --git a/src/main/java/seng302/visualiser/controllers/LobbyController.java b/src/main/java/seng302/visualiser/controllers/LobbyController.java index 1a8b13e3..809bd3b5 100644 --- a/src/main/java/seng302/visualiser/controllers/LobbyController.java +++ b/src/main/java/seng302/visualiser/controllers/LobbyController.java @@ -4,15 +4,13 @@ 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; import javafx.fxml.FXML; import javafx.scene.control.Button; -import javafx.scene.control.ListView; +import javafx.scene.control.TextArea; import javafx.scene.image.Image; import javafx.scene.image.ImageView; -import javafx.scene.layout.GridPane; import javafx.scene.text.Text; import seng302.gameServer.GameStages; import seng302.gameServer.GameState; @@ -33,28 +31,26 @@ public class LobbyController { void notify(CloseStatus exitCause); } - @FXML - private GridPane lobbyScreen; @FXML private Text lobbyIpText; @FXML private Button readyButton; @FXML - private ListView firstListView; + private TextArea playerOneTxt; @FXML - private ListView secondListView; + private TextArea playerTwoTxt; @FXML - private ListView thirdListView; + private TextArea playerThreeTxt; @FXML - private ListView fourthListView; + private TextArea playerFourTxt; @FXML - private ListView fifthListView; + private TextArea playerFiveTxt; @FXML - private ListView sixthListView; + private TextArea playerSixTxt; @FXML - private ListView seventhListView; + private TextArea playerSevenTxt; @FXML - private ListView eighthListView; + private TextArea playerEightTxt; @FXML private ImageView firstImageView; @FXML @@ -72,79 +68,67 @@ public class LobbyController { @FXML private ImageView eighthImageView; - private List> competitors = new ArrayList<>(); - private ObservableList firstCompetitor = FXCollections.observableArrayList(); - private ObservableList secondCompetitor = FXCollections.observableArrayList(); - private ObservableList thirdCompetitor = FXCollections.observableArrayList(); - private ObservableList fourthCompetitor = FXCollections.observableArrayList(); - private ObservableList fifthCompetitor = FXCollections.observableArrayList(); - private ObservableList sixthCompetitor = FXCollections.observableArrayList(); - private ObservableList seventhCompetitor = FXCollections.observableArrayList(); - private ObservableList eighthCompetitor = FXCollections.observableArrayList(); - private List imageViews = new ArrayList<>(); - private List listViews; + private List