mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch '1273_Changing_Cameras' into 'develop'
1273 changing cameras # Multiple Camera Views ## 3 Camera Views Implemented 1. Normal 3D (Isometric) 2. Top Down Perspective 3. Chase Cam (Over the Shoulder) - Isometric and Top Down Perspectives can Pan within limits. - Chase Cam rotates the camera around the boat. (While still following it) - All camera views can Zoom. # Testing No testing completed other than manually testing myself. A proper manual test should be completed by the merger. See merge request !76
This commit is contained in:
@@ -6,6 +6,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
import java.util.Timer;
|
||||||
import javafx.beans.property.ReadOnlyDoubleProperty;
|
import javafx.beans.property.ReadOnlyDoubleProperty;
|
||||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||||
import javafx.beans.property.ReadOnlyIntegerProperty;
|
import javafx.beans.property.ReadOnlyIntegerProperty;
|
||||||
@@ -16,6 +17,7 @@ import javafx.scene.paint.Color;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||||
|
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
* Yacht class for the racing boat. <p> Class created to store more variables (eg. boat statuses)
|
||||||
@@ -57,12 +59,17 @@ public class ClientYacht extends Observable {
|
|||||||
private Integer boatStatus;
|
private Integer boatStatus;
|
||||||
private Double currentVelocity;
|
private Double currentVelocity;
|
||||||
|
|
||||||
|
Timer t;
|
||||||
|
|
||||||
|
private BoatObject boatObject;
|
||||||
|
|
||||||
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
private List<YachtLocationListener> locationListeners = new ArrayList<>();
|
||||||
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
|
private List<MarkRoundingListener> markRoundingListeners = new ArrayList<>();
|
||||||
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
|
private ReadOnlyDoubleWrapper velocityProperty = new ReadOnlyDoubleWrapper();
|
||||||
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
|
private ReadOnlyLongWrapper timeTillNextProperty = new ReadOnlyLongWrapper();
|
||||||
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
|
private ReadOnlyLongWrapper timeSinceLastMarkProperty = new ReadOnlyLongWrapper();
|
||||||
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
|
private ReadOnlyIntegerWrapper placingProperty = new ReadOnlyIntegerWrapper();
|
||||||
|
private ReadOnlyDoubleWrapper headingProperty = new ReadOnlyDoubleWrapper();
|
||||||
private Color colour;
|
private Color colour;
|
||||||
|
|
||||||
public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
public ClientYacht(BoatMeshType boatType, Integer sourceId, String hullID, String shortName,
|
||||||
@@ -75,6 +82,7 @@ public class ClientYacht extends Observable {
|
|||||||
this.country = country;
|
this.country = country;
|
||||||
this.location = new GeoPoint(57.670341, 11.826856);
|
this.location = new GeoPoint(57.670341, 11.826856);
|
||||||
this.heading = 120.0; //In degrees
|
this.heading = 120.0; //In degrees
|
||||||
|
this.headingProperty.set(this.heading);
|
||||||
this.currentVelocity = 0d;
|
this.currentVelocity = 0d;
|
||||||
this.boatStatus = 1;
|
this.boatStatus = 1;
|
||||||
this.colour = Color.rgb(0, 0, 0, 1.0);
|
this.colour = Color.rgb(0, 0, 0, 1.0);
|
||||||
@@ -222,6 +230,7 @@ public class ClientYacht extends Observable {
|
|||||||
|
|
||||||
public void setHeading(Double heading) {
|
public void setHeading(Double heading) {
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
|
setHeadingProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -250,10 +259,10 @@ public class ClientYacht extends Observable {
|
|||||||
this.colour = colour;
|
this.colour = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void updateLocation(double lat, double lng, double heading, double velocity) {
|
public void updateLocation(double lat, double lng, double heading, double velocity) {
|
||||||
setLocation(lat, lng);
|
setLocation(lat, lng);
|
||||||
this.heading = heading;
|
this.heading = heading;
|
||||||
|
setHeadingProperty();
|
||||||
this.currentVelocity = velocity;
|
this.currentVelocity = velocity;
|
||||||
updateVelocityProperty(velocity);
|
updateVelocityProperty(velocity);
|
||||||
for (YachtLocationListener yll : locationListeners) {
|
for (YachtLocationListener yll : locationListeners) {
|
||||||
@@ -261,6 +270,10 @@ public class ClientYacht extends Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setHeadingProperty() {
|
||||||
|
headingProperty.set(heading);
|
||||||
|
}
|
||||||
|
|
||||||
public void addLocationListener(YachtLocationListener listener) {
|
public void addLocationListener(YachtLocationListener listener) {
|
||||||
locationListeners.add(listener);
|
locationListeners.add(listener);
|
||||||
}
|
}
|
||||||
@@ -289,4 +302,17 @@ public class ClientYacht extends Observable {
|
|||||||
public Double getCurrentVelocity() {
|
public Double getCurrentVelocity() {
|
||||||
return currentVelocity;
|
return currentVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBoatObject(BoatObject newBoatObject) {
|
||||||
|
this.boatObject = newBoatObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoatObject getBoatObject() {
|
||||||
|
return this.boatObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadOnlyDoubleWrapper getHeadingProperty() {
|
||||||
|
return headingProperty;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ public class GameKeyBind {
|
|||||||
return instance.actionToKeyMap.get(keyAction);
|
return instance.actionToKeyMap.get(keyAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public KeyAction getKeyAction(KeyCode keyCode) {
|
||||||
|
return instance.keyToActionMap.get(keyCode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a key to a key action
|
* Binds a key to a key action
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package seng302.visualiser;
|
package seng302.visualiser;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -9,6 +10,7 @@ import javafx.animation.AnimationTimer;
|
|||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.geometry.Point3D;
|
import javafx.geometry.Point3D;
|
||||||
|
import javafx.scene.Camera;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
@@ -21,7 +23,9 @@ import javafx.scene.transform.Scale;
|
|||||||
import javafx.scene.transform.Translate;
|
import javafx.scene.transform.Translate;
|
||||||
import seng302.gameServer.messages.RoundingSide;
|
import seng302.gameServer.messages.RoundingSide;
|
||||||
import seng302.model.ClientYacht;
|
import seng302.model.ClientYacht;
|
||||||
|
import seng302.model.GameKeyBind;
|
||||||
import seng302.model.GeoPoint;
|
import seng302.model.GeoPoint;
|
||||||
|
import seng302.model.KeyAction;
|
||||||
import seng302.model.Limit;
|
import seng302.model.Limit;
|
||||||
import seng302.model.mark.CompoundMark;
|
import seng302.model.mark.CompoundMark;
|
||||||
import seng302.model.mark.Corner;
|
import seng302.model.mark.Corner;
|
||||||
@@ -29,8 +33,12 @@ import seng302.model.mark.Mark;
|
|||||||
import seng302.model.token.Token;
|
import seng302.model.token.Token;
|
||||||
import seng302.utilities.GeoUtility;
|
import seng302.utilities.GeoUtility;
|
||||||
import seng302.utilities.Sounds;
|
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.MarkArrowFactory;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
|
||||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.Marker3D;
|
import seng302.visualiser.fxObjects.assets_3D.Marker3D;
|
||||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||||
@@ -42,18 +50,19 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
|||||||
|
|
||||||
public class GameView3D {
|
public class GameView3D {
|
||||||
|
|
||||||
|
|
||||||
private final double FOV = 60;
|
private final double FOV = 60;
|
||||||
private final double DEFAULT_CAMERA_DEPTH = -125;
|
|
||||||
private final double DEFAULT_CAMERA_X = 0;
|
private final double DEFAULT_CAMERA_X = 0;
|
||||||
private final double DEFAULT_CAMERA_Y = 155;
|
private final double DEFAULT_CAMERA_Y = 155;
|
||||||
|
|
||||||
private Group root3D;
|
private Group root3D;
|
||||||
private SubScene view;
|
private SubScene view;
|
||||||
// ParallelCamera camera;
|
|
||||||
private PerspectiveCamera camera;
|
|
||||||
private Group gameObjects;
|
private Group gameObjects;
|
||||||
|
|
||||||
|
// Cameras
|
||||||
|
private PerspectiveCamera isometricCam;
|
||||||
|
private PerspectiveCamera topDownCam;
|
||||||
|
private PerspectiveCamera chaseCam;
|
||||||
|
|
||||||
private double bufferSize = 0;
|
private double bufferSize = 0;
|
||||||
private double canvasWidth = 200;
|
private double canvasWidth = 200;
|
||||||
private double canvasHeight = 200;
|
private double canvasHeight = 200;
|
||||||
@@ -88,20 +97,22 @@ public class GameView3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GameView3D () {
|
public GameView3D () {
|
||||||
camera = new PerspectiveCamera(true);
|
isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y);
|
||||||
camera.getTransforms().addAll(
|
topDownCam = new TopDownCamera();
|
||||||
new Translate(DEFAULT_CAMERA_X,DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH)
|
chaseCam = new ChaseCamera();
|
||||||
);
|
|
||||||
camera.setFarClip(600);
|
for (PerspectiveCamera pc : Arrays.asList(isometricCam, topDownCam, chaseCam)) {
|
||||||
camera.setNearClip(0.1);
|
pc.setFarClip(600);
|
||||||
camera.setFieldOfView(FOV);
|
pc.setNearClip(0.1);
|
||||||
|
pc.setFieldOfView(FOV);
|
||||||
|
}
|
||||||
|
|
||||||
gameObjects = new Group();
|
gameObjects = new Group();
|
||||||
root3D = new Group(camera, gameObjects);
|
root3D = new Group(isometricCam, gameObjects);
|
||||||
view = new SubScene(
|
view = new SubScene(
|
||||||
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
||||||
);
|
);
|
||||||
view.setCamera(camera);
|
view.setCamera(isometricCam);
|
||||||
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
|
|
||||||
|
|
||||||
gameObjects.getChildren().addAll(
|
gameObjects.getChildren().addAll(
|
||||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||||
@@ -112,6 +123,8 @@ public class GameView3D {
|
|||||||
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement);
|
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) {
|
public void updateCourse(List<CompoundMark> newCourse, List<Corner> sequence) {
|
||||||
@@ -336,7 +349,6 @@ public class GameView3D {
|
|||||||
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
* it to distanceScaleFactor Returns the max horizontal distance of the map.
|
||||||
*/
|
*/
|
||||||
private double scaleRaceExtremities() {
|
private double scaleRaceExtremities() {
|
||||||
|
|
||||||
double vertAngle = Math.abs(
|
double vertAngle = Math.abs(
|
||||||
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
GeoUtility.getBearingRad(minLatPoint, maxLatPoint)
|
||||||
);
|
);
|
||||||
@@ -404,40 +416,45 @@ public class GameView3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void cameraMovement(KeyEvent event) {
|
public void cameraMovement(KeyEvent event) {
|
||||||
switch (event.getCode()) {
|
GameKeyBind keyBinds = GameKeyBind.getInstance();
|
||||||
case NUMPAD8:
|
KeyAction keyPressed = keyBinds.getKeyAction(event.getCode());
|
||||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(1,0,0)));
|
switch (keyPressed) {
|
||||||
|
case ZOOM_IN:
|
||||||
|
((RaceCamera) view.getCamera()).zoomIn();
|
||||||
break;
|
break;
|
||||||
case NUMPAD2:
|
case ZOOM_OUT:
|
||||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(1,0,0)));
|
((RaceCamera) view.getCamera()).zoomOut();
|
||||||
break;
|
break;
|
||||||
case NUMPAD4:
|
case FORWARD:
|
||||||
camera.getTransforms().addAll(new Rotate(-0.5, new Point3D(0,1,0)));
|
((RaceCamera) view.getCamera()).panUp();
|
||||||
break;
|
break;
|
||||||
case NUMPAD6:
|
case BACKWARD:
|
||||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0)));
|
((RaceCamera) view.getCamera()).panDown();
|
||||||
break;
|
break;
|
||||||
case Z:
|
case LEFT:
|
||||||
camera.getTransforms().addAll(new Translate(0, 0, 1.5));
|
((RaceCamera) view.getCamera()).panLeft();
|
||||||
break;
|
break;
|
||||||
case X:
|
case RIGHT:
|
||||||
camera.getTransforms().addAll(new Translate(0, 0, -1.5));
|
((RaceCamera) view.getCamera()).panRight();
|
||||||
break;
|
break;
|
||||||
case W:
|
case VIEW:
|
||||||
camera.getTransforms().addAll(new Translate(0, -1, 0));
|
toggleCamera();
|
||||||
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;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rescales the race to the size of the window.
|
* Rescales the race to the size of the window.
|
||||||
*
|
*
|
||||||
@@ -471,6 +488,12 @@ public class GameView3D {
|
|||||||
Point2D p2d = findScaledXY(lat, lon);
|
Point2D p2d = findScaledXY(lat, lon);
|
||||||
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
bo.moveTo(p2d.getX(), p2d.getY(), heading, velocity, sailIn, windDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (clientYacht.getSourceId().equals(
|
||||||
|
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
|
||||||
|
((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
|
||||||
|
((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
gameObjects.getChildren().addAll(wakes);
|
gameObjects.getChildren().addAll(wakes);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package seng302.visualiser.fxObjects.assets_3D;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||||
import javafx.geometry.Point3D;
|
import javafx.geometry.Point3D;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
@@ -30,12 +31,15 @@ public class BoatObject extends Group {
|
|||||||
private Boolean isSelected = false;
|
private Boolean isSelected = false;
|
||||||
private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
|
private Rotate rotation = new Rotate(0, new Point3D(0,0,1));
|
||||||
|
|
||||||
|
private ReadOnlyDoubleWrapper rotationProperty;
|
||||||
|
|
||||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BoatGroup with the default triangular boat polygon.
|
* Creates a BoatGroup with the default triangular boat polygon.
|
||||||
*/
|
*/
|
||||||
public BoatObject(BoatMeshType boatMeshType) {
|
public BoatObject(BoatMeshType boatMeshType) {
|
||||||
|
rotationProperty = new ReadOnlyDoubleWrapper(0.0);
|
||||||
boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
|
boatAssets = ModelFactory.boatGameView(boatMeshType, colour);
|
||||||
boatAssets.hideSail();
|
boatAssets.hideSail();
|
||||||
boatAssets.getAssets().getTransforms().addAll(
|
boatAssets.getAssets().getTransforms().addAll(
|
||||||
@@ -83,6 +87,7 @@ public class BoatObject extends Group {
|
|||||||
|
|
||||||
|
|
||||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||||
|
rotationProperty.set(heading);
|
||||||
rotation.setAngle(heading);
|
rotation.setAngle(heading);
|
||||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||||
if (sailsIn) {
|
if (sailsIn) {
|
||||||
@@ -130,4 +135,8 @@ public class BoatObject extends Group {
|
|||||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||||
selectedBoatListenerListeners.add(sbl);
|
selectedBoatListenerListeners.add(sbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReadOnlyDoubleWrapper getRotationProperty() {
|
||||||
|
return rotationProperty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user