- Chase Camera:

- Has panning bounds, zoom bounds, and general tidy up.
 - Now correctly observes the boat object rather than getting information from both the boat object AND the client yacht model.

Top Down Camera:
 - Can only pan within certain bounds now, and will continue to follow the boat regardless.
 - Can only zoom within certain bounds now.

Isometric Camera:
 - Nothing changed.

#tags [1273]
This commit is contained in:
alistairjmcintyre
2017-09-26 15:06:21 +13:00
parent 00b09997b0
commit 2e7487fdfc
5 changed files with 130 additions and 106 deletions
@@ -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;
@@ -53,12 +55,13 @@ public class GameView3D {
private Group root3D; private Group root3D;
private SubScene view; private SubScene view;
// ParallelCamera camera;
private PerspectiveCamera camera;
private PerspectiveCamera camera2;
private PerspectiveCamera camera3;
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;
@@ -93,28 +96,25 @@ public class GameView3D {
} }
public GameView3D () { public GameView3D () {
camera = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH); isometricCam = new IsometricCamera(DEFAULT_CAMERA_X, DEFAULT_CAMERA_Y,
camera.setFarClip(600); DEFAULT_CAMERA_DEPTH);
camera.setNearClip(0.1); topDownCam = new TopDownCamera();
camera.setFieldOfView(FOV); chaseCam = new ChaseCamera();
camera2 = new TopDownCamera(); for (PerspectiveCamera pc : Arrays.asList(isometricCam, topDownCam, chaseCam)) {
camera2.setFarClip(600); pc.setFarClip(600);
camera2.setNearClip(0.1); pc.setNearClip(0.1);
camera2.setFieldOfView(FOV); pc.setFieldOfView(FOV);
}
camera3 = new ChaseCamera();
camera3.setFarClip(600);
camera3.setNearClip(0.1);
camera3.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))); isometricCam.getTransforms()
.add(new Rotate(30, new Point3D(1, 0, 0))); //todo: move this into isometric cam?
gameObjects.getChildren().addAll( gameObjects.getChildren().addAll(
ModelFactory.importModel(ModelType.OCEAN).getAssets(), ModelFactory.importModel(ModelType.OCEAN).getAssets(),
@@ -449,16 +449,20 @@ public class GameView3D {
((RaceCamera) view.getCamera()).panRight(); ((RaceCamera) view.getCamera()).panRight();
break; break;
case F1: case F1:
if (view.getCamera().equals(camera)) { toggleCamera();
view.setCamera(camera2); break;
if (view.getCamera() instanceof TopDownCamera) { }
((RaceCamera) view.getCamera()).zoomIn(); }
}
} else if (view.getCamera().equals(camera2)) { private void toggleCamera() {
view.setCamera(camera3); Camera currCamera = view.getCamera();
} else {
view.setCamera(camera); if (currCamera.equals(isometricCam)) {
} view.setCamera(topDownCam);
} else if (currCamera.equals(topDownCam)) {
view.setCamera(chaseCam);
} else {
view.setCamera(isometricCam);
} }
} }
@@ -498,8 +502,8 @@ public class GameView3D {
if (clientYacht.getSourceId().equals( if (clientYacht.getSourceId().equals(
ViewManager.getInstance().getGameClient().getServerThread().getClientId())) { ViewManager.getInstance().getGameClient().getServerThread().getClientId())) {
((ChaseCamera) camera3).setPlayerBoat(newBoat, clientYacht); ((ChaseCamera) chaseCam).setPlayerBoat(newBoat);
((TopDownCamera) camera2).setPlayerBoat(newBoat); ((TopDownCamera) topDownCam).setPlayerBoat(newBoat);
} }
} }
Platform.runLater(() -> { Platform.runLater(() -> {
@@ -1,22 +1,25 @@
package seng302.visualiser.cameras; package seng302.visualiser.cameras;
import javafx.beans.value.ChangeListener; import java.util.Arrays;
import javafx.beans.value.ObservableValue; import javafx.beans.property.DoubleProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.geometry.Point3D; import javafx.geometry.Point3D;
import javafx.scene.PerspectiveCamera; import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Rotate; import javafx.scene.transform.Rotate;
import javafx.scene.transform.Transform; import javafx.scene.transform.Transform;
import javafx.scene.transform.Translate; import javafx.scene.transform.Translate;
import seng302.model.ClientYacht;
import seng302.visualiser.fxObjects.assets_3D.BoatObject; import seng302.visualiser.fxObjects.assets_3D.BoatObject;
public class ChaseCamera extends PerspectiveCamera implements RaceCamera { 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 ObservableList<Transform> transforms; private ObservableList<Transform> transforms;
private BoatObject playerBoat; private BoatObject playerBoat;
private ClientYacht playerYacht;
private Double zoomFactor; private Double zoomFactor;
private Double horizontalPan; private Double horizontalPan;
private Double verticalPan; private Double verticalPan;
@@ -25,43 +28,27 @@ public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
public ChaseCamera() { public ChaseCamera() {
super(true); super(true);
transforms = this.getTransforms(); transforms = this.getTransforms();
this.zoomFactor = -75.0;
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
this.horizontalPan = 0.0; this.horizontalPan = 0.0;
this.verticalPan = 0.0; this.verticalPan = 0.0;
} }
public void setPlayerBoat(BoatObject playerBoat, ClientYacht playerYacht) { public void setPlayerBoat(BoatObject playerBoat) {
this.playerBoat = playerBoat; this.playerBoat = playerBoat;
this.playerYacht = playerYacht;
this.playerYacht.getHeadingProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
Number newValue) {
repositionCamera();
}
});
this.playerBoat.layoutXProperty().addListener(new ChangeListener<Number>() { for (DoubleProperty o : Arrays
@Override .asList(playerBoat.getRotationProperty(), playerBoat.layoutYProperty(),
public void changed(ObservableValue<? extends Number> observable, Number oldValue, playerBoat.layoutXProperty())) {
Number newValue) { o.addListener((obs, oldVal, newVal) -> repositionCamera());
repositionCamera(); }
}
});
this.playerBoat.layoutYProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
Number newValue) {
repositionCamera();
}
});
} }
private void repositionCamera() { private void repositionCamera() {
transforms.clear(); transforms.clear();
transforms.addAll( transforms.addAll(
new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), 0), new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), 0),
new Rotate(playerYacht.getHeadingProperty().getValue() + horizontalPan, new Rotate(playerBoat.getRotationProperty().getValue() + horizontalPan,
new Point3D(0, 0, 1)), new Point3D(0, 0, 1)),
new Rotate(60 + verticalPan, new Point3D(1, 0, 0)), new Rotate(60 + verticalPan, new Point3D(1, 0, 0)),
new Translate(0, 0, zoomFactor) new Translate(0, 0, zoomFactor)
@@ -69,19 +56,25 @@ public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
} }
private void adjustZoomFactor(Double adjustment) { private void adjustZoomFactor(Double adjustment) {
if (zoomFactor + adjustment < -15.0 && zoomFactor + adjustment > -125.0) { if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
zoomFactor = zoomFactor + adjustment; zoomFactor = zoomFactor + adjustment;
repositionCamera(); repositionCamera();
} }
} }
private void adjustVerticalPan(Double adjustment) { private void adjustVerticalPan(Double adjustment) {
if (verticalPan + adjustment >= -20 && verticalPan + adjustment <= 20) { if (verticalPan + adjustment >= -VERTICAL_PAN_LIMIT
&& verticalPan + adjustment <= VERTICAL_PAN_LIMIT) {
verticalPan += adjustment; verticalPan += adjustment;
repositionCamera(); repositionCamera();
} }
} }
private void adjustHorizontalPan(Double adjustment) {
this.horizontalPan += adjustment;
repositionCamera();
}
@Override @Override
public void zoomIn() { public void zoomIn() {
adjustZoomFactor(5.0); adjustZoomFactor(5.0);
@@ -92,21 +85,14 @@ public class ChaseCamera extends PerspectiveCamera implements RaceCamera {
adjustZoomFactor(-5.0); adjustZoomFactor(-5.0);
} }
/*
These have been left intentionally empty for now. it would be cool to be able to pan around the boat and have the camera move around the boat though.
*/
@Override @Override
public void panLeft() { public void panLeft() {
this.horizontalPan -= 5; adjustHorizontalPan(-5.0);
repositionCamera();
} }
@Override @Override
public void panRight() { public void panRight() {
this.horizontalPan += 5; adjustHorizontalPan(5.0);
repositionCamera();
} }
@Override @Override
@@ -7,6 +7,13 @@ import javafx.scene.transform.Translate;
public class IsometricCamera extends PerspectiveCamera implements RaceCamera { public class IsometricCamera extends PerspectiveCamera implements RaceCamera {
private final Double PAN_LIMIT = 50.0;
private final Double NEAR_ZOOM_LIMIT = -15.0;
private final Double FAR_ZOOM_LIMIT = -125.0;
private Double horizontalAdjustment;
private Double verticalAdjustment;
ObservableList<Transform> transforms; ObservableList<Transform> transforms;
public IsometricCamera(Double cameraStartX, Double cameraStartY, Double cameraDepth) { public IsometricCamera(Double cameraStartX, Double cameraStartY, Double cameraDepth) {
@@ -1,8 +1,8 @@
package seng302.visualiser.cameras; package seng302.visualiser.cameras;
import javafx.beans.value.ChangeListener; import java.util.Arrays;
import javafx.beans.value.ObservableValue; import javafx.beans.property.DoubleProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.scene.PerspectiveCamera; import javafx.scene.PerspectiveCamera;
import javafx.scene.transform.Transform; import javafx.scene.transform.Transform;
@@ -11,75 +11,93 @@ import seng302.visualiser.fxObjects.assets_3D.BoatObject;
public class TopDownCamera extends PerspectiveCamera implements RaceCamera { 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 ObservableList<Transform> transforms;
private BoatObject playerBoat; private BoatObject playerBoat;
private Double zoomFactor;
private Double horizontalPan;
private Double verticalPan;
public TopDownCamera() { public TopDownCamera() {
super(true); super(true);
transforms = this.getTransforms(); transforms = this.getTransforms();
transforms.add(new Translate(0, 0, -125));
zoomFactor = (FAR_ZOOM_LIMIT + NEAR_ZOOM_LIMIT) / 2.0;
horizontalPan = 0.0;
verticalPan = 0.0;
} }
public void setPlayerBoat(BoatObject playerBoat) { public void setPlayerBoat(BoatObject playerBoat) {
this.playerBoat = playerBoat; this.playerBoat = playerBoat;
this.playerBoat.layoutXProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
Number newValue) {
updateCameraX((Double) oldValue, (Double) newValue);
}
});
this.playerBoat.layoutYProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue,
Number newValue) {
updateCameraY((Double) oldValue, (Double) newValue);
}
});
}
for (DoubleProperty o : Arrays
private void updateCameraX(Double oldXValue, Double newXValue) { .asList(playerBoat.layoutXProperty(), playerBoat.layoutYProperty())) {
if (transforms.size() == 0) { // boat is placed and then moved at start, o.addListener((obs, oldVal, newVal) -> updateCamera());
transforms.addAll(
new Translate(playerBoat.getLayoutX(), playerBoat.getLayoutY(), -125)
);
} else {
transforms.addAll(new Translate(newXValue - oldXValue, 0, 0));
} }
} }
private void updateCameraY(Double oldYValue, Double newYValue) { private void updateCamera() {
transforms.addAll(new Translate(0, (newYValue - oldYValue), 0)); transforms.clear();
transforms.addAll(
new Translate(playerBoat.getLayoutX() + horizontalPan,
playerBoat.getLayoutY() + verticalPan, zoomFactor)
);
}
private void adjustZoomFactor(Double adjustment) {
if (zoomFactor + adjustment < NEAR_ZOOM_LIMIT && zoomFactor + adjustment > FAR_ZOOM_LIMIT) {
zoomFactor = zoomFactor + adjustment;
updateCamera();
}
}
private void adjustVerticalPan(Double adjustment) {
if (verticalPan + adjustment >= -PAN_LIMIT && verticalPan + adjustment <= PAN_LIMIT) {
verticalPan += adjustment;
updateCamera();
}
}
private void adjustHorizontalPan(Double adjustment) {
if (horizontalPan + adjustment >= -PAN_LIMIT && horizontalPan + adjustment <= PAN_LIMIT) {
horizontalPan += adjustment;
updateCamera();
}
} }
@Override @Override
public void zoomIn() { public void zoomIn() {
transforms.addAll(new Translate(0, 0, 1.5)); adjustZoomFactor(ZOOM_STEP);
} }
@Override @Override
public void zoomOut() { public void zoomOut() {
transforms.addAll(new Translate(0, 0, -1.5)); adjustZoomFactor(-ZOOM_STEP);
} }
@Override @Override
public void panLeft() { public void panLeft() {
transforms.addAll(new Translate(-1, 0, 0)); adjustHorizontalPan(-1.0);
} }
@Override @Override
public void panRight() { public void panRight() {
transforms.addAll(new Translate(1, 0, 0)); adjustHorizontalPan(1.0);
} }
@Override @Override
public void panUp() { public void panUp() {
transforms.addAll(new Translate(0, -1, 0)); adjustVerticalPan(-1.0);
} }
@Override @Override
public void panDown() { public void panDown() {
transforms.addAll(new Translate(0, 1, 0)); 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;
}
} }