diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java
index c5317fa6..be7039fa 100644
--- a/src/main/java/seng302/gameServer/GameState.java
+++ b/src/main/java/seng302/gameServer/GameState.java
@@ -47,6 +47,7 @@ public class GameState implements Runnable {
private static final Double BOUNCE_DISTANCE_MARK = 20.0;
public static final Double BOUNCE_DISTANCE_YACHT = 30.0;
private static final Double COLLISION_VELOCITY_PENALTY = 0.3;
+ private static final Integer VELOCITY_BOOST_MULTIPLIER = 2;
private static Long previousUpdateTime;
public static Double windDirection;
@@ -453,8 +454,7 @@ public class GameState implements Runnable {
Double maxBoatSpeed = GeoUtility.knotsToMMS(boatSpeedInKnots) * speedMultiplier;
if (yacht.getPowerUp() != null) {
if (yacht.getPowerUp().equals(TokenType.BOOST)) {
- // TODO: 11/09/17 wmu16 CHANGE THIS TO MAGIC NUMBER
- maxBoatSpeed *= 2;
+ maxBoatSpeed *= VELOCITY_BOOST_MULTIPLIER;
}
}
diff --git a/src/main/java/seng302/model/ClientYacht.java b/src/main/java/seng302/model/ClientYacht.java
index 89715852..b1996333 100644
--- a/src/main/java/seng302/model/ClientYacht.java
+++ b/src/main/java/seng302/model/ClientYacht.java
@@ -12,9 +12,13 @@ import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
+import javafx.beans.value.ObservableObjectValue;
+import javafx.collections.FXCollections;
import javafx.scene.paint.Color;
+import jdk.nashorn.internal.objects.annotations.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import seng302.model.token.TokenType;
/**
* Yacht class for the racing boat.
Class created to store more variables (eg. boat statuses)
@@ -34,6 +38,12 @@ public class ClientYacht extends Observable {
void notifyRounding(ClientYacht yacht, int legNumber);
}
+ @FunctionalInterface
+ public interface PowerUpListener {
+
+ void notifyPowerUp(ClientYacht yacht, TokenType tokenType);
+ }
+
private Logger logger = LoggerFactory.getLogger(ClientYacht.class);
@@ -44,6 +54,7 @@ public class ClientYacht extends Observable {
private String boatName;
private String country;
private Integer position;
+ private TokenType powerUp;
private Long estimateTimeAtFinish;
private Boolean sailIn = false;
@@ -58,6 +69,7 @@ public class ClientYacht extends Observable {
private List locationListeners = new ArrayList<>();
private List markRoundingListeners = new ArrayList<>();
+ private List powerUpListeners = new ArrayList<>();
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
@@ -199,6 +211,17 @@ public class ClientYacht extends Observable {
this.position = position;
}
+ public void setPowerUp(TokenType tokenType) {
+ this.powerUp = tokenType;
+ for (PowerUpListener listener : powerUpListeners) {
+ listener.notifyPowerUp(this, tokenType);
+ }
+ }
+
+ public TokenType getPowerUp() {
+ return powerUp;
+ }
+
public void toggleSail() {
sailIn = !sailIn;
}
@@ -268,6 +291,10 @@ public class ClientYacht extends Observable {
markRoundingListeners.add(listener);
}
+ public void addPowerUpListener(PowerUpListener listener) {
+ powerUpListeners.add(listener);
+ }
+
public void removeMarkRoundingListener(MarkRoundingListener listener) {
markRoundingListeners.remove(listener);
}
diff --git a/src/main/java/seng302/visualiser/GameClient.java b/src/main/java/seng302/visualiser/GameClient.java
index 5cab5040..10a682fa 100644
--- a/src/main/java/seng302/visualiser/GameClient.java
+++ b/src/main/java/seng302/visualiser/GameClient.java
@@ -37,6 +37,7 @@ import seng302.model.stream.parser.RaceStatusData;
import seng302.model.stream.parser.YachtEventData;
import seng302.model.stream.xml.parser.RaceXMLData;
import seng302.model.stream.xml.parser.RegattaXMLData;
+import seng302.model.token.TokenType;
import seng302.utilities.Sounds;
import seng302.utilities.StreamParser;
import seng302.utilities.XMLGenerator;
@@ -245,7 +246,7 @@ public class GameClient {
break;
case YACHT_EVENT_CODE:
- displayYachtEvent(StreamParser.extractYachtEventCode(packet));
+ processYachtEvent(StreamParser.extractYachtEventCode(packet));
break;
case CHATTER_TEXT:
@@ -408,19 +409,25 @@ public class GameClient {
*
* @param yachtEventData The YachtEvent data packet
*/
- private void displayYachtEvent(YachtEventData yachtEventData) {
+ private void processYachtEvent(YachtEventData yachtEventData) {
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
showCollisionAlert(yachtEventData);
- } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_VELOCITY.getCode()) {
- showPickUp(yachtEventData);
- } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_BUMPER.getCode()) {
- showPickUp(yachtEventData);
- } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_HANDLING.getCode()) {
- showPickUp(yachtEventData);
- } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_RANDOM.getCode()) {
- showPickUp(yachtEventData);
- } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_WIND_WALKER.getCode()) {
- showPickUp(yachtEventData);
+ } else {
+ TokenType tokenType = null;
+ if (yachtEventData.getEventId() == YachtEventType.TOKEN_VELOCITY.getCode()) {
+ tokenType = TokenType.BOOST;
+ } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_BUMPER.getCode()) {
+ tokenType = TokenType.BUMPER;
+ } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_HANDLING.getCode()) {
+ tokenType = TokenType.HANDLING;
+ } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_RANDOM.getCode()) {
+ tokenType = TokenType.RANDOM;
+ } else if (yachtEventData.getEventId() == YachtEventType.TOKEN_WIND_WALKER.getCode()) {
+ tokenType = TokenType.WIND_WALKER;
+ }
+
+ showTokenPickUp(tokenType);
+ allBoatsMap.get(yachtEventData.getSubjectId().intValue()).setPowerUp(tokenType);
}
}
@@ -437,7 +444,7 @@ public class GameClient {
}
// TODO: 11/09/17 wmu16 - Add in functionality to viually indicate a pickup to a user
- private void showPickUp(YachtEventData yachtEventData) {
+ private void showTokenPickUp(TokenType tokenType) {
Sounds.playTokenPickupSound();
}
diff --git a/src/main/java/seng302/visualiser/controllers/RaceViewController.java b/src/main/java/seng302/visualiser/controllers/RaceViewController.java
index 2ac06dfb..15c3d8ec 100644
--- a/src/main/java/seng302/visualiser/controllers/RaceViewController.java
+++ b/src/main/java/seng302/visualiser/controllers/RaceViewController.java
@@ -20,6 +20,8 @@ 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.Scene;
import javafx.scene.SubScene;
import javafx.scene.chart.LineChart;
@@ -47,10 +49,12 @@ import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import seng302.model.ClientYacht;
+import seng302.model.ClientYacht.PowerUpListener;
import seng302.model.RaceState;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
import seng302.model.stream.xml.parser.RaceXMLData;
+import seng302.model.token.TokenType;
import seng302.utilities.Sounds;
import seng302.visualiser.GameView3D;
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
@@ -60,6 +64,8 @@ import seng302.visualiser.controllers.dialogs.FinishDialogController;
import seng302.visualiser.fxObjects.ChatHistory;
import seng302.visualiser.fxObjects.assets_2D.WindArrow;
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
+import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
+import seng302.visualiser.fxObjects.assets_3D.ModelType;
/**
* Controller class that manages the display of a race
@@ -110,6 +116,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
private Label windSpeedLabel;
@FXML
private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
+ @FXML
+ private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon;
//Race Data
private Map participants;
@@ -222,6 +230,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
return finishScreenDialog;
}
+
public void loadRace (
Map participants, RaceXMLData raceData, RaceState raceState,
ClientYacht player) {
@@ -241,6 +250,25 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
}
});
+ player.addPowerUpListener((yacht, tokenType) -> {
+ if (yacht == player) {
+ switch (tokenType) {
+ case BOOST:
+ velocityIcon.setVisible(true);
+ break;
+ case HANDLING:
+ handlingIcon.setVisible(true);
+ break;
+ case WIND_WALKER:
+ windWalkerIcon.setVisible(true);
+ break;
+ case BUMPER:
+ bumperIcon.setVisible(true);
+ break;
+ }
+ }
+ });
+
updateOrder(raceState.getPlayerPositions());
gameView = new GameView3D();
// gameView.setFrameRateFXText(fpsDisplay);
@@ -279,6 +307,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
});
}
+
/**
* The important annotations have been changed, update this view
*
diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml
index a2c22e09..03728bde 100644
--- a/src/main/resources/views/RaceView.fxml
+++ b/src/main/resources/views/RaceView.fxml
@@ -1,5 +1,14 @@
+
+
+
+
+
+
+
+
+
@@ -14,6 +23,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+