diff --git a/src/main/java/seng302/model/ClientYacht.java b/src/main/java/seng302/model/ClientYacht.java index 564754b0..ff544482 100644 --- a/src/main/java/seng302/model/ClientYacht.java +++ b/src/main/java/seng302/model/ClientYacht.java @@ -40,7 +40,7 @@ public class ClientYacht extends Observable { private String country; private Long estimateTimeAtFinish; - private Boolean sailIn = false; + private Boolean sailIn = true; private Integer currentMarkSeqID = 0; private Long markRoundTime; private Long timeTillNext; diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java index 16c17595..22559ce8 100644 --- a/src/main/java/seng302/visualiser/GameClient.java +++ b/src/main/java/seng302/visualiser/GameClient.java @@ -365,14 +365,15 @@ public class GameClient { socketThread.sendBoatAction(BoatAction.TACK_GYBE); break; //TODO Allow a zoom in and zoom out methods case Z: // zoom in - System.out.println("Zoom in"); + raceView.getGameView().zoomIn(); break; case X: // zoom out - System.out.println("Zoom out"); + raceView.getGameView().zoomOut(); 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) diff --git a/src/main/java/seng302/visualiser/GameView.java b/src/main/java/seng302/visualiser/GameView.java index cf8ecd95..de4e9e8d 100644 --- a/src/main/java/seng302/visualiser/GameView.java +++ b/src/main/java/seng302/visualiser/GameView.java @@ -71,6 +71,7 @@ public class GameView extends Pane { private Map boatObjects = new HashMap<>(); private Map annotations = new HashMap<>(); private ObservableList gameObjects; + private BoatObject selectedBoat = null; private Group annotationsGroup = new Group(); private Group wakesGroup = new Group(); private Group boatObjectGroup = new Group(); @@ -93,18 +94,18 @@ public class GameView extends Pane { double scaleFactor = 1; public void zoomOut() { - scaleFactor = 0.95; - for (Node child : getChildren()) { - child.setScaleX(child.getScaleX() * scaleFactor); - child.setScaleY(child.getScaleY() * scaleFactor); + scaleFactor = 0.1; + if (this.getScaleX() > 0.5) { + this.setScaleX(this.getScaleX() - scaleFactor); + this.setScaleY(this.getScaleY() - scaleFactor); } } public void zoomIn() { - scaleFactor = 1.05; - for (Node child : getChildren()) { - child.setScaleX(child.getScaleX() * scaleFactor); - child.setScaleY(child.getScaleY() * scaleFactor); + scaleFactor = 0.10; + if (this.getScaleX() < 2.5) { + this.setScaleX(this.getScaleX() + scaleFactor); + this.setScaleY(this.getScaleY() + scaleFactor); } } @@ -113,14 +114,25 @@ public class GameView extends Pane { VERTICAL } - public GameView() { + + private void trackBoat() { + if (selectedBoat != null) { + double x = selectedBoat.getBoatLayoutX(); + double y = selectedBoat.getBoatLayoutY(); + double displacementX = this.getWidth(); + double displacementY = this.getHeight(); + this.setLayoutX((-x + (displacementX / 2.0)) * this.getScaleX()); + this.setLayoutY((-y + (displacementY / 2.0)) * this.getScaleY()); + } else { + this.setLayoutX(0); + this.setLayoutY(0); + } + } + + public GameView () { gameObjects = this.getChildren(); // create image view for map, bind panel size to image gameObjects.add(mapImage); - fpsDisplay.setLayoutX(5); - fpsDisplay.setLayoutY(20); - fpsDisplay.setStrokeWidth(2); - gameObjects.add(fpsDisplay); gameObjects.add(raceBorder); gameObjects.add(markers); initializeTimer(); @@ -138,6 +150,7 @@ public class GameView extends Pane { @Override public void handle(long now) { + trackBoat(); if (lastTime == 0) { lastTime = now; } else { @@ -161,9 +174,7 @@ public class GameView extends Pane { lastTime = now; } } -// Platform.runLater(() -> - boatObjects.forEach((boat, boatObject) -> boatObject.updateLocation()); -// ); + boatObjects.forEach((boat, boatObject) -> boatObject.updateLocation()); } }; } @@ -343,6 +354,22 @@ public class GameView extends Pane { // drawGoogleMap(); } + private void setSelectedBoat(BoatObject bo, Boolean isSelected) { + if (this.selectedBoat == bo && !isSelected) { + this.selectedBoat = null; + boatObjects.forEach((boat, group) -> + group.setIsSelected(false) + ); + } else if (isSelected) { + this.selectedBoat = bo; + for (BoatObject group : boatObjects.values()) { + if (group != bo) { + group.setIsSelected(false); + } + } + } + } + /** * Draws all the boats. * @param clientYachts The yachts to set in the race @@ -353,6 +380,7 @@ public class GameView extends Pane { for (ClientYacht clientYacht : clientYachts) { Paint colour = Colors.getColor(); newBoat = new BoatObject(); + newBoat.addSelectedBoatListener(this::setSelectedBoat); newBoat.setFill(colour); boatObjects.put(clientYacht, newBoat); createAndBindAnnotationBox(clientYacht, colour); @@ -365,9 +393,6 @@ public class GameView extends Pane { BoatObject bo = boatObjects.get(boat); Point2D p2d = findScaledXY(lat, lon); bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir); -// annotations.get(boat).setLayoutX(p2d.getX()); -// annotations.get(boat).setLayoutY(p2d.getY()); -// annotations.get(boat).setLocation(100d, 100d); annotations.get(boat).setLocation(p2d.getX(), p2d.getY()); bo.setTrajectory( heading, @@ -630,6 +655,7 @@ public class GameView extends Pane { public void setBoatAsPlayer (ClientYacht playerYacht) { this.playerYacht = playerYacht; + playerYacht.toggleSail(); boatObjects.get(playerYacht).setAsPlayer(); annotations.get(playerYacht).addAnnotation( "velocity", @@ -679,4 +705,9 @@ public class GameView extends Pane { timeline.setOnFinished(event -> gameObjects.remove(circle)); }); } + + public void setFrameRateFXText(Text fpsDisplay) { + this.fpsDisplay = null; + this.fpsDisplay = fpsDisplay; + } } diff --git a/src/main/java/seng302/visualiser/controllers/RaceViewController.java b/src/main/java/seng302/visualiser/controllers/RaceViewController.java index bdc2687c..a4d2142b 100644 --- a/src/main/java/seng302/visualiser/controllers/RaceViewController.java +++ b/src/main/java/seng302/visualiser/controllers/RaceViewController.java @@ -71,7 +71,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel private Button selectAnnotationBtn; @FXML private ComboBox yachtSelectionComboBox; - + @FXML + private Text fpsDisplay; //Race Data private Map participants; private Map markers; @@ -115,11 +116,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel initialiseSparkLine(); gameView = new GameView(); - Platform.runLater(() -> contentAnchorPane.getChildren().add(gameView)); - gameView.setBoats(new ArrayList<>(participants.values())); - gameView.updateBorder(raceData.getCourseLimit()); - gameView.updateCourse( - new ArrayList<>(raceData.getCompoundMarks().values()), raceData.getMarkSequence() + gameView.setFrameRateFXText(fpsDisplay); + Platform.runLater(() -> contentAnchorPane.getChildren().add(0, gameView)); + gameView.setBoats(new ArrayList<>(participants.values())); + gameView.updateBorder(raceData.getCourseLimit()); + gameView.updateCourse( + new ArrayList<>(raceData.getCompoundMarks().values()), raceData.getMarkSequence() ); gameView.setBoatAsPlayer(player); gameView.startRace(); diff --git a/src/main/java/seng302/visualiser/fxObjects/AnnotationBox.java b/src/main/java/seng302/visualiser/fxObjects/AnnotationBox.java index cdaf329e..69c9e836 100644 --- a/src/main/java/seng302/visualiser/fxObjects/AnnotationBox.java +++ b/src/main/java/seng302/visualiser/fxObjects/AnnotationBox.java @@ -95,7 +95,7 @@ public class AnnotationBox extends Group { background.setStroke(theme); background.setStrokeWidth(2); background.setCache(true); - background.setCacheHint(CacheHint.SPEED); + background.setCacheHint(CacheHint.SCALE); this.getChildren().add(background); } @@ -213,7 +213,7 @@ public class AnnotationBox extends Group { Text text = new Text(); text.setFill(theme); text.setStrokeWidth(2); - text.setCacheHint(CacheHint.SPEED); +// text.setCacheHint(CacheHint.QUALITY); text.setCache(true); return text; } diff --git a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java index b04fcaae..dc27a279 100644 --- a/src/main/java/seng302/visualiser/fxObjects/BoatObject.java +++ b/src/main/java/seng302/visualiser/fxObjects/BoatObject.java @@ -1,9 +1,9 @@ package seng302.visualiser.fxObjects; import java.util.ArrayList; +import java.util.List; import javafx.application.Platform; import javafx.geometry.Point2D; -import javafx.scene.CacheHint; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.paint.Color; @@ -23,6 +23,12 @@ import javafx.scene.transform.Rotate; */ public class BoatObject extends Group { + @FunctionalInterface + public interface SelectedBoatListener { + + void notifySelected(BoatObject boatObject, Boolean isSelected); + } + //Constants for drawing private static final double BOAT_HEIGHT = 15d; private static final double BOAT_WIDTH = 10d; @@ -41,9 +47,11 @@ public class BoatObject extends Group { private double distanceTravelled, lastRotation; private Point2D lastPoint; private Paint colour = Color.BLACK; - private Boolean isSelected, destinationSet; //All boats are initialised as selected + private Boolean isSelected = false, destinationSet; //All boats are initialised as selected private boolean isPlayer = false; + private List selectedBoatListenerListeners = new ArrayList<>(); + /** * Creates a BoatGroup with the default triangular boat polygon. */ @@ -85,7 +93,7 @@ public class BoatObject extends Group { }); boatPoly.setOnMouseClicked(event -> setIsSelected(!isSelected)); boatPoly.setCache(true); - boatPoly.setCacheHint(CacheHint.SPEED); +// boatPoly.setCacheHint(CacheHint.SPEED); // annotationBox = new AnnotationBox(); // annotationBox.setFill(colour); @@ -287,6 +295,7 @@ public class BoatObject extends Group { // } public void setIsSelected(Boolean isSelected) { + updateListener(isSelected); this.isSelected = isSelected; setLineGroupVisible(isSelected); setWakeVisible(isSelected); @@ -365,6 +374,10 @@ public class BoatObject extends Group { lastHeading = heading; } + public Boolean getSelected() { + return isSelected; + } + public void setTrajectory(double heading, double velocity, double scaleFactorX, double scaleFactorY) { // wake.setRotation(lastHeading - heading, velocity); // rotateTo(heading); @@ -372,4 +385,14 @@ public class BoatObject extends Group { // yVelocity = Math.sin(Math.toRadians(heading)) * velocity * scaleFactorY; lastHeading = heading; } + + private void updateListener(Boolean isSelected) { + for (SelectedBoatListener sbl : selectedBoatListenerListeners) { + sbl.notifySelected(this, isSelected); + } + } + + public void addSelectedBoatListener(SelectedBoatListener sbl) { + selectedBoatListenerListeners.add(sbl); + } } \ No newline at end of file diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml index e13853d1..d00f0099 100644 --- a/src/main/resources/views/RaceView.fxml +++ b/src/main/resources/views/RaceView.fxml @@ -1,5 +1,11 @@ + + + + + + @@ -17,40 +23,60 @@ - - - - - - - - - - - - - - + + + + diff --git a/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java b/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java index be2f7a46..5d4e4df4 100644 --- a/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java +++ b/src/test/java/seng302/visualiser/map/BoatSailAnimationToggleTest.java @@ -21,9 +21,9 @@ public class BoatSailAnimationToggleTest { @Test public void sailToggleTest() throws Exception { - assertFalse(yacht.getSailIn()); - yacht.toggleSail(); assertTrue(yacht.getSailIn()); + yacht.toggleSail(); + assertFalse(yacht.getSailIn()); } }