mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Added 3D mark arrows and cleaned up other classes.
This commit is contained in:
@@ -1,17 +1,12 @@
|
||||
package seng302.gameServer;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import seng302.gameServer.messages.*;
|
||||
import seng302.model.Player;
|
||||
import seng302.model.ServerYacht;
|
||||
import seng302.model.stream.packets.PacketType;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
||||
import seng302.utilities.XMLGenerator;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
@@ -24,7 +19,6 @@ import java.util.zip.Checksum;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import seng302.gameServer.messages.BoatAction;
|
||||
import seng302.gameServer.messages.BoatLocationMessage;
|
||||
import seng302.gameServer.messages.ChatterMessage;
|
||||
import seng302.gameServer.messages.ClientType;
|
||||
import seng302.gameServer.messages.CustomizeRequestType;
|
||||
@@ -33,14 +27,11 @@ import seng302.gameServer.messages.RegistrationResponseMessage;
|
||||
import seng302.gameServer.messages.RegistrationResponseStatus;
|
||||
import seng302.gameServer.messages.XMLMessage;
|
||||
import seng302.gameServer.messages.XMLMessageSubType;
|
||||
import seng302.gameServer.messages.YachtEventCodeMessage;
|
||||
import seng302.model.Player;
|
||||
import seng302.model.ServerYacht;
|
||||
import seng302.model.stream.packets.PacketType;
|
||||
import seng302.model.stream.packets.StreamPacket;
|
||||
import seng302.model.stream.xml.generator.RaceXMLTemplate;
|
||||
import seng302.model.stream.xml.generator.RegattaXMLTemplate;
|
||||
import seng302.model.token.Token;
|
||||
import seng302.utilities.XMLGenerator;
|
||||
|
||||
/**
|
||||
@@ -240,8 +231,6 @@ public class ServerToClientThread implements Runnable {
|
||||
|
||||
xmlGenerator.setRaceTemplate(race);
|
||||
|
||||
System.out.println(xmlGenerator.getRegatta().getName());
|
||||
|
||||
XMLMessage xmlMessage;
|
||||
xmlMessage = new XMLMessage(xmlGenerator.getRegattaAsXml(), XMLMessageSubType.REGATTA,
|
||||
xmlGenerator.getRegattaAsXml().length());
|
||||
|
||||
@@ -16,6 +16,7 @@ import seng302.model.mark.CompoundMark;
|
||||
import seng302.model.mark.Corner;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.assets_2D.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -5,29 +5,17 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.AmbientLight;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
import javafx.scene.PointLight;
|
||||
import javafx.scene.SceneAntialiasing;
|
||||
import javafx.scene.SubScene;
|
||||
import javafx.scene.effect.BlendMode;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.ImagePattern;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.Sphere;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
@@ -40,7 +28,10 @@ import seng302.model.mark.Corner;
|
||||
import seng302.model.mark.Mark;
|
||||
import seng302.model.token.Token;
|
||||
import seng302.utilities.GeoUtility;
|
||||
import seng302.visualiser.fxObjects.assets_2D.BoatObject;
|
||||
import seng302.utilities.Sounds;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
import seng302.visualiser.fxObjects.assets_3D.Marker3D;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
@@ -50,12 +41,15 @@ import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
public class GameView3D {
|
||||
|
||||
|
||||
private final double FOV = 60;
|
||||
private final double DEFAULT_CAMERA_DEPTH = 100;
|
||||
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;
|
||||
// ParallelCamera camera;
|
||||
private PerspectiveCamera camera;
|
||||
private Group gameObjects;
|
||||
|
||||
@@ -64,24 +58,16 @@ public class GameView3D {
|
||||
private double canvasHeight = 200;
|
||||
private boolean horizontalInversion = false;
|
||||
|
||||
|
||||
|
||||
|
||||
private double distanceScaleFactor;
|
||||
private ScaleDirection scaleDirection;
|
||||
private GeoPoint minLatPoint, minLonPoint, maxLatPoint, maxLonPoint;
|
||||
private double referencePointX, referencePointY;
|
||||
private double metersPerPixelX, metersPerPixelY;
|
||||
|
||||
final double SCALE_DELTA = 1.1;
|
||||
|
||||
private Text fpsDisplay = new Text();
|
||||
private Group raceBorder = new Group();
|
||||
|
||||
/* Note that if either of these is null then values for it have not been added and the other
|
||||
should be used as the limits of the map. */
|
||||
private List<Limit> borderPoints;
|
||||
private Map<Mark, Group> markerObjects;
|
||||
private Map<Mark, Marker3D> markerObjects;
|
||||
|
||||
private Map<ClientYacht, BoatObject> boatObjects = new HashMap<>();
|
||||
private BoatObject selectedBoat = null;
|
||||
@@ -89,160 +75,37 @@ public class GameView3D {
|
||||
private Group boatObjectGroup = new Group();
|
||||
private Group markers = new Group();
|
||||
private Group tokens = new Group();
|
||||
private Group playerAnnotation = new Group();
|
||||
private List<CompoundMark> course = new ArrayList<>();
|
||||
private List<Node> mapTokens;
|
||||
private Timer playerBoatAnimationTimer = new Timer();
|
||||
private AnimationTimer playerBoatAnimationTimer;
|
||||
private Group trail = new Group();
|
||||
private ImageView mapImage = new ImageView();
|
||||
|
||||
//FRAME RATE
|
||||
|
||||
private AnimationTimer timer;
|
||||
private int NUM_SAMPLES = 10;
|
||||
private final long[] frameTimes = new long[NUM_SAMPLES];
|
||||
private Double frameRate = 60.0;
|
||||
private int frameTimeIndex = 0;
|
||||
private boolean arrayFilled = false;
|
||||
private ClientYacht playerYacht;
|
||||
private double windDir = 0.0;
|
||||
|
||||
double scaleFactor = 1;
|
||||
private Double windDir;
|
||||
|
||||
private enum ScaleDirection {
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public GameView3D () {
|
||||
camera = new PerspectiveCamera(true);
|
||||
// camera = new ParallelCamera();
|
||||
// gameObjects.getTransforms().add(new Scale(4,4,4));
|
||||
// camera.setLayoutX(camera.getLayoutX()-400);
|
||||
// camera.setLayoutY(camera.getLayoutY()-400);
|
||||
camera.getTransforms().addAll(
|
||||
new Translate(0,0, -DEFAULT_CAMERA_DEPTH)
|
||||
new Translate(DEFAULT_CAMERA_X,DEFAULT_CAMERA_Y, DEFAULT_CAMERA_DEPTH)
|
||||
);
|
||||
camera.setFarClip(Double.MAX_VALUE);
|
||||
camera.setFarClip(600);
|
||||
camera.setNearClip(0.1);
|
||||
camera.setFieldOfView(FOV);
|
||||
gameObjects = new Group();
|
||||
PointLight pl = new PointLight(Color.DARKGRAY);
|
||||
pl.setLightOn(true);
|
||||
pl.setBlendMode(BlendMode.ADD);
|
||||
pl.setOpacity(0.5);
|
||||
pl.getTransforms().add(new Translate(0,0,-500));
|
||||
AmbientLight al = new AmbientLight();
|
||||
al.setLightOn(true);
|
||||
al.setBlendMode(BlendMode.SOFT_LIGHT);
|
||||
al.getTransforms().add(new Translate(0, 0, -100));
|
||||
root3D = new Group(camera, gameObjects);
|
||||
view = new SubScene(
|
||||
root3D, 1000, 1000, true, SceneAntialiasing.BALANCED
|
||||
);
|
||||
view.setCamera(camera);
|
||||
// view.setFill(Color.LIGHTBLUE);
|
||||
camera.getTransforms().add(new Rotate(30, new Point3D(1,0,0)));
|
||||
// gameObjects.getChildren().addAll(raceBorder, markers, tokens);
|
||||
System.out.println(camera.getLayoutX());
|
||||
System.out.println(camera.getTranslateX());
|
||||
System.out.println(camera.getLayoutY());
|
||||
System.out.println(camera.getTranslateY());
|
||||
System.out.println(camera.getTranslateZ());
|
||||
camera.setTranslateZ(-80);
|
||||
camera.setTranslateY(150);
|
||||
Sphere red = new Sphere(1);
|
||||
red.setMaterial(new PhongMaterial(Color.RED));
|
||||
red.setLayoutX(0);
|
||||
red.setLayoutY(0);
|
||||
|
||||
Sphere blue = new Sphere(1);
|
||||
blue.setMaterial(new PhongMaterial(Color.BLUE));
|
||||
blue.setLayoutX(1);
|
||||
blue.setLayoutY(0);
|
||||
|
||||
Sphere green = new Sphere(1);
|
||||
green.setMaterial(new PhongMaterial(Color.GREEN));
|
||||
green.setLayoutX(-.5);
|
||||
green.setLayoutY(0);
|
||||
|
||||
Sphere white = new Sphere(1);
|
||||
white.setMaterial(new PhongMaterial(Color.WHITE));
|
||||
white.setLayoutX(-.25);
|
||||
white.setLayoutY(0);
|
||||
|
||||
Sphere black = new Sphere(1);
|
||||
black.setMaterial(new PhongMaterial(Color.BLACK));
|
||||
black.setLayoutX(-.125);
|
||||
black.setLayoutY(0);
|
||||
|
||||
// ImagePattern oceanImage = new ImagePattern(
|
||||
// new Image(
|
||||
// GameView3D.class.getResourceAsStream(
|
||||
// "/pics/water.gif")
|
||||
// ), 0, 0, 1000, 1000, false
|
||||
// );
|
||||
//
|
||||
// Circle ocean = new Circle(0, 0, 5000);
|
||||
// ocean.setFill(oceanImage);
|
||||
// ocean.getTransforms().add(new Scale(0.1, 0.1));
|
||||
|
||||
gameObjects.getChildren().addAll(
|
||||
// ocean,
|
||||
// ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
raceBorder, trail, markers, tokens, playerAnnotation,
|
||||
white, blue, green, black, red
|
||||
ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
raceBorder, trail, markers, tokens
|
||||
);
|
||||
|
||||
System.out.println(camera.getLayoutX());
|
||||
System.out.println(camera.getTranslateX());
|
||||
System.out.println(camera.getLayoutY());
|
||||
System.out.println(camera.getTranslateY());
|
||||
System.out.println(camera.getTranslateZ());
|
||||
// Sphere s = new Sphere(1);
|
||||
// s.setMaterial(new PhongMaterial(Color.RED));
|
||||
// Sphere left = new Sphere(1);
|
||||
// left.setMaterial(new PhongMaterial(Color.LEMONCHIFFON));
|
||||
// left.getTransforms().add(new Translate(-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
// Sphere right = new Sphere(1);
|
||||
// right.setMaterial(new PhongMaterial(Color.ROSYBROWN));
|
||||
// right.getTransforms().add(new Translate(Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0, 0));
|
||||
// Sphere top = new Sphere(1);
|
||||
// top.setMaterial(new PhongMaterial(Color.TEAL));
|
||||
// top.getTransforms().add(new Translate(0,-Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
// Sphere bottom = new Sphere(1);
|
||||
// bottom.setMaterial(new PhongMaterial(Color.BLANCHEDALMOND));
|
||||
// bottom.getTransforms().add(new Translate(0, Math.tan(Math.toRadians(FOV / 2)) * DEFAULT_CAMERA_DEPTH, 0));
|
||||
//
|
||||
// Node boat = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BLUE).getAssets();
|
||||
// Node boat2 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.BROWN).getAssets();
|
||||
// boat2.getTransforms().add(new Translate(0,20, 0));
|
||||
// Node boat3 = ModelFactory.boatGameView(BoatMeshType.DINGHY, Color.RED).getAssets();
|
||||
// boat3.getTransforms().add(new Translate(0,-20, 0));
|
||||
//
|
||||
// Node sMarker = ModelFactory.importModel(ModelType.START_MARKER).getAssets();
|
||||
// sMarker.getTransforms().add(0, new Translate(30, 30, 0));
|
||||
//
|
||||
// Node fMarker = ModelFactory.importModel(ModelType.FINISH_MARKER).getAssets();
|
||||
// fMarker.getTransforms().add(0, new Translate(30, -30, 0));
|
||||
//
|
||||
// Node marker = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
// marker.getTransforms().add(0, new Translate(30, 0, 0));
|
||||
//
|
||||
// Node coin = ModelFactory.importModel(ModelType.VELOCITY_PICKUP).getAssets();
|
||||
// coin.setTranslateX(coin.getTranslateX() - 30);
|
||||
//
|
||||
// gameObjects.getChildren().addAll(
|
||||
// ModelFactory.importModel(ModelType.OCEAN).getAssets(),
|
||||
// s, left, right, top, bottom,
|
||||
// boat, boat2, boat3,
|
||||
// sMarker, fMarker, marker,
|
||||
// coin
|
||||
// );
|
||||
|
||||
view.sceneProperty().addListener((obs, old, scene) -> {
|
||||
if (scene != null) {
|
||||
scene.addEventHandler(KeyEvent.KEY_PRESSED, this::cameraMovement);
|
||||
@@ -298,6 +161,8 @@ public class GameView3D {
|
||||
}
|
||||
}
|
||||
|
||||
createMarkArrows(sequence);
|
||||
|
||||
//Scale race to markers if there is no border.
|
||||
if (borderPoints == null) {
|
||||
rescaleRace(new ArrayList<>(markerObjects.keySet()));
|
||||
@@ -305,7 +170,6 @@ public class GameView3D {
|
||||
//Move the Markers to initial position.
|
||||
markerObjects.forEach(((mark, marker) -> {
|
||||
Point2D p2d = findScaledXY(mark.getLat(), mark.getLng());
|
||||
System.out.println(mark.toString() + " " + p2d.toString());
|
||||
marker.setLayoutX(p2d.getX());
|
||||
marker.setLayoutY(p2d.getY());
|
||||
}));
|
||||
@@ -323,10 +187,7 @@ public class GameView3D {
|
||||
* @param markerType the type of marker as a ModelType. Should be PLAIN_MARKER, START_MARKER or END_MARKER
|
||||
*/
|
||||
private void makeAndBindMarker(Mark observableMark, ModelType markerType) {
|
||||
|
||||
Group marker = ModelFactory.importModel(markerType).getAssets();
|
||||
|
||||
markerObjects.put(observableMark, marker);
|
||||
markerObjects.put(observableMark, new Marker3D(markerType));
|
||||
observableMark.addPositionListener((mark, lat, lon) -> {
|
||||
Point2D p2d = findScaledXY(lat, lon);
|
||||
markerObjects.get(mark).setLayoutX(p2d.getX());
|
||||
@@ -364,6 +225,46 @@ public class GameView3D {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates all the data needed for to create mark arrows. Requires that a course has been
|
||||
* added to the gameview.
|
||||
* @param sequence The order in which marks are traversed.
|
||||
*/
|
||||
private void createMarkArrows (List<Corner> sequence) {
|
||||
for (int i=1; i < sequence.size()-1; i++) { //General case.
|
||||
// TODO: 16/08/17 This comparison doesn't need to exist but ehhh....
|
||||
for (Mark mark : course.get(i).getMarks()) {
|
||||
markerObjects.get(mark).addArrows(
|
||||
mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT,
|
||||
GeoUtility.getBearing(course.get(i-1).getMidPoint(), mark),
|
||||
GeoUtility.getBearing(mark, course.get(i+1).getMidPoint())
|
||||
);
|
||||
}
|
||||
}
|
||||
createStartLineArrows();
|
||||
createFinishLineArrows();
|
||||
}
|
||||
|
||||
private void createStartLineArrows () {
|
||||
for (Mark mark : course.get(0).getMarks()) {
|
||||
markerObjects.get(mark).addArrows(
|
||||
mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT,
|
||||
0d, //90
|
||||
GeoUtility.getBearing(mark, course.get(1).getMidPoint())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void createFinishLineArrows () {
|
||||
for (Mark mark : course.get(course.size()-1).getMarks()) {
|
||||
markerObjects.get(mark).addArrows(
|
||||
mark.getRoundingSide() == RoundingSide.STARBOARD ? MarkArrowFactory.RoundingSide.STARBOARD : MarkArrowFactory.RoundingSide.PORT,
|
||||
GeoUtility.getBearing(course.get(course.size()-2).getMidPoint(), mark),
|
||||
GeoUtility.getBearing(mark, mark)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the point with
|
||||
* the leftmost point, rightmost point, southern most point and northern most point
|
||||
@@ -517,10 +418,10 @@ public class GameView3D {
|
||||
case NUMPAD6:
|
||||
camera.getTransforms().addAll(new Rotate(0.5, new Point3D(0,1,0)));
|
||||
break;
|
||||
case X:
|
||||
case Z:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, 1.5));
|
||||
break;
|
||||
case Z:
|
||||
case X:
|
||||
camera.getTransforms().addAll(new Translate(0, 0, -1.5));
|
||||
break;
|
||||
case W:
|
||||
@@ -561,35 +462,20 @@ public class GameView3D {
|
||||
for (ClientYacht clientYacht : yachts) {
|
||||
Color colour = clientYacht.getColour();
|
||||
newBoat = new BoatObject();
|
||||
// newBoat.addSelectedBoatListener(this::setSelectedBoat);
|
||||
newBoat.setFill(colour);
|
||||
boatObjects.put(clientYacht, newBoat);
|
||||
// createAndBindAnnotationBox(clientYacht, colour);
|
||||
wakesGroup.getChildren().add(newBoat.getWake());
|
||||
wakes.add(newBoat.getWake());
|
||||
boatObjectGroup.getChildren().add(newBoat);
|
||||
// trails.getChildren().add(newBoat.getTrail());
|
||||
|
||||
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);
|
||||
// annotations.get(boat).setLocation(p2d.getX(), p2d.getY());
|
||||
bo.setTrajectory(
|
||||
heading,
|
||||
velocity,
|
||||
metersPerPixelX,
|
||||
metersPerPixelY);
|
||||
});
|
||||
}
|
||||
// annotationsGroup.getChildren().addAll(annotations.values());
|
||||
Platform.runLater(() -> {
|
||||
|
||||
// gameObjects.addAll(trails);
|
||||
gameObjects.getChildren().addAll(wakes);
|
||||
gameObjects.getChildren().addAll(boatObjectGroup);
|
||||
// gameObjects.addAll(annotationsGroup);
|
||||
// gameObjects.addAll(boatObjectGroup);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -630,7 +516,7 @@ public class GameView3D {
|
||||
),
|
||||
new Point3D(0,0,1)
|
||||
),
|
||||
new Scale((lastLocation.distance(location) / 15)-0.2, 1, 1)
|
||||
new Scale((lastLocation.distance(location) / 10)-0.2, 1, 1)
|
||||
);
|
||||
|
||||
Point2D midPoint = location.midpoint(lastLocation);
|
||||
@@ -652,7 +538,7 @@ public class GameView3D {
|
||||
),
|
||||
new Point3D(0,0,1)
|
||||
),
|
||||
new Scale((firstLocation.distance(lastLocation) / 15)-0.2, 1, 1)
|
||||
new Scale((firstLocation.distance(lastLocation) / 10)-0.2, 1, 1)
|
||||
);
|
||||
|
||||
Point2D midPoint = lastLocation.midpoint(firstLocation);
|
||||
@@ -684,74 +570,65 @@ public class GameView3D {
|
||||
}
|
||||
|
||||
public void setBoatAsPlayer (ClientYacht playerYacht) {
|
||||
this.playerYacht = playerYacht;
|
||||
playerBoatAnimationTimer = new AnimationTimer() {
|
||||
|
||||
Platform.runLater(() ->
|
||||
playerAnnotation.getChildren().setAll(ModelFactory.importModel(ModelType.PLAYER_IDENTIFIER).getAssets())
|
||||
);
|
||||
BoatObject playerAssets = boatObjects.get(playerYacht);
|
||||
playerAnnotation.layoutXProperty().bind(playerAssets.layoutXProperty());
|
||||
playerAnnotation.layoutYProperty().bind(playerAssets.layoutYProperty());
|
||||
|
||||
playerBoatAnimationTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
private Point2D lastLocation = findScaledXY(playerYacht.getLocation());
|
||||
double count = 60;
|
||||
Point2D lastLocation = findScaledXY(playerYacht.getLocation());
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Node segment = ModelFactory.importModel(ModelType.TRAIL_SEGMENT).getAssets();
|
||||
Point2D location = findScaledXY(playerYacht.getLocation());
|
||||
segment.getTransforms().addAll(
|
||||
new Translate(location.getX(), location.getY()),
|
||||
new Rotate(playerYacht.getHeading(), new Point3D(0,0,1)),
|
||||
new Scale(1, lastLocation.distance(location) / 5)
|
||||
);
|
||||
Platform.runLater(() -> {
|
||||
public void handle(long now) {
|
||||
if (--count == 0) {
|
||||
count = 60;
|
||||
Node segment = ModelFactory.importModel(ModelType.TRAIL_SEGMENT).getAssets();
|
||||
Point2D location = findScaledXY(playerYacht.getLocation());
|
||||
segment.getTransforms().addAll(
|
||||
new Translate(location.getX(), location.getY(), 0),
|
||||
new Rotate(playerYacht.getHeading(), new Point3D(0,0,1)),
|
||||
new Scale(1, lastLocation.distance(location) / 5, 1)
|
||||
);
|
||||
trail.getChildren().add(segment);
|
||||
if (trail.getChildren().size() > 100) {
|
||||
trail.getChildren().remove(0);
|
||||
}
|
||||
});
|
||||
lastLocation = location;
|
||||
// TODO: 11/09/2017 ROTATE PLAYER ICON
|
||||
// double leg = playerYacht.getLegNumber();
|
||||
// if (compoundMark != null) {
|
||||
// for (Mark mark : compoundMark.getMarks()) {
|
||||
//// System.out.println("markerObjects.get(mark) = " + markerObjects.get(mark));
|
||||
// markerObjects.get(mark).showNextExitArrow();
|
||||
// }
|
||||
// }
|
||||
// CompoundMark nextMark = null;
|
||||
// if (legNumber < course.size() - 1) {
|
||||
// nextMark = course.get(legNumber);
|
||||
// for (Mark mark : nextMark.getMarks()) {
|
||||
// markerObjects.get(mark).showNextEnterArrow();
|
||||
// }
|
||||
// }
|
||||
lastLocation = location;
|
||||
}
|
||||
}
|
||||
}, 0L, 500L);
|
||||
|
||||
// playerYacht.toggleSail();
|
||||
// boatObjects.get(playerYacht).setAsPlayer();
|
||||
// CompoundMark currentMark = course.get(playerYacht.getLegNumber());
|
||||
// for (Mark mark : currentMark.getMarks()) {
|
||||
// markerObjects.get(mark).showNextExitArrow();
|
||||
// }
|
||||
// annotations.get(playerYacht).addAnnotation(
|
||||
// "velocity",
|
||||
// playerYacht.getVelocityProperty(),
|
||||
// (velocity) -> String.format("Speed: %.2f ms", velocity.doubleValue())
|
||||
// );
|
||||
// Platform.runLater(() -> {
|
||||
// boatObjectGroup.getChildren().remove(boatObjects.get(playerYacht));
|
||||
// gameObjects.add(boatObjects.get(playerYacht));
|
||||
// annotationsGroup.getChildren().remove(annotations.get(playerYacht));
|
||||
// gameObjects.add(annotations.get(playerYacht));
|
||||
// });
|
||||
// playerYacht.addMarkRoundingListener(this::updateMarkArrows);
|
||||
};
|
||||
playerBoatAnimationTimer.start();
|
||||
playerYacht.addMarkRoundingListener(this::updateMarkArrows);
|
||||
boatObjects.get(playerYacht).addSelectedBoatListener((boatObject, isSelected) -> {
|
||||
System.out.println("IS SELECTED " + isSelected);
|
||||
});
|
||||
}
|
||||
|
||||
public void setWindDir(double windDir) {
|
||||
this.windDir = windDir;
|
||||
}
|
||||
|
||||
private void updateMarkArrows (ClientYacht yacht, int legNumber) {
|
||||
CompoundMark compoundMark;
|
||||
if (legNumber - 1 >= 0) {
|
||||
Sounds.playMarkRoundingSound();
|
||||
compoundMark = course.get(legNumber-1);
|
||||
for (Mark mark : compoundMark.getMarks()) {
|
||||
markerObjects.get(mark).showNextExitArrow();
|
||||
}
|
||||
}
|
||||
CompoundMark nextMark = null;
|
||||
if (legNumber < course.size() - 1) {
|
||||
Sounds.playMarkRoundingSound();
|
||||
nextMark = course.get(legNumber);
|
||||
for (Mark mark : nextMark.getMarks()) {
|
||||
markerObjects.get(mark).showNextEnterArrow();
|
||||
}
|
||||
}
|
||||
if (legNumber - 2 >= 0) {
|
||||
CompoundMark lastMark = course.get(Math.max(0, legNumber - 2));
|
||||
if (lastMark != nextMark) {
|
||||
for (Mark mark : lastMark.getMarks()) {
|
||||
markerObjects.get(mark).hideAllArrows();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ import seng302.visualiser.controllers.annotations.ImportantAnnotationController;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationDelegate;
|
||||
import seng302.visualiser.controllers.annotations.ImportantAnnotationsState;
|
||||
import seng302.visualiser.fxObjects.ChatHistory;
|
||||
import seng302.visualiser.fxObjects.assets_2D.BoatObject;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatObject;
|
||||
import seng302.visualiser.fxObjects.assets_2D.WindArrow;
|
||||
|
||||
/**
|
||||
|
||||
+91
-11
@@ -1,10 +1,19 @@
|
||||
package seng302.visualiser.fxObjects.assets_2D;
|
||||
package seng302.visualiser.fxObjects;
|
||||
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.*;
|
||||
import javafx.scene.shape.Arc;
|
||||
import javafx.scene.shape.ArcType;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.shape.Polyline;
|
||||
import javafx.scene.shape.StrokeLineCap;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.Model;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
// TODO: 16/08/17 this class used to be well written... FeelsBadMan. Maybe lose the ternary operators.
|
||||
/**
|
||||
@@ -26,6 +35,36 @@ public class MarkArrowFactory {
|
||||
public static final double ARROW_HEAD_WIDTH = 6;
|
||||
public static final double STROKE_WIDTH = 3;
|
||||
|
||||
public static Model constructEntryArrow3D (
|
||||
RoundingSide roundingSide, double angle, ModelType type) {
|
||||
Model entryArrow = ModelFactory.importModel(type);
|
||||
int multiplier = roundingSide == RoundingSide.STARBOARD ? 1 : -1;
|
||||
double relativeX = multiplier * 5 * Math.sin(angle + Math.PI / 2);
|
||||
double relativeY = multiplier * 5 * Math.cos(angle + Math.PI / 2);
|
||||
double xStart = relativeX + multiplier * 20 * Math.sin(angle + Math.PI / 2);
|
||||
double yStart = relativeY + multiplier * 20 * Math.cos(angle + Math.PI / 2);
|
||||
entryArrow.getAssets().getTransforms().addAll(
|
||||
new Translate(xStart, yStart, 0),
|
||||
new Rotate(Math.toDegrees(angle), new Point3D(0,0,1))
|
||||
);
|
||||
return entryArrow;
|
||||
}
|
||||
|
||||
public static Model constructExitArrow3D (
|
||||
RoundingSide roundingSide, double angle, ModelType type) {
|
||||
Model exitArrow = ModelFactory.importModel(type);
|
||||
angle = Math.toRadians(angle);
|
||||
int multiplier = roundingSide == RoundingSide.STARBOARD ? 1 : -1;
|
||||
double xStart = multiplier * 5 * Math.sin(angle + Math.PI / 2);
|
||||
double yStart = multiplier * 5 * Math.cos(angle + Math.PI / 2);
|
||||
exitArrow.getAssets().getTransforms().addAll(
|
||||
new Translate(xStart, yStart, 0),
|
||||
new Rotate(Math.toDegrees(angle), new Point3D(0,0,1))
|
||||
);
|
||||
return exitArrow;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an entry arrow group showing an arrow into and out of the rounding area. It is centered on (0, 0).
|
||||
* @param roundingSide The side of the boat that will be closest to the mark.
|
||||
@@ -35,48 +74,72 @@ public class MarkArrowFactory {
|
||||
* @return The group containing all JavaFX objects.
|
||||
*/
|
||||
public static Group constructEntryArrow (RoundingSide roundingSide, double angleOfEntry,
|
||||
double angleOfExit, Paint colour) {
|
||||
if (roundingSide == RoundingSide.PORT && angleOfEntry < angleOfExit && Math.abs(angleOfExit - angleOfEntry) < 180) {
|
||||
double angleOfExit, Paint colour) {
|
||||
// Check to see if the the angle around mark would take you inside of it. (less than 180)
|
||||
// If so make interior angle.
|
||||
if (roundingSide == RoundingSide.PORT && angleOfEntry < angleOfExit &&
|
||||
Math.abs(angleOfExit - angleOfEntry) < 180) {
|
||||
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
|
||||
} else if (roundingSide == RoundingSide.STARBOARD && angleOfEntry > angleOfExit && -Math.abs(angleOfEntry - angleOfExit) > -180) {
|
||||
|
||||
} else if (roundingSide == RoundingSide.STARBOARD && angleOfEntry > angleOfExit &&
|
||||
-Math.abs(angleOfEntry - angleOfExit) > -180) {
|
||||
return makeInteriorAngle(roundingSide, angleOfExit, angleOfEntry, colour);
|
||||
}
|
||||
|
||||
angleOfEntry = 180 - angleOfEntry;
|
||||
//Create regular exit arrow.
|
||||
Group arrow = new Group();
|
||||
Group exitSection = constructExitArrow(roundingSide, angleOfExit, colour);
|
||||
//Reverse angles to make arc
|
||||
angleOfEntry = 180 - angleOfEntry;
|
||||
angleOfExit = 180 - angleOfExit;
|
||||
//Maker the arc
|
||||
Arc roundSection = new Arc(
|
||||
0, 0, MARK_ARROW_SEPARATION, MARK_ARROW_SEPARATION,
|
||||
(roundingSide == RoundingSide.PORT ? -180 : 0) + angleOfEntry,
|
||||
//Where to start drawing arc from
|
||||
(roundingSide == RoundingSide.PORT ? 0 : angleOfEntry),
|
||||
//Which way to go around the mark. (clockwise vs anticlockwise)
|
||||
roundingSide == RoundingSide.PORT ? Math.abs(angleOfExit - angleOfEntry) : -Math.abs(angleOfEntry - angleOfExit)
|
||||
);
|
||||
roundSection.setStrokeWidth(STROKE_WIDTH);
|
||||
roundSection.setType(ArcType.OPEN);
|
||||
roundSection.setStroke(colour);
|
||||
roundSection.setFill(new Color(0,0,0,0));
|
||||
//Revert angle to normal for line segment. Invert Port/Starboard since it is an entry arrow.
|
||||
Polygon entrySection = constructLineSegment(
|
||||
roundingSide == RoundingSide.PORT ? RoundingSide.STARBOARD : RoundingSide.PORT, 180 + angleOfEntry, colour
|
||||
roundingSide == RoundingSide.PORT ? RoundingSide.STARBOARD : RoundingSide.PORT,
|
||||
180 + angleOfEntry, colour
|
||||
);
|
||||
arrow.getChildren().addAll(exitSection, roundSection, entrySection);
|
||||
return arrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an arrow when the turning is not around the outside of the mark.
|
||||
*
|
||||
* @param roundingSide side to round on.
|
||||
* @param angleOfExit angle of entry
|
||||
* @param angleOfEntry angle of exit
|
||||
* @param colour colour of arrow
|
||||
* @return the arrow.
|
||||
*/
|
||||
private static Group makeInteriorAngle (RoundingSide roundingSide, double angleOfExit, double angleOfEntry, Paint colour) {
|
||||
Group arrow = new Group();
|
||||
Polygon lineSegment;
|
||||
//Reverse angle of exit/entry to find position between them
|
||||
angleOfEntry = Math.toRadians(360 - angleOfEntry);
|
||||
angleOfExit = Math.toRadians(180 - angleOfExit);
|
||||
//Find start of entry arrow if it was a regular arrow.
|
||||
int multiplier = roundingSide == RoundingSide.STARBOARD ? -1 : 1;
|
||||
double xStart = multiplier * MARK_ARROW_SEPARATION * Math.sin(angleOfEntry + Math.PI / 2);
|
||||
double yStart = multiplier * MARK_ARROW_SEPARATION * Math.cos(angleOfEntry + Math.PI / 2);
|
||||
xStart = xStart + (ARROW_LENGTH * Math.sin(angleOfEntry));
|
||||
yStart = yStart + (ARROW_LENGTH * Math.cos(angleOfEntry));
|
||||
//Find of end exit arrow if it was a regular arrow.
|
||||
multiplier = roundingSide == RoundingSide.STARBOARD ? 1 : -1;
|
||||
double xEnd = multiplier * MARK_ARROW_SEPARATION * Math.sin(angleOfExit + Math.PI / 2);
|
||||
double yEnd = multiplier * MARK_ARROW_SEPARATION * Math.cos(angleOfExit + Math.PI / 2);
|
||||
xEnd = xEnd + (ARROW_LENGTH * Math.sin(angleOfExit));
|
||||
yEnd = yEnd + (ARROW_LENGTH * Math.cos(angleOfExit));
|
||||
//Make line between these points.
|
||||
lineSegment = new Polygon(
|
||||
xStart, yStart,
|
||||
xEnd, yEnd
|
||||
@@ -85,12 +148,14 @@ public class MarkArrowFactory {
|
||||
lineSegment.setFill(Color.BLUE);
|
||||
lineSegment.setStrokeWidth(STROKE_WIDTH);
|
||||
lineSegment.setStrokeLineCap(StrokeLineCap.ROUND);
|
||||
//Make arrow head at the angle between these points.
|
||||
Polyline arrowHead = constructArrowHead(
|
||||
90 + Math.toDegrees(Math.atan2(yStart - yEnd, xEnd - xStart)),
|
||||
colour
|
||||
);
|
||||
arrowHead.setLayoutX(xEnd);
|
||||
arrowHead.setLayoutY(yEnd);
|
||||
//Construct arrow.
|
||||
arrow.getChildren().addAll(lineSegment, arrowHead);
|
||||
return arrow;
|
||||
}
|
||||
@@ -113,6 +178,15 @@ public class MarkArrowFactory {
|
||||
return arrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a line rotated to the correct angle and and in the correct position for a mark at
|
||||
* position 0,0. Note that a line segment is assumed to be facing away from the mark so for
|
||||
* entry Starboard make the RoundingSide Port and vice versa.
|
||||
* @param roundingSide Rounding side of an exit arrow. (Reversed for entry)
|
||||
* @param angle Angle of line segment.
|
||||
* @param colour the desired colour of the line.
|
||||
* @return Line segmented at correct rotation centered at (0,0)
|
||||
*/
|
||||
private static Polygon constructLineSegment (RoundingSide roundingSide, double angle, Paint colour) {
|
||||
Polygon lineSegment;
|
||||
angle = Math.toRadians(angle);
|
||||
@@ -122,8 +196,8 @@ public class MarkArrowFactory {
|
||||
double xEnd = xStart + (ARROW_LENGTH * Math.sin(angle));
|
||||
double yEnd = yStart + (ARROW_LENGTH * Math.cos(angle));
|
||||
lineSegment = new Polygon(
|
||||
xStart, yStart,
|
||||
xEnd, yEnd
|
||||
xStart, yStart,
|
||||
xEnd, yEnd
|
||||
);
|
||||
lineSegment.setStroke(colour);
|
||||
lineSegment.setFill(Color.BLUE);
|
||||
@@ -132,6 +206,12 @@ public class MarkArrowFactory {
|
||||
return lineSegment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PolyLine in the shape of an arrow head.
|
||||
* @param rotation direction for the arrow head to point.
|
||||
* @param colour colour of the arrow head
|
||||
* @return the arrowhead shaped PolyLine.
|
||||
*/
|
||||
private static Polyline constructArrowHead (double rotation, Paint colour) {
|
||||
Polyline arrow = new Polyline(
|
||||
-ARROW_HEAD_WIDTH, -ARROW_HEAD_DEPTH,
|
||||
@@ -1,462 +0,0 @@
|
||||
package seng302.visualiser.fxObjects.assets_2D;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyDoubleWrapper;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.AmbientLight;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.PointLight;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Line;
|
||||
import javafx.scene.shape.Polygon;
|
||||
import javafx.scene.shape.Polyline;
|
||||
import javafx.scene.shape.Shape3D;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
import javafx.scene.transform.Translate;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
|
||||
import seng302.visualiser.fxObjects.assets_3D.BoatModel;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelFactory;
|
||||
import seng302.visualiser.fxObjects.assets_3D.ModelType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
|
||||
* a wake object and two text labels to annotate the boat teams name and the boats velocity. The
|
||||
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is
|
||||
* minimized in which case it attempts to store animations and apply them when the window is
|
||||
* maximised.
|
||||
*/
|
||||
public class BoatObject extends Group {
|
||||
|
||||
|
||||
private static final double MODEL_SCALE_FACTOR = 400;
|
||||
private static final double MODEL_X_OFFSET = 0; // standard
|
||||
private static final double MODEL_Y_OFFSET = 0; // standard
|
||||
|
||||
private static final int VIEWPORT_SIZE = 800;
|
||||
|
||||
private static final Color lightColor = Color.rgb(244, 255, 250);
|
||||
private static final Color jewelColor = Color.rgb(0, 190, 222);
|
||||
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SelectedBoatListener {
|
||||
|
||||
void notifySelected(BoatObject boatObject, Boolean isSelected);
|
||||
}
|
||||
|
||||
//Constants for drawing
|
||||
private static final float BOAT_HEIGHT = 15f;
|
||||
private static final float BOAT_WIDTH = 10f;
|
||||
|
||||
private double xVelocity;
|
||||
private double yVelocity;
|
||||
private double lastHeading;
|
||||
private double sailState;
|
||||
//Graphical objects
|
||||
private Polyline trail = new Polyline();
|
||||
private BoatModel boatAssets;
|
||||
private Polygon sail;
|
||||
private Group wake;
|
||||
private Line leftLayLine;
|
||||
private Line rightLayline;
|
||||
private double distanceTravelled, lastRotation;
|
||||
private Point2D lastPoint;
|
||||
private Color colour = Color.BLACK;
|
||||
private Boolean isSelected = false, destinationSet; //All boats are initialised as selected
|
||||
private boolean isPlayer = false;
|
||||
private Rotate rotation = new Rotate(0,0,1);
|
||||
|
||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the default triangular boat polygon.
|
||||
*/
|
||||
public BoatObject() {
|
||||
this(-BOAT_WIDTH / 2, BOAT_HEIGHT / 2,
|
||||
0.0, -BOAT_HEIGHT / 2,
|
||||
BOAT_WIDTH / 2, BOAT_HEIGHT / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the boat being the default polygon. The head of the boat should be
|
||||
* at point (0,0).
|
||||
*
|
||||
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat
|
||||
* polygon.
|
||||
*/
|
||||
public BoatObject(double... points) {
|
||||
initChildren(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the javafx objects that will be the in the group by default.
|
||||
*
|
||||
* @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat
|
||||
* polygon.
|
||||
*/
|
||||
private void initChildren(double... points) {
|
||||
boatAssets = ModelFactory.boatGameView(BoatMeshType.DINGHY, colour);
|
||||
boatAssets.hideSail();
|
||||
boatAssets.getAssets().getTransforms().addAll(
|
||||
// new Rotate(-40, new Point3D(1,0,0)),
|
||||
rotation
|
||||
// new Rotate(-90, new Point3D(0,0,1))
|
||||
);
|
||||
boatAssets.getAssets().getTransforms().add(new Scale(5, 5, 5));
|
||||
// boatAssets.setDrawMode(DrawMode.FILL);
|
||||
// boatAssets.setFill(colour);
|
||||
// boatAssets.setFill(this.colour);
|
||||
// boatAssets.setMaterial(new PhongMaterial(this.colour));
|
||||
boatAssets.getAssets().setOnMouseEntered(event -> {
|
||||
// boatAssets.setFill(Color.FLORALWHITE);
|
||||
// boatAssets.setStroke(Color.RED);
|
||||
// boatAssets.setMaterial(new PhongMaterial(Color.FLORALWHITE));
|
||||
});
|
||||
boatAssets.getAssets().setOnMouseExited(event -> {
|
||||
// boatAssets.setMaterial(new PhongMaterial(this.colour));
|
||||
// boatAssets.setFill(colour);
|
||||
// boatAssets.setFill(this.colour);
|
||||
// boatAssets.setStroke(Color.BLACK);
|
||||
});
|
||||
boatAssets.getAssets().setOnMouseClicked(event -> setIsSelected(!isSelected));
|
||||
boatAssets.getAssets().setCache(true);
|
||||
// boatAssets.setCacheHint(CacheHint.SPEED);
|
||||
|
||||
// annotationBox = new AnnotationBox();
|
||||
// annotationBox.setFill(colour);
|
||||
|
||||
leftLayLine = new Line();
|
||||
rightLayline = new Line();
|
||||
trail.getStrokeDashArray().setAll(5d, 10d);
|
||||
trail.setCache(true);
|
||||
|
||||
wake = ModelFactory.importModel(ModelType.WAKE).getAssets();
|
||||
|
||||
sail = new Polygon(0.0,BOAT_HEIGHT / 4,
|
||||
0.0, BOAT_HEIGHT);
|
||||
sailState = 0;
|
||||
sail.setStrokeWidth(2.0);
|
||||
sail.setStroke(Color.BLACK);
|
||||
sail.setFill(Color.TRANSPARENT);
|
||||
sail.setCache(true);
|
||||
super.getChildren().clear();
|
||||
PointLight pointLight = new PointLight(Color.WHITE);
|
||||
// pointLight.setLightOn(true);
|
||||
pointLight.getTransforms().add(new Translate(0, 0, -30));
|
||||
super.getChildren().add(pointLight);
|
||||
// pointLight = new PointLight(Color.WHITE);
|
||||
//// pointLight.setLightOn(true);
|
||||
// pointLight.getTransforms().add(new Translate(50, 50, -20));
|
||||
// super.getChildren().add(pointLight);
|
||||
// pointLight = new PointLight(Color.WHITE);
|
||||
//// pointLight.setLightOn(true);
|
||||
// pointLight.getTransforms().add(new Translate(50, -50, -20));
|
||||
// super.getChildren().add(pointLight);
|
||||
// pointLight = new PointLight(Color.WHITE);
|
||||
//// pointLight.setLightOn(true);
|
||||
// pointLight.getTransforms().add(new Translate(-50, -50, -20));
|
||||
// super.getChildren().add(pointLight);
|
||||
AmbientLight light = new AmbientLight(new Color(0.5,0.5,0.5,1));
|
||||
super.getChildren().add(light);
|
||||
super.getChildren().addAll(boatAssets.getAssets());
|
||||
}
|
||||
|
||||
public void setFill (Color value) {
|
||||
this.colour = value;
|
||||
PhongMaterial pm = new PhongMaterial(this.colour);
|
||||
pm.setSpecularPower(0.5);
|
||||
pm.setSpecularColor(Color.BLACK);
|
||||
for (int i=0;i<2;i++) {
|
||||
Shape3D s = (Shape3D) boatAssets.getAssets().getChildren().get(i);
|
||||
s.setMaterial(pm);
|
||||
}
|
||||
trail.setStroke(colour);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the boat and its children annotations to coordinates specified
|
||||
* @param x The X coordinate to move the boat to
|
||||
* @param y The Y coordinate to move the boat to
|
||||
* @param rotation The rotation by which the boat moves
|
||||
* @param velocity The velocity the boat is moving
|
||||
* @param sailIn Boolean to toggle sail state.
|
||||
* @param windDir .
|
||||
*/
|
||||
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
|
||||
Double dx = Math.abs(boatAssets.getAssets().getLayoutX() - x);
|
||||
Double dy = Math.abs(boatAssets.getAssets().getLayoutY() - y);
|
||||
Platform.runLater(() -> {
|
||||
rotateTo(rotation, sailIn, windDir);
|
||||
boatAssets.getAssets().setLayoutX(x);
|
||||
boatAssets.getAssets().setLayoutY(y);
|
||||
// if (sailIn) {
|
||||
//// sail.getPoints().clear();
|
||||
//// sail.getPoints().addAll(0.0, 0.0, 4.0, 1.5, 8.0, 3.0, 12.0, 3.5, 16.0, 3.0, 20.0, 1.5, 24.0, 0.0);
|
||||
//// sail.getPoints().addAll(0.0, 0.0, 24.0, 0.0);
|
||||
// sail.setLayoutX(x);
|
||||
// sail.setLayoutY(y);
|
||||
// } else {
|
||||
//// animateSail();
|
||||
// sail.setLayoutX(x);
|
||||
// sail.setLayoutY(y);
|
||||
// }
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
});
|
||||
// wake.setRotation(rotation, velocity);
|
||||
// rotateTo(rotation);
|
||||
// boatAssets.setLayoutX(x);
|
||||
// boatAssets.setLayoutY(y);
|
||||
// wake.setLayoutX(x);
|
||||
// wake.setLayoutY(y);
|
||||
// wake.rotate(rotation);
|
||||
|
||||
// wake.setRotation(rotation, groundSpeed);
|
||||
// isStopped = false;
|
||||
// destinationSet = true;
|
||||
lastRotation = rotation;
|
||||
|
||||
distanceTravelled += Math.sqrt((dx * dx) + (dy * dy));
|
||||
|
||||
if (distanceTravelled > 15 && isPlayer) {
|
||||
distanceTravelled = 0d;
|
||||
Platform.runLater(() -> trail.getPoints().addAll(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
private Double normalizeHeading(double heading, double windDirection) {
|
||||
Double normalizedHeading = heading - windDirection;
|
||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
|
||||
return normalizedHeading;
|
||||
}
|
||||
|
||||
|
||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||
rotation.setAngle(heading);
|
||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||
if (sailsIn) {
|
||||
boatAssets.showSail();
|
||||
Double sailWindOffset = 30.0;
|
||||
Double upwindAngleLimit = 15.0;
|
||||
Double downwindAngleLimit = 10.0; //Upwind from normalised horizontal
|
||||
Double normalizedHeading = normalizeHeading(heading, windDir);
|
||||
System.out.println("normalizedHeading = " + normalizedHeading);
|
||||
if (normalizedHeading < 180) {
|
||||
if (normalizedHeading < sailWindOffset + upwindAngleLimit){
|
||||
boatAssets.rotateSail(-upwindAngleLimit);
|
||||
} else if (normalizedHeading > 90 + sailWindOffset){
|
||||
boatAssets.rotateSail(-90 + downwindAngleLimit);
|
||||
} else {
|
||||
boatAssets.rotateSail(-heading + windDir + sailWindOffset);
|
||||
}
|
||||
} else {
|
||||
if (normalizedHeading > 360 - (sailWindOffset + upwindAngleLimit)) {
|
||||
boatAssets.rotateSail(upwindAngleLimit);
|
||||
} else if (normalizedHeading < 270 - sailWindOffset) {
|
||||
boatAssets.rotateSail(90 - downwindAngleLimit);
|
||||
} else {
|
||||
System.out.println("windDir = " + windDir);
|
||||
boatAssets.rotateSail(-heading + windDir - sailWindOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boatAssets.hideSail();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void animateSail(){
|
||||
Double[] points = new Double[200];
|
||||
double amplitude = 2.0;
|
||||
double period = 10;
|
||||
for (int i = 0; i < 50; i++) {
|
||||
points[i * 2] = amplitude * Math.sin(((Math.PI * i) / period + sailState));
|
||||
points[i * 2 + 1] = (double) (BOAT_HEIGHT * i) / BOAT_HEIGHT / 2;
|
||||
points[199 - (i * 2)] = (double) (BOAT_HEIGHT * i) / BOAT_HEIGHT / 2;
|
||||
points[199 - (i * 2 + 1)] = amplitude * Math.sin(((Math.PI * i) / period + sailState));
|
||||
}
|
||||
if (sailState == - 2 * Math.PI) {
|
||||
sailState = 0;
|
||||
} else {
|
||||
sailState = sailState - Math.PI / 5;
|
||||
}
|
||||
sail.getPoints().clear();
|
||||
sail.getPoints().addAll(points);
|
||||
|
||||
}
|
||||
|
||||
public void updateLocation() {
|
||||
// boatAssets.getTransforms().add(new Rotate(2, new Point3D(1,1,1)));
|
||||
// double dx = xVelocity / 60;
|
||||
// double dy = yVelocity / 60;
|
||||
//
|
||||
// distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
||||
// moveGroupBy(dx, dy);
|
||||
//
|
||||
// if (distanceTravelled > 70) {
|
||||
// distanceTravelled = 0d;
|
||||
//
|
||||
// if (lastPoint != null) {
|
||||
// Line l = new Line(
|
||||
// lastPoint.getX(),
|
||||
// lastPoint.getY(),
|
||||
// boatAssets.getLayoutX(),
|
||||
// boatAssets.getLayoutY()
|
||||
// );
|
||||
// l.getStrokeDashArray().setAll(3d, 7d);
|
||||
// l.setStroke(colour);
|
||||
// l.setCache(true);
|
||||
// l.setCacheHint(CacheHint.SPEED);
|
||||
// lineGroup.getChildren().add(l);
|
||||
// }
|
||||
// lastPoint = new Point2D(boatAssets.getLayoutX(), boatAssets.getLayoutY());
|
||||
// }
|
||||
// wake.updatePosition();
|
||||
}
|
||||
|
||||
// /**
|
||||
// * This function works out if a boat is going upwind or down wind. It looks at the boats current position, the next
|
||||
// * gates position and the current wind
|
||||
// * If bot the wind vector from the next gate and the boat from the next gate lay on the same side, then the boat is
|
||||
// * going up wind, if they are on different sides of the gate, then the boat is going downwind
|
||||
// * @param canvasController
|
||||
// */
|
||||
// public Boolean isUpwindLeg(GameViewController canvasController, Mark nextMark) {
|
||||
//
|
||||
// Double windAngle = StreamParser.getWindDirection();
|
||||
// GateMark thisGateMark = (GateMark) nextMark;
|
||||
// SingleMark nextMark1 = thisGateMark.getSingleMark1();
|
||||
// SingleMark nextMark2 = thisGateMark.getSingleMark2();
|
||||
// Point2D nextMarkPoint1 = canvasController.findScaledXY(nextMark1.getLatitude(), nextMark1.getLongitude());
|
||||
// Point2D nextMarkPoint2 = canvasController.findScaledXY(nextMark2.getLatitude(), nextMark2.getLongitude());
|
||||
//
|
||||
// Point2D boatCurrentPoint = new Point2D(boatAssets.getLayoutX(), boatAssets.getLayoutY());
|
||||
// Point2D windTestPoint = GeoUtility.makeArbitraryVectorPoint(nextMarkPoint1, windAngle, 10d);
|
||||
//
|
||||
//
|
||||
// Integer boatLineFuncResult = GeoUtility.lineFunction(nextMarkPoint1, nextMarkPoint2, boatCurrentPoint);
|
||||
// Integer windLineFuncResult = GeoUtility.lineFunction(nextMarkPoint1, nextMarkPoint2, windTestPoint);
|
||||
//
|
||||
//
|
||||
// /*
|
||||
// If both the wind vector from the gate and the boat from the gate are on the same side of that gate, then the
|
||||
// boat is travelling into the wind. thus upwind. Otherwise if they are on different sides, then the boat is going
|
||||
// with the wind.
|
||||
// */
|
||||
// return boatLineFuncResult.equals(windLineFuncResult);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
public void setIsSelected(Boolean isSelected) {
|
||||
updateListener(isSelected);
|
||||
this.isSelected = isSelected;
|
||||
setLineGroupVisible(isSelected);
|
||||
setWakeVisible(isSelected);
|
||||
setLayLinesVisible(isSelected);
|
||||
}
|
||||
|
||||
public void setVisibility (boolean teamName, boolean velocity, boolean estTime, boolean legTime,
|
||||
boolean trail, boolean wake) {
|
||||
// boatAnnotations.setVisible(teamName, velocity, estTime, legTime);
|
||||
// this.wake.setVisible(wake);
|
||||
this.trail.setVisible(trail);
|
||||
}
|
||||
|
||||
public void setLineGroupVisible(Boolean visible) {
|
||||
trail.setVisible(visible);
|
||||
}
|
||||
|
||||
public void setWakeVisible(Boolean visible) {
|
||||
// wake.setVisible(visible);
|
||||
}
|
||||
|
||||
public void setLayLinesVisible(Boolean visible) {
|
||||
leftLayLine.setVisible(visible);
|
||||
rightLayline.setVisible(visible);
|
||||
}
|
||||
|
||||
public void setLaylines(Line line1, Line line2) {
|
||||
this.leftLayLine = line1;
|
||||
this.rightLayline = line2;
|
||||
}
|
||||
|
||||
public ArrayList<Line> getLaylines() {
|
||||
ArrayList<Line> laylines = new ArrayList<>();
|
||||
laylines.add(leftLayLine);
|
||||
laylines.add(rightLayline);
|
||||
return laylines;
|
||||
}
|
||||
|
||||
public Group getWake () {
|
||||
return wake;
|
||||
}
|
||||
|
||||
public Node getTrail() {
|
||||
return trail;
|
||||
}
|
||||
|
||||
public Double getBoatLayoutX() {
|
||||
return boatAssets.getAssets().getLayoutX();
|
||||
}
|
||||
|
||||
|
||||
public Double getBoatLayoutY() {
|
||||
return boatAssets.getAssets().getLayoutY();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this boat to appear highlighted
|
||||
*/
|
||||
public void setAsPlayer() {
|
||||
// boatAssets.getPoints().setAll(
|
||||
// -BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75,
|
||||
// 0.0, -BOAT_HEIGHT / 1.75,
|
||||
// BOAT_WIDTH / 1.75, BOAT_HEIGHT / 1.75
|
||||
// );
|
||||
// boatAssets.setStroke(Color.BLACK);
|
||||
// boatAssets.setStrokeWidth(2);
|
||||
// boatAssets.setStrokeLineCap(StrokeLineCap.ROUND);
|
||||
isPlayer = true;
|
||||
animateSail();
|
||||
}
|
||||
|
||||
public void setTrajectory(double heading, double velocity, double windDir) {
|
||||
// wake.r(lastHeading - heading, velocity);
|
||||
// rotateTo(heading, false, windDir);
|
||||
xVelocity = Math.cos(Math.toRadians(heading)) * velocity;
|
||||
yVelocity = Math.sin(Math.toRadians(heading)) * velocity;
|
||||
lastHeading = heading;
|
||||
}
|
||||
|
||||
public Boolean getSelected() {
|
||||
return isSelected;
|
||||
}
|
||||
|
||||
public void setTrajectory(double heading, double velocity, double scaleFactorX, double scaleFactorY) {
|
||||
// wake.setRotation(lastHeading - heading, velocity);
|
||||
// rotateTo(heading);
|
||||
// xVelocity = Math.cos(Math.toRadians(heading)) * velocity * scaleFactorX;
|
||||
// yVelocity = Math.sin(Math.toRadians(heading)) * velocity * scaleFactorY;
|
||||
lastHeading = heading;
|
||||
}
|
||||
|
||||
private void updateListener(Boolean isSelected) {
|
||||
for (SelectedBoatListener sbl : selectedBoatListenerListeners) {
|
||||
sbl.notifySelected(this, isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||
selectedBoatListenerListeners.add(sbl);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.shape.Circle;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
|
||||
/**
|
||||
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
||||
|
||||
@@ -58,7 +58,7 @@ public class BoatModel extends Model {
|
||||
*/
|
||||
public void changeColour(Color newColour) {
|
||||
changeColourChild(HULL_INDEX, newColour);
|
||||
changeColourChild(SAIL_INDEX, newColour);
|
||||
changeColourChild(MAST_INDEX, newColour);
|
||||
}
|
||||
|
||||
private void changeColourChild(int index, Color newColour) {
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
package seng302.visualiser.fxObjects.assets_3D;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.transform.Rotate;
|
||||
|
||||
/**
|
||||
* BoatGroup is a javafx group that by default contains a graphical objects for representing a 2
|
||||
* dimensional boat. It contains a single polygon for the boat, a group of lines to show it's path,
|
||||
* a wake object and two text labels to annotate the boat teams name and the boats velocity. The
|
||||
* boat will update it's position onscreen everytime UpdatePosition is called unless the window is
|
||||
* minimized in which case it attempts to store animations and apply them when the window is
|
||||
* maximised.
|
||||
*/
|
||||
public class BoatObject extends Group {
|
||||
|
||||
@FunctionalInterface
|
||||
public interface SelectedBoatListener {
|
||||
|
||||
void notifySelected(BoatObject boatObject, Boolean isSelected);
|
||||
}
|
||||
|
||||
private BoatModel boatAssets;
|
||||
private Group wake;
|
||||
private Color colour = Color.BLACK;
|
||||
private Boolean isSelected = false;
|
||||
private Rotate rotation = new Rotate(0,0,1);
|
||||
|
||||
private List<SelectedBoatListener> selectedBoatListenerListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a BoatGroup with the default triangular boat polygon.
|
||||
*/
|
||||
public BoatObject() {
|
||||
boatAssets = ModelFactory.boatGameView(BoatMeshType.DINGHY, colour);
|
||||
boatAssets.hideSail();
|
||||
boatAssets.getAssets().getTransforms().addAll(
|
||||
rotation
|
||||
);
|
||||
boatAssets.getAssets().setOnMouseClicked(event -> {
|
||||
setIsSelected(!isSelected);
|
||||
updateListeners();
|
||||
});
|
||||
boatAssets.getAssets().setCache(true);
|
||||
wake = ModelFactory.importModel(ModelType.WAKE).getAssets();
|
||||
super.getChildren().addAll(boatAssets.getAssets());
|
||||
}
|
||||
|
||||
public void setFill (Color value) {
|
||||
this.colour = value;
|
||||
boatAssets.changeColour(colour);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Moves the boat and its children annotations to coordinates specified
|
||||
* @param x The X coordinate to move the boat to
|
||||
* @param y The Y coordinate to move the boat to
|
||||
* @param rotation The rotation by which the boat moves
|
||||
* @param velocity The velocity the boat is moving
|
||||
* @param sailIn Boolean to toggle sail state.
|
||||
* @param windDir .
|
||||
*/
|
||||
public void moveTo(double x, double y, double rotation, double velocity, Boolean sailIn, double windDir) {
|
||||
Double dx = Math.abs(boatAssets.getAssets().getLayoutX() - x);
|
||||
Double dy = Math.abs(boatAssets.getAssets().getLayoutY() - y);
|
||||
Platform.runLater(() -> {
|
||||
rotateTo(rotation, sailIn, windDir);
|
||||
this.layoutXProperty().setValue(x);
|
||||
this.layoutYProperty().setValue(y);
|
||||
wake.setLayoutX(x);
|
||||
wake.setLayoutY(y);
|
||||
});
|
||||
}
|
||||
|
||||
private Double normalizeHeading(double heading, double windDirection) {
|
||||
Double normalizedHeading = heading - windDirection;
|
||||
normalizedHeading = (double) Math.floorMod(normalizedHeading.longValue(), 360L);
|
||||
return normalizedHeading;
|
||||
}
|
||||
|
||||
|
||||
private void rotateTo(double heading, boolean sailsIn, double windDir) {
|
||||
rotation.setAngle(heading);
|
||||
wake.getTransforms().setAll(new Rotate(heading, new Point3D(0,0,1)));
|
||||
if (sailsIn) {
|
||||
boatAssets.showSail();
|
||||
Double sailWindOffset = 30.0;
|
||||
Double upwindAngleLimit = 15.0;
|
||||
Double downwindAngleLimit = 10.0; //Upwind from normalised horizontal
|
||||
Double normalizedHeading = normalizeHeading(heading, windDir);
|
||||
if (normalizedHeading < 180) {
|
||||
if (normalizedHeading < sailWindOffset + upwindAngleLimit){
|
||||
boatAssets.rotateSail(-upwindAngleLimit);
|
||||
} else if (normalizedHeading > 90 + sailWindOffset){
|
||||
boatAssets.rotateSail(-90 + downwindAngleLimit);
|
||||
} else {
|
||||
boatAssets.rotateSail(-heading + windDir + sailWindOffset);
|
||||
}
|
||||
} else {
|
||||
if (normalizedHeading > 360 - (sailWindOffset + upwindAngleLimit)) {
|
||||
boatAssets.rotateSail(upwindAngleLimit);
|
||||
} else if (normalizedHeading < 270 - sailWindOffset) {
|
||||
boatAssets.rotateSail(90 - downwindAngleLimit);
|
||||
} else {
|
||||
boatAssets.rotateSail(-heading + windDir - sailWindOffset);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boatAssets.hideSail();
|
||||
}
|
||||
}
|
||||
|
||||
public Group getWake () {
|
||||
return wake;
|
||||
}
|
||||
|
||||
public void setIsSelected(Boolean isSelected) {
|
||||
this.isSelected = isSelected;
|
||||
}
|
||||
|
||||
private void updateListeners() {
|
||||
for (SelectedBoatListener sbl : selectedBoatListenerListeners) {
|
||||
sbl.notifySelected(this, this.isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
public void addSelectedBoatListener(SelectedBoatListener sbl) {
|
||||
selectedBoatListenerListeners.add(sbl);
|
||||
}
|
||||
}
|
||||
@@ -4,45 +4,42 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.transform.Scale;
|
||||
import seng302.visualiser.fxObjects.assets_2D.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.assets_2D.MarkArrowFactory.RoundingSide;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory;
|
||||
import seng302.visualiser.fxObjects.MarkArrowFactory.RoundingSide;
|
||||
|
||||
/**
|
||||
* Visual object for a mark. Contains a coloured circle and any specified arrows.
|
||||
*/
|
||||
public class Marker3D extends Group {
|
||||
|
||||
private Group mark = ModelFactory.importModel(ModelType.PLAIN_MARKER).getAssets();
|
||||
private Paint colour = Color.BLACK;
|
||||
private Model mark;
|
||||
private List<Group> enterArrows = new ArrayList<>();
|
||||
private List<Group> exitArrows = new ArrayList<>();
|
||||
private int enterArrowIndex = 0;
|
||||
private int exitArrowIndex = 0;
|
||||
private ModelType markType;
|
||||
private ModelType arrowType;
|
||||
|
||||
/**
|
||||
* Creates a new Marker containing only a circle. The default colour is black.
|
||||
*/
|
||||
public Marker3D() {
|
||||
// mark.setRadius(5);
|
||||
// mark.setCenterX(0);
|
||||
// mark.setCenterY(0);
|
||||
Platform.runLater(() -> {
|
||||
mark.getTransforms().add(new Scale(5,5,5));
|
||||
this.getChildren().addAll(mark, new Group());
|
||||
}); //Empty group placeholder or arrows.
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Marker containing only a circle of the given colour.
|
||||
* @param colour the desired colour for the marker.
|
||||
*/
|
||||
public Marker3D(Paint colour) {
|
||||
this();
|
||||
this.colour = colour;
|
||||
// mark.setFill(colour);
|
||||
public Marker3D(ModelType modelType) {
|
||||
markType = modelType;
|
||||
switch (markType) {
|
||||
case PLAIN_MARKER:
|
||||
arrowType = ModelType.PLAIN_ARROW;
|
||||
break;
|
||||
case FINISH_MARKER:
|
||||
arrowType = ModelType.FINISH_ARROW;
|
||||
break;
|
||||
case START_MARKER:
|
||||
arrowType = ModelType.START_ARROW;
|
||||
break;
|
||||
}
|
||||
mark = ModelFactory.importModel(modelType);
|
||||
Platform.runLater(() ->
|
||||
this.getChildren().addAll(mark.getAssets())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,13 +50,13 @@ public class Marker3D extends Group {
|
||||
* @param exitAngle The angle the arrow wil point from the marker.
|
||||
*/
|
||||
public void addArrows(RoundingSide roundingSide, double entryAngle,
|
||||
double exitAngle) {
|
||||
double exitAngle) {
|
||||
//Change Color.GRAY to this.colour to revert all gray arrows.
|
||||
enterArrows.add(
|
||||
MarkArrowFactory.constructEntryArrow(roundingSide, entryAngle, exitAngle, Color.GRAY)
|
||||
MarkArrowFactory.constructEntryArrow3D(roundingSide, entryAngle, arrowType).getAssets()
|
||||
);
|
||||
exitArrows.add(
|
||||
MarkArrowFactory.constructExitArrow(roundingSide, exitAngle, Color.GRAY)
|
||||
MarkArrowFactory.constructExitArrow3D(roundingSide, exitAngle, arrowType).getAssets()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,12 +78,9 @@ public class Marker3D extends Group {
|
||||
|
||||
private void showArrow(List<Group> arrowList, int arrowListIndex) {
|
||||
if (arrowListIndex < arrowList.size()) {
|
||||
if (arrowListIndex == 1) {;
|
||||
}
|
||||
Platform.runLater(() -> {
|
||||
this.getChildren().remove(1);
|
||||
this.getChildren().add(arrowList.get(arrowListIndex));
|
||||
});
|
||||
Platform.runLater(() ->
|
||||
this.getChildren().setAll(mark.getAssets(), arrowList.get(arrowListIndex))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +88,6 @@ public class Marker3D extends Group {
|
||||
* Hides all arrows.
|
||||
*/
|
||||
public void hideAllArrows() {
|
||||
Platform.runLater(() -> this.getChildren().setAll(mark, new Group()));
|
||||
Platform.runLater(() -> this.getChildren().setAll(mark.getAssets()));
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ import javafx.scene.Group;
|
||||
*/
|
||||
public class Model {
|
||||
|
||||
AnimationTimer animationTimer;
|
||||
Group assets;
|
||||
protected AnimationTimer animationTimer;
|
||||
protected Group assets;
|
||||
|
||||
Model (Group assets, AnimationTimer animation) {
|
||||
public Model (Group assets, AnimationTimer animation) {
|
||||
this.assets = assets;
|
||||
this.animationTimer = animation;
|
||||
if (animation != null) {
|
||||
@@ -25,7 +25,7 @@ public class Model {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimation(AnimationTimer animation) {
|
||||
void setAnimation(AnimationTimer animation) {
|
||||
animationTimer = animation;
|
||||
if (animation != null) {
|
||||
animation.start();
|
||||
|
||||
@@ -9,6 +9,7 @@ import javafx.scene.CacheHint;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.PhongMaterial;
|
||||
import javafx.scene.shape.Circle;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.scene.transform.Scale;
|
||||
@@ -78,7 +79,7 @@ public class ModelFactory {
|
||||
Group boatAssets = getUnmodifiedBoatModel(boatType, primaryColour);
|
||||
boatAssets.getTransforms().setAll(
|
||||
new Rotate(-90, new Point3D(0,0,1)),
|
||||
new Scale(0.06, 0.06, 0.06)
|
||||
new Scale(0.3, 0.3, 0.3)
|
||||
);
|
||||
return new BoatModel(boatAssets, null, boatType);
|
||||
}
|
||||
@@ -137,6 +138,10 @@ public class ModelFactory {
|
||||
return makeTrail(assets);
|
||||
case PLAYER_IDENTIFIER:
|
||||
return makeIdentifierIcon(assets);
|
||||
case START_ARROW:
|
||||
case FINISH_ARROW:
|
||||
case PLAIN_ARROW:
|
||||
makeArrow(assets);
|
||||
default:
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
@@ -174,23 +179,17 @@ public class ModelFactory {
|
||||
}
|
||||
|
||||
private static Model makeOcean(Group group) {
|
||||
// group.setScaleY(Double.MAX_VALUE);
|
||||
// group.setScaleX(Double.MAX_VALUE);
|
||||
group.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1, 0, 0)),
|
||||
new Scale(10,4,10)
|
||||
Circle ocean = new Circle(
|
||||
0,0,250, Color.SKYBLUE
|
||||
);
|
||||
// group.getChildren().add(new AmbientLight());
|
||||
// Circle ocean = new Circle(0,0,500, Color.SKYBLUE);
|
||||
// ocean.setStroke(Color.TRANSPARENT);
|
||||
// group.getChildren().add(ocean);
|
||||
ocean.setStroke(Color.TRANSPARENT);
|
||||
group.getChildren().add(ocean);
|
||||
return new Model(new Group(group), null);
|
||||
}
|
||||
|
||||
private static Model makeBarrier(Group assets) {
|
||||
assets.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1,0,0)),
|
||||
new Scale(1.5,1.5,1.5)
|
||||
new Rotate(90, new Point3D(1,0,0))
|
||||
);
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
@@ -213,7 +212,8 @@ public class ModelFactory {
|
||||
|
||||
private static Model makeTrail(Group trailPiece) {
|
||||
trailPiece.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(0,0,1))
|
||||
new Rotate(-90, new Point3D(0,0,1)),
|
||||
new Rotate(90, new Point3D(1,0,0))
|
||||
);
|
||||
return new Model(new Group(trailPiece), null);
|
||||
}
|
||||
@@ -225,4 +225,12 @@ public class ModelFactory {
|
||||
);
|
||||
return new Model(assets, null);
|
||||
}
|
||||
|
||||
private static Model makeArrow(Group assets) {
|
||||
assets.getTransforms().addAll(
|
||||
new Rotate(90, new Point3D(1,0,0)),
|
||||
new Scale(0.1, 0.1, 0.1)
|
||||
);
|
||||
return new Model(new Group(assets), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public enum ModelType {
|
||||
START_MARKER ("start_marker.dae"),
|
||||
PLAIN_MARKER ("plain_marker.dae"),
|
||||
MARK_AREA ("mark_area.dae"),
|
||||
OCEAN ("ocean.dae"),
|
||||
OCEAN (null),
|
||||
BORDER_PYLON ("barrier_pole.dae"),
|
||||
BORDER_BARRIER ("barrier_segment.dae"),
|
||||
FINISH_LINE ("finish_line.dae"),
|
||||
@@ -19,12 +19,14 @@ public enum ModelType {
|
||||
GATE_LINE ("gate_line.dae"),
|
||||
WAKE ("wake.dae"),
|
||||
TRAIL_SEGMENT ("trail_segment.dae"),
|
||||
PLAYER_IDENTIFIER ("player_identifier.dae");
|
||||
PLAYER_IDENTIFIER ("player_identifier.dae"),
|
||||
PLAIN_ARROW ("arrow.dae"),
|
||||
START_ARROW ("finish_arrow.dae"),
|
||||
FINISH_ARROW ("start_arrow.dae");
|
||||
|
||||
final String filename;
|
||||
|
||||
ModelType(String filename) {
|
||||
this.filename = filename;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user