mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
Merge branch 'develop' into loading_screens
# Conflicts: # src/main/resources/views/RaceView.fxml
This commit is contained in:
@@ -10,15 +10,16 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Alert.AlertType;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Pair;
|
||||
import seng302.gameServer.GameStages;
|
||||
import seng302.gameServer.GameState;
|
||||
@@ -39,6 +40,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;
|
||||
@@ -46,6 +48,7 @@ import seng302.utilities.XMLParser;
|
||||
import seng302.visualiser.controllers.LobbyController;
|
||||
import seng302.visualiser.controllers.RaceViewController;
|
||||
import seng302.visualiser.controllers.ViewManager;
|
||||
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
||||
|
||||
/**
|
||||
* This class is a client side instance of a yacht racing game in JavaFX. The game is instantiated
|
||||
@@ -169,10 +172,12 @@ public class GameClient {
|
||||
|
||||
private void showConnectionError (String message) {
|
||||
Platform.runLater(() -> {
|
||||
Alert alert = new Alert(AlertType.ERROR);
|
||||
alert.setHeaderText("Connection Error");
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
PopupDialogController controller = ViewManager.getInstance().showPopupDialog();
|
||||
controller.setHeader("Oops");
|
||||
controller.setContent(message);
|
||||
controller.setOptionButtonText("GO HOME");
|
||||
controller
|
||||
.setOptionButtonEventHandler(event -> ViewManager.getInstance().goToStartView());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -250,12 +255,7 @@ public class GameClient {
|
||||
break;
|
||||
|
||||
case YACHT_EVENT_CODE:
|
||||
YachtEventData yachtEventData = StreamParser.extractYachtEventCode(packet);
|
||||
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
|
||||
showCollisionAlert(StreamParser.extractYachtEventCode(packet));
|
||||
} else if (yachtEventData.getEventId() == YachtEventType.TOKEN.getCode()) {
|
||||
showPickUp();
|
||||
}
|
||||
processYachtEvent(StreamParser.extractYachtEventCode(packet));
|
||||
break;
|
||||
|
||||
case CHATTER_TEXT:
|
||||
@@ -415,21 +415,66 @@ public class GameClient {
|
||||
return courseData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appropriately displays the event client side given the YachtEventCode (collision / token..)
|
||||
*
|
||||
* @param yachtEventData The YachtEvent data packet
|
||||
*/
|
||||
private void processYachtEvent(YachtEventData yachtEventData) {
|
||||
ClientYacht thisYacht = allBoatsMap.get(yachtEventData.getSubjectId().intValue());
|
||||
|
||||
if (yachtEventData.getEventId() == YachtEventType.COLLISION.getCode()) {
|
||||
showCollisionAlert(thisYacht);
|
||||
} else if (yachtEventData.getEventId() == YachtEventType.POWER_DOWN.getCode()) {
|
||||
thisYacht.powerDown();
|
||||
Sounds.playTokenPickupSound(); // TODO: 23/09/17 This should be power down sound
|
||||
} else if (yachtEventData.getEventId() == YachtEventType.BUMPER_CRASH.getCode()) {
|
||||
showDisableAlert(thisYacht);
|
||||
} else { //Else all token pickup types
|
||||
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;
|
||||
}
|
||||
|
||||
Sounds.playTokenPickupSound();
|
||||
thisYacht.setPowerUp(tokenType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turns a disabled boat black until the bumper affect wears off
|
||||
*
|
||||
* @param yacht The yacht to show as disabled
|
||||
*/
|
||||
private void showDisableAlert(ClientYacht yacht) {
|
||||
Color originalColor = yacht.getColour();
|
||||
yacht.setColour(Color.BLACK);
|
||||
|
||||
Timer disableTimer = new Timer("Disable Timer");
|
||||
disableTimer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
yacht.setColour(originalColor);
|
||||
}
|
||||
}, GameState.BUMPER_DISABLE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells race view to show a collision animation.
|
||||
*/
|
||||
private void showCollisionAlert(YachtEventData yachtEventData) {
|
||||
private void showCollisionAlert(ClientYacht yacht) {
|
||||
Sounds.playCrashSound();
|
||||
raceState.storeCollision(
|
||||
allBoatsMap.get(
|
||||
yachtEventData.getSubjectId().intValue()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: 11/09/17 wmu16 - Add in functionality to viually indicate a pickup to a user
|
||||
private void showPickUp() {
|
||||
Sounds.playTokenPickupSound();
|
||||
raceState.storeCollision(yacht);
|
||||
}
|
||||
|
||||
private void formatAndSendChatMessage(String rawChat) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package seng302.visualiser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -9,6 +10,7 @@ import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Camera;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
@@ -21,16 +23,23 @@ import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.gameServer.messages.RoundingSide;
|
||||
import seng302.model.ClientYacht;
|
||||
import seng302.model.GameKeyBind;
|
||||
import seng302.model.GeoPoint;
|
||||
import seng302.model.KeyAction;
|
||||
import seng302.model.Limit;
|
||||
import seng302.model.mark.CompoundMark;
|
||||
import seng302.model.mark.Corner;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.token.Token;
|
||||
import seng302.model.token.TokenType;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.cameras.ChaseCamera;
|
||||
import seng302.visualiser.cameras.IsometricCamera;
|
||||
import seng302.visualiser.cameras.RaceCamera;
|
||||
import seng302.visualiser.cameras.TopDownCamera;
|
||||
import seng302.visualiser.controllers.ViewManager;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
import seng302.visualiser.fxObjects.assets_3D.Marker3D;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||
@@ -42,18 +51,19 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
public class GameView3D {
|
||||
|
||||
|
||||
private final double FOV = 60;
|
||||
private final double DEFAULT_CAMERA_DEPTH = -125;
|
||||
private final double DEFAULT_CAMERA_X = 0;
|
||||
private final double DEFAULT_CAMERA_Y = 155;
|
||||
|
||||
private Group root3D;
|
||||
private SubScene view;
|
||||
// ParallelCamera camera;
|
||||
private PerspectiveCamera camera;
|
||||
private Group gameObjects;
|
||||
|
||||
// Cameras
|
||||
private PerspectiveCamera isometricCam;
|
||||
private PerspectiveCamera topDownCam;
|
||||
private PerspectiveCamera chaseCam;
|
||||
|
||||
private double bufferSize = 0;
|
||||
private double canvasWidth = 200;
|
||||
private double canvasHeight = 200;
|
||||
@@ -88,20 +98,22 @@ public class GameView3D {
|
||||
}
|
||||
|
||||
public GameView3D () {
|
||||
camera = new PerspectiveCamera(true);
|
||||
camera.getTransforms().addAll(
|
||||
new Translate(DEFAULT_CAMERA_X,DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH)
|
||||
);
|
||||
camera.setFarClip(600);
|
||||
camera.setNearClip(0.1);
|
||||
camera.setFieldOfView(FOV);
|
||||
isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y);
|
||||
topDownCam = new TopDownCamera();
|
||||
chaseCam = new ChaseCamera();
|
||||
|
||||
for (PerspectiveCamera pc : Arrays.asList(isometricCam, topDownCam, chaseCam)) {
|
||||
pc.setFarClip(600);
|
||||
pc.setNearClip(0.1);
|
||||
pc.setFieldOfView(FOV);
|
||||
}
|
||||
|
||||
gameObjects = new Group();
|
||||
root3D = new Group(camera, gameObjects);
|
||||
root3D = new Group(isometricCam, gameObjects);
|
||||
view = new SubScene(
|
||||
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
||||
);
|
||||
view.setCamera(camera);
|
||||
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
|
||||
view.setCamera(isometricCam);
|
||||
|
||||
gameObjects.getChildren().addAll(
|
||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
@@ -336,7 +348,6 @@ public class GameView3D {
|
||||
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
||||
*/
|
||||
private double scaleRaceExtremities() {
|
||||
|
||||
double vertAngle = Math.abs(
|
||||
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
||||
);
|
||||
@@ -404,37 +415,44 @@ public class GameView3D {
|
||||
}
|
||||
|
||||
public void cameraMovement(KeyEvent event) {
|
||||
switch (event.getCode()) {
|
||||
case NUMPAD8:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case NUMPAD2:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(1,0,0)));
|
||||
break;
|
||||
case NUMPAD4:
|
||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case NUMPAD6:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case Z:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, 1.5));
|
||||
break;
|
||||
case X:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, -1.5));
|
||||
break;
|
||||
case W:
|
||||
camera.getTransforms().addAll(new Translate(0, -1, 0));
|
||||
break;
|
||||
case S:
|
||||
camera.getTransforms().addAll(new Translate(0, 1, 0));
|
||||
break;
|
||||
case A:
|
||||
camera.getTransforms().addAll(new Translate(-1, 0, 0));
|
||||
break;
|
||||
case D:
|
||||
camera.getTransforms().addAll(new Translate(1, 0, 0));
|
||||
break;
|
||||
GameKeyBind keyBinds = GameKeyBind.getInstance();
|
||||
KeyAction keyPressed = keyBinds.getKeyAction(event.getCode());
|
||||
if (keyPressed != null) {
|
||||
switch (keyPressed) {
|
||||
case ZOOM_IN:
|
||||
((RaceCamera) view.getCamera()).zoomIn();
|
||||
break;
|
||||
case ZOOM_OUT:
|
||||
((RaceCamera) view.getCamera()).zoomOut();
|
||||
break;
|
||||
case FORWARD:
|
||||
((RaceCamera) view.getCamera()).panUp();
|
||||
break;
|
||||
case BACKWARD:
|
||||
((RaceCamera) view.getCamera()).panDown();
|
||||
break;
|
||||
case LEFT:
|
||||
((RaceCamera) view.getCamera()).panLeft();
|
||||
break;
|
||||
case RIGHT:
|
||||
((RaceCamera) view.getCamera()).panRight();
|
||||
break;
|
||||
case VIEW:
|
||||
toggleCamera();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void toggleCamera() {
|
||||
Camera currCamera = view.getCamera();
|
||||
|
||||
if (currCamera.equals(isometricCam)) {
|
||||
view.setCamera(topDownCam);
|
||||
} else if (currCamera.equals(topDownCam)) {
|
||||
view.setCamera(chaseCam);
|
||||
} else {
|
||||
view.setCamera(isometricCam);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,11 +484,14 @@ public class GameView3D {
|
||||
wakesGroup.getChildren().add(newBoat.getWake());
|
||||
wakes.add(newBoat.getWake());
|
||||
boatObjectGroup.getChildren().add(newBoat);
|
||||
clientYacht.addLocationListener((boat, lat, lon, heading, sailIn, velocity) -> {
|
||||
BoatObject bo = boatObjects.get(boat);
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
||||
});
|
||||
clientYacht.addLocationListener(this::updateBoatLocation);
|
||||
clientYacht.addColorChangeListener(this::updateBoatColor);
|
||||
|
||||
if (clientYacht.getSourceId().equals(
|
||||
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
|
||||
((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
|
||||
((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
|
||||
}
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
gameObjects.getChildren().addAll(wakes);
|
||||
@@ -482,6 +503,23 @@ public class GameView3D {
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the boatObjects color with that of the clientYachts object. Used in notification from
|
||||
* a listener on this attribute in clientYacht to re paint the boat mesh
|
||||
*
|
||||
* @param clientYacht The yacht to update the colour for
|
||||
*/
|
||||
private void updateBoatColor(ClientYacht clientYacht) {
|
||||
boatObjects.get(clientYacht).setFill(clientYacht.getColour());
|
||||
}
|
||||
|
||||
private void updateBoatLocation(ClientYacht boat, Double lat, Double lon, Double heading,
|
||||
Boolean sailIn, Double velocity) {
|
||||
BoatObject bo = boatObjects.get(boat);
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a border to the GameView and rescales to the size of the border, does not rescale if a
|
||||
* border already exists. Assumes the border is larger than the course.
|
||||
@@ -557,7 +595,27 @@ public class GameView3D {
|
||||
mapTokens = new ArrayList<>();
|
||||
for (Token token : newTokens) {
|
||||
Point2D location = findScaledXY(token.getLat(), token.getLng());
|
||||
Node tokenObject = ModelFactory.importModel(ModelType.VELOCITY_PICKUP).getAssets();
|
||||
|
||||
ModelType modelType = null;
|
||||
switch (token.getTokenType()) {
|
||||
case BOOST:
|
||||
modelType = ModelType.VELOCITY_PICKUP;
|
||||
break;
|
||||
case HANDLING:
|
||||
modelType = ModelType.HANDLING_PICKUP;
|
||||
break;
|
||||
case BUMPER:
|
||||
modelType = ModelType.BUMPER_PICKUP;
|
||||
break;
|
||||
case RANDOM:
|
||||
modelType = ModelType.RANDOM_PICKUP;
|
||||
break;
|
||||
case WIND_WALKER:
|
||||
modelType = ModelType.WIND_WALKER_PICKUP;
|
||||
break;
|
||||
}
|
||||
|
||||
Node tokenObject = ModelFactory.importModel(modelType).getAssets();
|
||||
tokenObject.setLayoutX(location.getX());
|
||||
tokenObject.setLayoutY(location.getY());
|
||||
mapTokens.add(tokenObject);
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
package seng302.visualiser.cameras;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Transform;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
|
||||
|
||||
public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
|
||||
|
||||
private final Double VERTICAL_PAN_LIMIT = 20.0;
|
||||
private final Double NEAR_ZOOM_LIMIT = -15.0;
|
||||
private final Double FAR_ZOOM_LIMIT = -125.0;
|
||||
|
||||
private final Double ZOOM_STEP = 2.5;
|
||||
private final Double PAN_STEP = 2.5;
|
||||
|
||||
private ObservableList<Transform> transforms;
|
||||
private BoatObject playerBoat;
|
||||
|
||||
private Double zoomFactor;
|
||||
private Double horizontalPan;
|
||||
private Double verticalPan;
|
||||
|
||||
|
||||
public ChaseCamera() {
|
||||
super(true);
|
||||
transforms = this.getTransforms();
|
||||
|
||||
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||
this.horizontalPan = 0.0;
|
||||
this.verticalPan = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a player boat object to observe and update the camera with.
|
||||
*
|
||||
* @param playerBoat The player boat to be observed.
|
||||
*/
|
||||
public void setPlayerBoat(BoatObject playerBoat) {
|
||||
this.playerBoat = playerBoat;
|
||||
|
||||
for (DoubleProperty o : Arrays
|
||||
.asList(playerBoat.getRotationProperty(), playerBoat.layoutYProperty(),
|
||||
playerBoat.layoutXProperty())) {
|
||||
o.addListener((obs, oldVal, newVal) -> repositionCamera());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||
*/
|
||||
private void repositionCamera() {
|
||||
transforms.clear();
|
||||
transforms.addAll(
|
||||
new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), 0),
|
||||
new Rotate(playerBoat.getRotationProperty().getValue() + horizontalPan,
|
||||
new Point3D(0, 0, 1)),
|
||||
new Rotate(60 + verticalPan, new Point3D(1, 0, 0)),
|
||||
new Translate(0, 0, zoomFactor)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustZoomFactor(Double adjustment) {
|
||||
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||
zoomFactor = zoomFactor + adjustment;
|
||||
repositionCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Vertical Panning of the Camera
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustVerticalPan(Double adjustment) {
|
||||
if (verticalPan + adjustment >= -VERTICAL_PAN_LIMIT
|
||||
&& verticalPan + adjustment <= VERTICAL_PAN_LIMIT) {
|
||||
verticalPan += adjustment;
|
||||
repositionCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Horizontal Panning of the Camera.
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustHorizontalPan(Double adjustment) {
|
||||
this.horizontalPan += adjustment;
|
||||
repositionCamera();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomIn() {
|
||||
adjustZoomFactor(ZOOM_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomOut() {
|
||||
adjustZoomFactor(-ZOOM_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panLeft() {
|
||||
adjustHorizontalPan(-PAN_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panRight() {
|
||||
adjustHorizontalPan(PAN_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panUp() {
|
||||
adjustVerticalPan(-PAN_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panDown() {
|
||||
adjustVerticalPan(PAN_STEP);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package seng302.visualiser.cameras;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Transform;
|
||||
import javafx.scene.transform.Translate;
|
||||
|
||||
public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
|
||||
|
||||
private final Double MIN_X = -120.0;
|
||||
private final Double MAX_X = 125.0;
|
||||
|
||||
private final Double MIN_Y = 40.0;
|
||||
private final Double MAX_Y = 170.0;
|
||||
|
||||
private final Double PAN_LIMIT = 160.0;
|
||||
private final Double NEAR_ZOOM_LIMIT = -50.0;
|
||||
private final Double FAR_ZOOM_LIMIT = -160.0;
|
||||
|
||||
private Double horizontalPan;
|
||||
private Double verticalPan;
|
||||
private Double zoomFactor;
|
||||
|
||||
private ObservableList<Transform> transforms;
|
||||
|
||||
public IsometricCamera(Double cameraStartX, Double cameraStartY) {
|
||||
super(true);
|
||||
transforms = this.getTransforms();
|
||||
|
||||
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||
horizontalPan = cameraStartX;
|
||||
verticalPan = cameraStartY;
|
||||
|
||||
updateCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||
*/
|
||||
private void updateCamera() {
|
||||
transforms.clear();
|
||||
transforms.addAll(
|
||||
new Translate(horizontalPan, verticalPan, zoomFactor),
|
||||
new Rotate(30, new Point3D(1, 0, 0))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||
*
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustZoomFactor(Double adjustment) {
|
||||
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||
zoomFactor = zoomFactor + adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Vertical Panning of the Camera
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustVerticalPan(Double adjustment) {
|
||||
if (verticalPan + adjustment >= MIN_Y && verticalPan + adjustment <= MAX_Y) {
|
||||
verticalPan += adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Horizontal Panning of the Camera.
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustHorizontalPan(Double adjustment) {
|
||||
if (horizontalPan + adjustment >= MIN_X && horizontalPan + adjustment <= MIN_Y) {
|
||||
this.horizontalPan += adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomIn() {
|
||||
adjustZoomFactor(-2.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomOut() {
|
||||
adjustZoomFactor(2.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panLeft() {
|
||||
adjustHorizontalPan(-2.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panRight() {
|
||||
adjustHorizontalPan(2.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panUp() {
|
||||
adjustVerticalPan(-2.5);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panDown() {
|
||||
adjustVerticalPan(2.5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package seng302.visualiser.cameras;
|
||||
|
||||
|
||||
public interface RaceCamera {
|
||||
|
||||
void zoomIn();
|
||||
|
||||
void zoomOut();
|
||||
|
||||
void panLeft();
|
||||
|
||||
void panRight();
|
||||
|
||||
void panUp();
|
||||
|
||||
void panDown();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package seng302.visualiser.cameras;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
import javafx.scene.transform.Transform;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
|
||||
public class TopDownCamera extends PerspectiveCamera implements RaceCamera {
|
||||
|
||||
private final Double PAN_LIMIT = 30.0;
|
||||
private final Double NEAR_ZOOM_LIMIT = -30.0;
|
||||
private final Double FAR_ZOOM_LIMIT = -130.0;
|
||||
private final Double ZOOM_STEP = 2.5;
|
||||
|
||||
private ObservableList<Transform> transforms;
|
||||
private BoatObject playerBoat;
|
||||
|
||||
private Double zoomFactor;
|
||||
private Double horizontalPan;
|
||||
private Double verticalPan;
|
||||
|
||||
public TopDownCamera() {
|
||||
super(true);
|
||||
transforms = this.getTransforms();
|
||||
|
||||
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
|
||||
horizontalPan = 0.0;
|
||||
verticalPan = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a player boat object to observe and update the camera with.
|
||||
*
|
||||
* @param playerBoat The player boat to be observed.
|
||||
*/
|
||||
public void setPlayerBoat(BoatObject playerBoat) {
|
||||
this.playerBoat = playerBoat;
|
||||
|
||||
for (DoubleProperty o : Arrays
|
||||
.asList(playerBoat.layoutXProperty(), playerBoat.layoutYProperty())) {
|
||||
o.addListener((obs, oldVal, newVal) -> updateCamera());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the camera to a new position after some change (Zooming or Panning)
|
||||
*/
|
||||
private void updateCamera() {
|
||||
transforms.clear();
|
||||
transforms.addAll(
|
||||
new Translate(playerBoat.getLayoutX() + horizontalPan,
|
||||
playerBoat.getLayoutY() + verticalPan, zoomFactor)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the zoom amount (camera depth) by some adjustment value
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustZoomFactor(Double adjustment) {
|
||||
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
|
||||
zoomFactor = zoomFactor + adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Vertical Panning of the Camera
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustVerticalPan(Double adjustment) {
|
||||
if (verticalPan + adjustment >= -PAN_LIMIT && verticalPan + adjustment <= PAN_LIMIT) {
|
||||
verticalPan += adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the Horizontal Panning of the Camera.
|
||||
* @param adjustment the adjustment to be made to the camera
|
||||
*/
|
||||
private void adjustHorizontalPan(Double adjustment) {
|
||||
if (horizontalPan + adjustment >= -PAN_LIMIT && horizontalPan + adjustment <= PAN_LIMIT) {
|
||||
horizontalPan += adjustment;
|
||||
updateCamera();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomIn() {
|
||||
adjustZoomFactor(ZOOM_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomOut() {
|
||||
adjustZoomFactor(-ZOOM_STEP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panLeft() {
|
||||
adjustHorizontalPan(-1.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panRight() {
|
||||
adjustHorizontalPan(1.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panUp() {
|
||||
adjustVerticalPan(-1.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void panDown() {
|
||||
adjustVerticalPan(1.0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -42,11 +44,15 @@ import javafx.scene.shape.Polyline;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import javax.swing.ImageIcon;
|
||||
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.Token;
|
||||
import seng302.model.token.TokenType;
|
||||
import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.GameView3D;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
||||
@@ -56,6 +62,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
|
||||
@@ -63,6 +71,8 @@ import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
|
||||
|
||||
private final int CHAT_LIMIT = 128;
|
||||
private static final Double ICON_BLINK_TIMEOUT_RATIO = 0.6;
|
||||
private static final Integer ICON_BLINK_PERIOD = 500;
|
||||
|
||||
@FXML
|
||||
private AnchorPane loadingScreenPane;
|
||||
@@ -110,6 +120,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
private Label windSpeedLabel;
|
||||
@FXML
|
||||
private Label positionLabel, boatSpeedLabel, boatHeadingLabel;
|
||||
@FXML
|
||||
private ImageView velocityIcon, handlingIcon, windWalkerIcon, bumperIcon, badRandomIcon;
|
||||
|
||||
//Race Data
|
||||
private Map<Integer, ClientYacht> participants;
|
||||
@@ -130,6 +142,10 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
private JFXDialog finishScreenDialog;
|
||||
private FinishDialogController finishDialogController;
|
||||
|
||||
//Icon stuff
|
||||
private Timer blinkingTimer = new Timer();
|
||||
private ImageView iconToDisplay;
|
||||
|
||||
public void initialize() {
|
||||
contentStackPane.setVisible(false);
|
||||
Image loadingImage = new Image("PP.png");
|
||||
@@ -252,6 +268,7 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void loadRace (
|
||||
Map<Integer, ClientYacht> participants, RaceXMLData raceData, RaceState raceState,
|
||||
ClientYacht player) {
|
||||
@@ -271,6 +288,9 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
}
|
||||
});
|
||||
|
||||
player.addPowerUpListener(this::displayPowerUpIcon);
|
||||
player.addPowerDownListener(this::removeIcon);
|
||||
|
||||
updateOrder(raceState.getPlayerPositions());
|
||||
gameView = new GameView3D();
|
||||
// gameView.setFrameRateFXText(fpsDisplay);
|
||||
@@ -309,6 +329,68 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the relevant icon, starts blinking it when it is close to turning off and then
|
||||
* switches it off after the tokens time out
|
||||
*
|
||||
* @param yacht The yacht only for which we are displaying the icon
|
||||
* @param tokenType The type of token, indicating what icon needs to be displayed
|
||||
*/
|
||||
private void displayPowerUpIcon(ClientYacht yacht, TokenType tokenType) {
|
||||
if (yacht == player) {
|
||||
if (iconToDisplay != null) {
|
||||
iconToDisplay.setVisible(false);
|
||||
}
|
||||
|
||||
switch (tokenType) {
|
||||
case BOOST:
|
||||
iconToDisplay = velocityIcon;
|
||||
break;
|
||||
case HANDLING:
|
||||
iconToDisplay = handlingIcon;
|
||||
break;
|
||||
case WIND_WALKER:
|
||||
iconToDisplay = windWalkerIcon;
|
||||
break;
|
||||
case BUMPER:
|
||||
iconToDisplay = bumperIcon;
|
||||
break;
|
||||
case RANDOM:
|
||||
iconToDisplay = badRandomIcon;
|
||||
break;
|
||||
default:
|
||||
iconToDisplay = velocityIcon;
|
||||
}
|
||||
|
||||
//Turn icon on
|
||||
iconToDisplay.setVisible(true);
|
||||
|
||||
//Start blinking icon towards end
|
||||
if (blinkingTimer != null) {
|
||||
blinkingTimer.cancel();
|
||||
}
|
||||
blinkingTimer = new Timer("Blinking Timer");
|
||||
blinkingTimer.schedule(new TimerTask() {
|
||||
Boolean isVisible = true;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
isVisible = !isVisible;
|
||||
iconToDisplay.setVisible(isVisible);
|
||||
}
|
||||
}, (int) (tokenType.getTimeout() * ICON_BLINK_TIMEOUT_RATIO), ICON_BLINK_PERIOD);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeIcon(ClientYacht yacht) {
|
||||
if (yacht == player) {
|
||||
blinkingTimer.cancel();
|
||||
iconToDisplay.setVisible(false);
|
||||
iconToDisplay = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The important annotations have been changed, update this view
|
||||
*
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.jfoenix.controls.JFXTextField;
|
||||
import com.jfoenix.validation.RequiredFieldValidator;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
@@ -27,6 +28,7 @@ import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.ServerListener;
|
||||
import seng302.visualiser.ServerListenerDelegate;
|
||||
import seng302.visualiser.controllers.cells.ServerCell;
|
||||
import seng302.visualiser.controllers.dialogs.ServerCreationController;
|
||||
import seng302.visualiser.validators.HostNameFieldValidator;
|
||||
import seng302.visualiser.validators.NumberRangeValidator;
|
||||
import seng302.visualiser.validators.ValidationTools;
|
||||
@@ -55,6 +57,14 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
||||
|
||||
private Label noServersFound;
|
||||
private Logger logger = LoggerFactory.getLogger(ServerListController.class);
|
||||
private JFXDialog serverCreationDialog;
|
||||
private List<ServerCreationDialogListener> serverCreationDialogListeners = new ArrayList<>();
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ServerCreationDialogListener {
|
||||
|
||||
void notifyClosure();
|
||||
}
|
||||
|
||||
// TODO: 12/09/17 ajm412: break this method down, its way too long.
|
||||
@Override
|
||||
@@ -115,6 +125,8 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
||||
serverListHostButton.setOnAction(action -> {
|
||||
showServerCreationDialog();
|
||||
});
|
||||
|
||||
addServerCreationDialogListener(this::closeServerCreationDialog);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,9 +137,11 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
||||
FXMLLoader dialogContent = new FXMLLoader(getClass().getResource(
|
||||
"/views/dialogs/ServerCreationDialog.fxml"));
|
||||
try {
|
||||
JFXDialog dialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
||||
serverCreationDialog = new JFXDialog(serverListMainStackPane, dialogContent.load(),
|
||||
DialogTransition.CENTER);
|
||||
dialog.show();
|
||||
ServerCreationController serverCreationController = dialogContent.getController();
|
||||
serverCreationController.setListener(serverCreationDialogListeners);
|
||||
serverCreationDialog.show();
|
||||
Sounds.playButtonClick();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Could not create Server Creation Dialog.");
|
||||
@@ -135,6 +149,10 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
||||
});
|
||||
}
|
||||
|
||||
private void closeServerCreationDialog() {
|
||||
serverCreationDialog.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the connection and attempts to connect to a given hostname and port number.
|
||||
*/
|
||||
@@ -203,4 +221,14 @@ public class ServerListController implements Initializable, ServerListenerDelega
|
||||
public void serverDetected(ServerDescription serverDescription, List<ServerDescription> servers) {
|
||||
Platform.runLater(() -> refreshServers(servers));
|
||||
}
|
||||
|
||||
private void addServerCreationDialogListener(
|
||||
ServerCreationDialogListener serverCreationDialogListener) {
|
||||
serverCreationDialogListeners.add(serverCreationDialogListener);
|
||||
}
|
||||
|
||||
private void removeServerCreationDialogListener(
|
||||
ServerCreationDialogListener serverCreationDialogListener) {
|
||||
serverCreationDialogListeners.remove(serverCreationDialogListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import seng302.utilities.BonjourInstallChecker;
|
||||
import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.GameClient;
|
||||
import seng302.visualiser.controllers.dialogs.KeyBindingDialogController;
|
||||
import seng302.visualiser.controllers.dialogs.PopupDialogController;
|
||||
|
||||
public class ViewManager {
|
||||
|
||||
@@ -109,8 +110,6 @@ public class ViewManager {
|
||||
gameClient.stopGame();
|
||||
System.exit(0);
|
||||
});
|
||||
|
||||
jfxSnackbar = new JFXSnackbar(decorator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,6 +194,7 @@ public class ViewManager {
|
||||
}
|
||||
});
|
||||
|
||||
jfxSnackbar = new JFXSnackbar(decorator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,6 +228,7 @@ public class ViewManager {
|
||||
.getController();
|
||||
keyBindingDialogController.setGameClient(this.gameClient);
|
||||
keyBindingDialog.show();
|
||||
decorator.requestFocus();
|
||||
Sounds.playButtonClick();
|
||||
}
|
||||
}
|
||||
@@ -237,6 +238,26 @@ public class ViewManager {
|
||||
keyBindingDialog.close();
|
||||
}
|
||||
|
||||
public PopupDialogController showPopupDialog() {
|
||||
FXMLLoader dialogContent = new FXMLLoader(
|
||||
getClass().getResource("/views/dialogs/PopupDialog.fxml"));
|
||||
for (Node node : decorator.getChildren()) {
|
||||
if (node instanceof StackPane) {
|
||||
try {
|
||||
JFXDialog dialog = new JFXDialog((StackPane) node, dialogContent.load(),
|
||||
DialogTransition.CENTER);
|
||||
PopupDialogController popupDialogController = dialogContent.getController();
|
||||
popupDialogController.setPopupDialog(dialog);
|
||||
dialog.show();
|
||||
return popupDialogController;
|
||||
} catch (IOException e) {
|
||||
logger.error("Cannot load Popup dialog");
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a snackbar at the bottom of the app for 1 second.
|
||||
*
|
||||
|
||||
+15
-5
@@ -48,6 +48,16 @@ public class KeyBindingDialogController implements Initializable {
|
||||
private Label downwindLabel;
|
||||
@FXML
|
||||
private JFXToggleButton turningToggle;
|
||||
@FXML
|
||||
private JFXButton viewButton;
|
||||
@FXML
|
||||
private JFXButton rightButton;
|
||||
@FXML
|
||||
private JFXButton leftButton;
|
||||
@FXML
|
||||
private JFXButton forwardButton;
|
||||
@FXML
|
||||
private JFXButton backwardButton;
|
||||
//---------FXML END---------//
|
||||
|
||||
private GameKeyBind gameKeyBind;
|
||||
@@ -60,7 +70,8 @@ public class KeyBindingDialogController implements Initializable {
|
||||
gameKeyBind = GameKeyBind.getInstance();
|
||||
buttons = new ArrayList<>();
|
||||
Collections.addAll(buttons,
|
||||
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn);
|
||||
zoomInbtn, zoomOutBtn, vmgBtn, sailInOutBtn, tackGybeBtn, upwindBtn, downwindBtn,
|
||||
viewButton, rightButton, leftButton, forwardButton, backwardButton);
|
||||
bindButtonWithAction();
|
||||
loadKeyBind();
|
||||
|
||||
@@ -76,12 +87,10 @@ public class KeyBindingDialogController implements Initializable {
|
||||
resetBtn.setOnMouseClicked(event -> {
|
||||
gameKeyBind.setToDefault();
|
||||
loadKeyBind();
|
||||
showSnackBar("All keys reset!", false);
|
||||
});
|
||||
|
||||
closeLabel.setOnMouseClicked(event -> ViewManager.getInstance().closeKeyBindingDialog());
|
||||
|
||||
keyBindingDialogHeader.setFocusTraversable(true);
|
||||
keyBindingDialogHeader.requestFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +115,7 @@ public class KeyBindingDialogController implements Initializable {
|
||||
*/
|
||||
private void bindButtonWithAction() {
|
||||
buttonActionMap = new HashMap<>();
|
||||
for (int i = 0; i < 7; i++) {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
buttonActionMap.put(buttons.get(i), KeyAction.getType(i + 1));
|
||||
}
|
||||
}
|
||||
@@ -149,6 +158,7 @@ public class KeyBindingDialogController implements Initializable {
|
||||
+ "-fx-background-color: -fx-pp-front-color; "
|
||||
+ "-fx-text-fill: -fx-pp-theme-color; "
|
||||
+ "-fx-font-size: 13;");
|
||||
keyBindingDialogHeader.requestFocus();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package seng302.visualiser.controllers.dialogs;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXDialog;
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
|
||||
public class PopupDialogController implements Initializable {
|
||||
|
||||
@FXML
|
||||
private Label headerLabel;
|
||||
@FXML
|
||||
private Label contentLabel;
|
||||
@FXML
|
||||
private Label closeLabel;
|
||||
@FXML
|
||||
private JFXButton optionButton;
|
||||
|
||||
@FXML
|
||||
private JFXDialog popupDialog;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.contentLabel.setText(content);
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.headerLabel.setText(header);
|
||||
}
|
||||
|
||||
public void setOptionButton(JFXButton jfxButton) {
|
||||
this.optionButton = jfxButton;
|
||||
}
|
||||
|
||||
public void setOptionButtonText(String text) {
|
||||
this.optionButton.setText(text);
|
||||
}
|
||||
|
||||
public void setOptionButtonEventHandler(EventHandler<? super MouseEvent> eventHandler) {
|
||||
this.optionButton.setOnMouseClicked(eventHandler);
|
||||
}
|
||||
|
||||
public void setPopupDialog(JFXDialog popupDialog) {
|
||||
this.popupDialog = popupDialog;
|
||||
this.closeLabel.setOnMouseClicked(event -> this.popupDialog.close());
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,15 @@ import com.jfoenix.controls.JFXSlider;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import com.jfoenix.validation.RequiredFieldValidator;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
import javafx.application.Platform;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import seng302.gameServer.ServerDescription;
|
||||
import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.controllers.ServerListController.ServerCreationDialogListener;
|
||||
import seng302.visualiser.controllers.ViewManager;
|
||||
import seng302.visualiser.validators.FieldLengthValidator;
|
||||
import seng302.visualiser.validators.ValidationTools;
|
||||
@@ -28,8 +29,12 @@ public class ServerCreationController implements Initializable {
|
||||
private Label maxPlayersLabel;
|
||||
@FXML
|
||||
private JFXButton submitBtn;
|
||||
@FXML
|
||||
private Label closeLabel;
|
||||
//---------FXML END---------//
|
||||
|
||||
private List<ServerCreationDialogListener> serverCreationDialogListeners;
|
||||
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
updateMaxPlayerLabel();
|
||||
maxPlayersSlider.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||
@@ -49,6 +54,7 @@ public class ServerCreationController implements Initializable {
|
||||
validateServerSettings();
|
||||
});
|
||||
|
||||
closeLabel.setOnMouseClicked(event -> notifyListeners());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,4 +93,14 @@ public class ServerCreationController implements Initializable {
|
||||
Sounds.playHoverSound();
|
||||
}
|
||||
|
||||
public void setListener(List<ServerCreationDialogListener> serverCreationDialogListeners) {
|
||||
this.serverCreationDialogListeners = serverCreationDialogListeners;
|
||||
}
|
||||
|
||||
public void notifyListeners() {
|
||||
for (ServerCreationDialogListener serverCreationDialogListener : serverCreationDialogListeners) {
|
||||
serverCreationDialogListener.notifyClosure();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package seng302.visualiser.fxObjects.assets_3D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
@@ -30,12 +31,15 @@ public class BoatObject extends Group {
|
||||
private Boolean isSelected = false;
|
||||
private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
|
||||
|
||||
private ReadOnlyDoubleWrapper rotationProperty;
|
||||
|
||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the default triangular boat polygon.
|
||||
*/
|
||||
public BoatObject(BoatMeshType boatMeshType) {
|
||||
rotationProperty = new ReadOnlyDoubleWrapper(0.0);
|
||||
boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
|
||||
boatAssets.hideSail();
|
||||
boatAssets.getAssets().getTransforms().addAll(
|
||||
@@ -83,6 +87,7 @@ public class BoatObject extends Group {
|
||||
|
||||
|
||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||
rotationProperty.set(heading);
|
||||
rotation.setAngle(heading);
|
||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||
if (sailsIn) {
|
||||
@@ -130,4 +135,8 @@ public class BoatObject extends Group {
|
||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||
selectedBoatListenerListeners.add(sbl);
|
||||
}
|
||||
|
||||
public ReadOnlyDoubleWrapper getRotationProperty() {
|
||||
return rotationProperty;
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,11 @@ public class ModelFactory {
|
||||
}
|
||||
switch (tokenType) {
|
||||
case VELOCITY_PICKUP:
|
||||
return makeCoinPickup(assets);
|
||||
case BUMPER_PICKUP:
|
||||
case RANDOM_PICKUP:
|
||||
case HANDLING_PICKUP:
|
||||
case WIND_WALKER_PICKUP:
|
||||
return makeTokenPickup(assets);
|
||||
case FINISH_MARKER:
|
||||
case PLAIN_MARKER:
|
||||
case START_MARKER:
|
||||
@@ -185,24 +189,22 @@ public class ModelFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static Model makeCoinPickup(Group assets){
|
||||
assets.setRotationAxis(new Point3D(1,0,0));
|
||||
assets.setRotate(90);
|
||||
assets.setTranslateX(0.2);
|
||||
assets.setTranslateY(1);
|
||||
private static Model makeTokenPickup(Group assets) {
|
||||
Rotate animationRotate = new Rotate(0, new Point3D(0, 0, 1));
|
||||
assets.getTransforms().addAll(
|
||||
new Translate(0,-1,0),
|
||||
new Rotate(0 ,new Point3D(1,1,1))
|
||||
animationRotate,
|
||||
new Translate(0, 0, -1)
|
||||
);
|
||||
|
||||
return new Model(new Group(assets), new AnimationTimer() {
|
||||
|
||||
private double rotation = 0;
|
||||
private Group group = assets;
|
||||
private Rotate rotate = animationRotate;
|
||||
|
||||
@Override
|
||||
public void handle(long now) {
|
||||
rotation += 1;
|
||||
((Rotate) group.getTransforms().get(1)).setAngle(rotation);
|
||||
rotate.setAngle(rotation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ package seng302.visualiser.fxObjects.assets_3D;
|
||||
public enum ModelType {
|
||||
|
||||
VELOCITY_PICKUP("velocity_pickup.dae"),
|
||||
HANDLING_PICKUP("turning_pickup.dae"),
|
||||
WIND_WALKER_PICKUP("wind_walker_pickup.dae"),
|
||||
BUMPER_PICKUP("bumper_pickup.dae"),
|
||||
RANDOM_PICKUP("random_pickup.dae"),
|
||||
FINISH_MARKER ("finish_marker.dae"),
|
||||
START_MARKER ("start_marker.dae"),
|
||||
PLAIN_MARKER ("plain_marker.dae"),
|
||||
|
||||
Reference in New Issue
Block a user