diff --git a/dedicatedServer/src/main/java/app/App.java b/dedicatedServer/src/main/java/app/App.java index 3b36c43e..b2228131 100644 --- a/dedicatedServer/src/main/java/app/App.java +++ b/dedicatedServer/src/main/java/app/App.java @@ -21,7 +21,7 @@ public class App extends Application { public void start(Stage primaryStage) { try { //TODO should read a configuration file to configure server? - Event raceEvent = new Event(false, 0); + Event raceEvent = new Event(false, 0, 5); } catch (Exception e) { diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index 602aed43..1a70b65c 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -40,24 +40,17 @@ public class Event { private String raceXML; private String regattaXML; private String boatXML; - private XMLFileType xmlFileType; - private Polars boatPolars; - /** * Data sources containing data from the xml files. */ - RaceDataSource raceDataSource; - BoatDataSource boatDataSource; - RegattaDataSource regattaDataSource; - - + private RaceDataSource raceDataSource; + private BoatDataSource boatDataSource; + private RegattaDataSource regattaDataSource; private ConnectionAcceptor connectionAcceptor; private LatestMessages latestMessages; - private CompositeCommand compositeCommand; - /** * This is used to allocate source IDs. */ @@ -66,22 +59,17 @@ public class Event { private RaceLogic raceLogic; private Thread raceThread; - private Thread connectionThread; - private int mapIndex; - - - - /** * Constructs an event, using various XML files. * @param singlePlayer Whether or not to create a single player event. * @param mapIndex Specifies which map to use. * @throws EventConstructionException Thrown if we cannot create an Event for any reason. */ - public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException { + public Event(boolean singlePlayer, int mapIndex, int raceLength) throws + EventConstructionException { PolarParser.parseNewPolars("mock/polars/acc_polars.csv"); this.mapIndex = mapIndex; String raceXMLFile; @@ -125,8 +113,8 @@ public class Event { } else { this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle); - this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, windSpeed, 15 * 60 * 1000); - + this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, + windSpeed, raceLength); } this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index af520a83..502e6ab6 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -21,6 +21,8 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; /** * Helper Class for creating a Race XML @@ -212,12 +214,16 @@ public class RaceXMLCreator { double averageSpeed = (bestDownWindSpeed + bestUpWindSpeed) / 2; double raceApproximateTime = getRaceLength(race, averageSpeed); double scale = milliseconds / raceApproximateTime; + Map hasBeenScaled = new HashMap<>(); for (XMLCorner cm: race.getCompoundMarkSequence().getCorner()){ int index = cm.getCompoundMarkID() - 1; XMLCompoundMark mark = race.getCourse().getCompoundMark().get(index); - for (XMLMark m: mark.getMark()){ - scalePoint(m, center, scale); + if (!hasBeenScaled.containsKey(mark)) { + for (XMLMark m : mark.getMark()) { + scalePoint(m, center, scale); + } } + hasBeenScaled.put(mark, true); } for (XMLLimit limit: race.getCourseLimit().getLimit()){ scalePoint(limit, center, scale); @@ -319,8 +325,13 @@ public class RaceXMLCreator { } - - + /** + * sets the current race time of the xml + * @param raceXML race xml to alter + * @param racePrestartTime prestart time + * @param racePreparatoryTime preparatory time + * @deprecated this should be used from the RaceXMLCreator not from this function + */ public static void setRaceXMLAtCurrentTimeToNow(XMLRace raceXML, long racePrestartTime, long racePreparatoryTime){ //The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute. long millisecondsToAdd = racePrestartTime + racePreparatoryTime; diff --git a/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java index 33583a38..dac62be0 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java @@ -4,6 +4,8 @@ import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.control.Slider; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import mock.app.Event; @@ -28,8 +30,12 @@ import java.util.logging.Logger; */ public class HostGameController extends Controller { private @FXML ImageView mapImage; + private @FXML Slider sliderLength; + private @FXML Label lblLength; private ArrayList listOfMaps; private int currentMapIndex = 0; + private int selectedRaceLength; // in minutes + private final int MAX_RACE_LENGTH = 30; // in minutes private DatagramSocket udpSocket; private MatchBrowserInterface matchBrowserInterface; @@ -37,8 +43,33 @@ public class HostGameController extends Controller { loadMaps(); this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket(); this.matchBrowserInterface = MatchBrowserSingleton.getInstance().getMatchBrowserInterface(); + setRaceLengthSlider(); } + /** + * Sets up the values and display for a slider object which allows a user + * to select how many minutes long they would like their race to be. + */ + private void setRaceLengthSlider(){ + // set the listener to update the label + sliderLength.valueProperty().addListener((ov, old_val, new_val) -> { + selectedRaceLength = new_val.intValue(); + if (selectedRaceLength == 1){ + lblLength.setText(selectedRaceLength + " minute."); + } else { + lblLength.setText(selectedRaceLength + " minutes."); + } + }); + + // set values and marks to be displayed + sliderLength.setMin(2); + sliderLength.setMax(MAX_RACE_LENGTH); + sliderLength.setShowTickLabels(true); + sliderLength.setMajorTickUnit(MAX_RACE_LENGTH-1); + sliderLength.setBlockIncrement(1); + + sliderLength.getStylesheets().add("/css/slider.css"); + } /** @@ -64,7 +95,8 @@ public class HostGameController extends Controller { */ public void hostGamePressed() { try { - App.game = new Event(false, currentMapIndex); + App.game = new Event(false, currentMapIndex, + selectedRaceLength*60*1000); App.gameType = currentMapIndex; HttpMatchBrowserHost matchBrowserHost = new HttpMatchBrowserHost(); diff --git a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java index 38816a0e..5953bf92 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java @@ -40,7 +40,7 @@ public class LobbyController extends Controller { private @FXML TextField addressFld; private @FXML TextField portFld; - private ObservableList connections; + private ObservableList allConnections; private ObservableList customConnections; private AudioClip sound; @@ -51,12 +51,20 @@ public class LobbyController extends Controller { public void initialize() { httpMatchBrowserClient = new HttpMatchBrowserClient(); + httpMatchBrowserClient.connections.addListener(new ListChangeListener() { + @Override + public void onChanged(Change c) { + refreshTable(); + } + }); + new Thread(httpMatchBrowserClient, "Match Client").start(); // set up the connection table customConnections = FXCollections.observableArrayList(); + allConnections = FXCollections.observableArrayList(); //connections.add(new RaceConnection("localhost", 4942, "Local Game")); - lobbyTable.setItems(httpMatchBrowserClient.connections); + lobbyTable.setItems(allConnections); gameNameColumn.setCellValueFactory(cellData -> cellData.getValue().gamenameProperty()); hostNameColumn.setCellValueFactory(cellData -> cellData.getValue().hostnameProperty()); statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty()); @@ -82,8 +90,14 @@ public class LobbyController extends Controller { public void refreshBtnPressed(){ sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/buttonpress.wav").toExternalForm()); sound.play(); + refreshTable(); + } + + private void refreshTable() { + allConnections.clear(); + addCustomGames(); addServerGames(); - for(RaceConnection connection: connections) { + for(RaceConnection connection: allConnections) { connection.check(); } try { @@ -144,9 +158,9 @@ public class LobbyController extends Controller { try { int port = Integer.parseInt(portString); customConnections.add(new RaceConnection(hostName, port, "Boat Game")); - connections.addAll(customConnections); addressFld.clear(); portFld.clear(); + refreshTable(); } catch (NumberFormatException e) { System.err.println("Port number entered is not a number"); } @@ -173,17 +187,14 @@ public class LobbyController extends Controller { * Adds the games received from the server */ private void addServerGames() { - httpMatchBrowserClient.connections.addAll(customConnections); - httpMatchBrowserClient.connections.addListener(new ListChangeListener() { - @Override - public void onChanged(Change c) { - refreshBtnPressed(); - } - }); - + allConnections.addAll(httpMatchBrowserClient.connections); /* for (HostGame game : matchBrowserLobbyInterface.getGames()) { connections.add(new RaceConnection(game.getIp(), 4942, "Boat Game")); }*/ } + + private void addCustomGames() { + allConnections.addAll(customConnections); + } } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/NextMarkController.java b/racevisionGame/src/main/java/visualiser/Controllers/NextMarkController.java new file mode 100644 index 00000000..20da6f3c --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/Controllers/NextMarkController.java @@ -0,0 +1,123 @@ +package visualiser.Controllers; + +import com.interactivemesh.jfx.importer.stl.StlMeshImporter; +import javafx.animation.AnimationTimer; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.geometry.Point3D; +import javafx.scene.AmbientLight; +import javafx.scene.control.Label; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.paint.PhongMaterial; +import javafx.scene.shape.Cylinder; +import javafx.scene.shape.MeshView; +import javafx.scene.shape.Shape3D; +import javafx.scene.transform.Rotate; +import shared.model.Bearing; +import shared.model.CompoundMark; +import shared.model.GPSCoordinate; +import visualiser.layout.Annotation3D; +import visualiser.layout.Assets3D; +import visualiser.layout.Subject3D; +import visualiser.layout.View3D; +import visualiser.model.VisualiserBoat; + +import java.net.URL; +import java.util.Observable; +import java.util.Observer; + +public class NextMarkController { + private @FXML StackPane arrowStackPane2d; + private @FXML StackPane arrowStackPane3d; + private @FXML Pane pane2d; + private @FXML Pane pane3d; + + private VisualiserBoat boat; + + public void initialiseArrowView(VisualiserBoat boat) { + this.boat = boat; + pane2d.setVisible(true); + pane3d.setVisible(false); + initialise2dArrowView(); + initialise3dArrowView(); + } + + private void initialise2dArrowView() { + AnimationTimer arrow2d = new AnimationTimer() { + @Override + public void handle(long now) { + if (boat.getCurrentLeg().getEndCompoundMark() != null) { + CompoundMark target = boat.getCurrentLeg().getEndCompoundMark(); + Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); + arrowStackPane2d.setRotate(headingToMark.degrees()); + } else { + stop(); + } + } + }; + arrow2d.start(); + } + + private void initialise3dArrowView() { + ObservableList viewSubjects = FXCollections.observableArrayList(); + String arrowPath = "assets/mark_arrow.x3d"; + + Shape3D arrow = Assets3D.loadX3d(arrowPath); + + arrow.setScaleX(25); + arrow.setScaleY(25); + arrow.setScaleZ(100); + arrow.setRotationAxis(new Point3D(1,0,0)); + + arrowStackPane3d.getChildren().add(arrow); + + AnimationTimer arrow3d = new AnimationTimer() { + @Override + public void handle(long now) { + if (boat.getCurrentLeg().getEndCompoundMark() != null) { + arrow.getTransforms().clear(); + double zRotation = calculateZRotate(); + arrow.setRotate(calculateXRotate(zRotation)); + arrow.getTransforms().add(new Rotate(zRotation, new Point3D(0, 0, 1))); + } else { + stop(); + } + } + }; + arrow3d.start(); + } + + public void show2d() { + pane3d.setVisible(false); + pane2d.setVisible(true); + } + + public void show3d() { + pane2d.setVisible(false); + pane3d.setVisible(true); + } + + private double calculateZRotate() { + CompoundMark target = boat.getCurrentLeg().getEndCompoundMark(); + Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); + return -headingToMark.degrees() + boat.getBearing().degrees() + 180; + } + + private double calculateXRotate(double zRotation) { +// if (zRotation > 360) { +// zRotation -=360; +// } else if (zRotation < 0) { +// zRotation += 360; +// } +// +// if (zRotation > 180) { +// zRotation = 360 - zRotation; +// } + + return 70; + //return 90 - 20 * Math.cos(Math.toRadians(zRotation)); + } +} diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index 5e9c708c..d90db1cf 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -17,10 +17,12 @@ import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.paint.Material; import javafx.scene.paint.PhongMaterial; +import javafx.scene.shape.Cylinder; import javafx.scene.paint.Stop; import javafx.scene.shape.MeshView; import javafx.scene.shape.Shape3D; @@ -80,10 +82,12 @@ public class RaceViewController extends Controller { // note: it says it's not used but it is! do not remove :) private @FXML ArrowController arrowController; + private @FXML NextMarkController nextMarkController; private @FXML GridPane canvasBase; private @FXML GridPane canvasBase1; private @FXML SplitPane racePane; private @FXML StackPane arrowPane; + private @FXML Pane nextMarkPane; private @FXML Label timer; private @FXML Label FPS; private @FXML Label timeZone; @@ -285,19 +289,6 @@ public class RaceViewController extends Controller { * Initialises the various UI components to listen to the {@link #visualiserRace}. */ private void initialiseRaceVisuals() { - - // Import arrow mesh - URL asset = this.getClass().getClassLoader().getResource("assets/arrow V1.0.4.stl"); - StlMeshImporter importer = new StlMeshImporter(); - importer.read(asset); - - MeshView arrow = new MeshView(importer.getImport()); - PhongMaterial arrowMat = new PhongMaterial(Color.RED); - arrow.setMaterial(arrowMat); - - this.nextMarkArrow = new Annotation3D(arrow); - this.nextMarkArrow.setScale(0.1); - // initialise displays initialiseFps(); initialiseInfoTable(); @@ -306,6 +297,7 @@ public class RaceViewController extends Controller { initialiseSpeedometer(); initialiseRaceCanvas(); raceTimer(); // start the timer + nextMarkPane.toFront(); speedometerLoop(); new Sparkline(this.raceState, this.sparklineChart); timeZone.setText(this.raceState.getRaceClock().getTimeZone()); @@ -315,6 +307,12 @@ public class RaceViewController extends Controller { private void initialiseView3D(VisualiserRaceEvent race) { viewSubjects = FXCollections.observableArrayList(); + try { + nextMarkController.initialiseArrowView(race.getVisualiserRaceState().getBoat(race.getVisualiserRaceState().getPlayerBoatID())); + } catch (BoatNotFoundException e) { + e.printStackTrace(); + } + AmbientLight ambientLight = new AmbientLight(Color.web("#CCCCFF")); ambientLight.setTranslateX(250); ambientLight.setTranslateZ(210); @@ -385,11 +383,29 @@ public class RaceViewController extends Controller { viewSubjects.add(markModel); } - for (VisualiserBoat boat: race.getVisualiserRaceState().getBoats()) { + // Position and add each boat to view + for(VisualiserBoat boat: race.getVisualiserRaceState().getBoats()) { + Shape3D mesh = Assets3D.getBoat(); + + PhongMaterial boatColorMat = new PhongMaterial(boat.getColor()); + //mesh.setMaterial(boatColorMat); + Subject3D boatModel = new Subject3D(mesh, boat.getSourceID()); + + // Configure visualiser for client's boat if (boat.isClientBoat()) { + // Add player boat highlight Shockwave boatHighlight = new Shockwave(10); boatHighlight.getMesh().setMaterial(new PhongMaterial(new Color(1, 1, 0, 0.1))); viewSubjects.add(boatHighlight); + + // Track player boat with camera + viewSubjects.add(boatModel); + Platform.runLater(() -> { + view3D.trackSubject(boatModel); + view3D.setThirdPerson(); + }); + + // Track player boat with highlight AnimationTimer highlightTrack = new AnimationTimer() { @Override public void handle(long now) { @@ -398,28 +414,23 @@ public class RaceViewController extends Controller { } }; highlightTrack.start(); - } - } - // Position and add each boat to view - for(VisualiserBoat boat: race.getVisualiserRaceState().getBoats()) { -// MeshView mesh; -// if(boat.getSourceID() == race.getVisualiserRaceState().getPlayerBoatID()) { -// mesh = new MeshView(importer.getImport()); -// } else { -// mesh = new MeshView(importerBurgerBoat.getImport()); -// } - Shape3D mesh = Assets3D.getBoat(); - - PhongMaterial boatColorMat = new PhongMaterial(boat.getColor()); - //mesh.setMaterial(boatColorMat); - Subject3D boatModel = new Subject3D(mesh, boat.getSourceID()); - - viewSubjects.add(boatModel); + // Highlight next mark only for player boat + Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1)); + CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark(); + view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor); + if(nextMark.getMark2() != null) { + view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor); + } + boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr))); + } else { + viewSubjects.add(boatModel); + } //add sail Sails3D sails3D = new Sails3D(); Subject3D sailsSubject = new Subject3D(sails3D, 0); + sails3D.setMouseTransparent(true); sails3D.setMaterial(boatColorMat); sailsSubject.setXRot(0d); sailsSubject.setHeading(visualiserRace.getVisualiserRaceState().getWindDirection().degrees()); @@ -500,17 +511,9 @@ public class RaceViewController extends Controller { }; trackBoat.start(); - Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1)); - CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark(); - view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor); - if(nextMark.getMark2() != null) { - view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor); - } Subject3D shockwave = new Shockwave(10); - viewSubjects.add(shockwave); - boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr))); boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave))); } // Fix initial bird's-eye position @@ -595,37 +598,32 @@ public class RaceViewController extends Controller { } private void addThirdPersonAnnotations(Subject3D subject3D) { - viewSubjects.add(nextMarkArrow); - final VisualiserBoat boat; - try { - boat = visualiserRace.getVisualiserRaceState().getBoat(subject3D.getSourceID()); - } catch (BoatNotFoundException e) { - e.printStackTrace(); - return; - } - arrowToNextMark = new AnimationTimer() { - @Override - public void handle(long now) { - CompoundMark target = boat.getCurrentLeg().getEndCompoundMark(); - if (target != null) { - Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); - - nextMarkArrow.setX(view3D.getPivot().getX()); - nextMarkArrow.setY(view3D.getPivot().getY()); - nextMarkArrow.setZ(view3D.getPivot().getZ() + 15); - nextMarkArrow.setHeading(headingToMark.degrees()); - } - } - }; - arrowToNextMark.start(); + nextMarkController.show3d(); +// viewSubjects.add(nextMarkArrow); +// final VisualiserBoat boat; +// try { +// boat = visualiserRace.getVisualiserRaceState().getBoat(subject3D.getSourceID()); +// } catch (BoatNotFoundException e) { +// e.printStackTrace(); +// return; +// } +// arrowToNextMark = new AnimationTimer() { +// @Override +// public void handle(long now) { +// CompoundMark target = boat.getCurrentLeg().getEndCompoundMark(); +// Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); +// +// nextMarkArrow.setX(view3D.getPivot().getX()); +// nextMarkArrow.setY(view3D.getPivot().getY()); +// nextMarkArrow.setZ(view3D.getPivot().getZ() + 15); +// nextMarkArrow.setHeading(headingToMark.degrees()); +// } +// }; +// arrowToNextMark.start(); } private void removeThirdPersonAnnotations() { - viewSubjects.remove(nextMarkArrow); - if (arrowToNextMark != null) { - arrowToNextMark.stop(); - } - + nextMarkController.show2d(); } /** diff --git a/racevisionGame/src/main/java/visualiser/layout/Assets3D.java b/racevisionGame/src/main/java/visualiser/layout/Assets3D.java index 756d5a9e..28bb3497 100644 --- a/racevisionGame/src/main/java/visualiser/layout/Assets3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/Assets3D.java @@ -52,7 +52,7 @@ public class Assets3D { windArrow = new Annotation3D(loadX3d(arrowPath)); } - private static Shape3D loadX3d(String path){ + public static Shape3D loadX3d(String path){ X3dModelImporter x3dModelImporter = new X3dModelImporter(); URL asset = Assets3D.class.getClassLoader().getResource(path); x3dModelImporter.read(asset); diff --git a/racevisionGame/src/main/java/visualiser/layout/View3D.java b/racevisionGame/src/main/java/visualiser/layout/View3D.java index 7277ac5f..8501cdaa 100644 --- a/racevisionGame/src/main/java/visualiser/layout/View3D.java +++ b/racevisionGame/src/main/java/visualiser/layout/View3D.java @@ -81,7 +81,7 @@ public class View3D extends Pane { /** * Distance to stop zoom */ - private final double ZOOM_IN_LIMIT = 30; + private final double ZOOM_IN_LIMIT = 3; private final double ZOOM_OUT_LIMIT = 700; private final double MAX_ZOOM_LIMIT = 1500; private final double MAX_PITCH = 60; // birds eye view diff --git a/racevisionGame/src/main/resources/assets/mark_arrow.x3d b/racevisionGame/src/main/resources/assets/mark_arrow.x3d new file mode 100644 index 00000000..1b41caec --- /dev/null +++ b/racevisionGame/src/main/resources/assets/mark_arrow.x3d @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/racevisionGame/src/main/resources/assets/textures/Material Diffuse Color.002 b/racevisionGame/src/main/resources/assets/textures/Material Diffuse Color.002 new file mode 100644 index 00000000..0c5dbaeb Binary files /dev/null and b/racevisionGame/src/main/resources/assets/textures/Material Diffuse Color.002 differ diff --git a/racevisionGame/src/main/resources/css/slider.css b/racevisionGame/src/main/resources/css/slider.css new file mode 100644 index 00000000..2cb9832d --- /dev/null +++ b/racevisionGame/src/main/resources/css/slider.css @@ -0,0 +1,16 @@ +.slider .thumb { + -fx-background-image: url("/visualiser/images/sun.png"); + -fx-background-size: 25px; + -fx-pref-height: 25px; + -fx-pref-width: 25px; + -fx-background-position: top; + -fx-background-repeat: no-repeat; + -fx-focus-color: transparent; + -fx-background-color: transparent; +} + +.slider .track { + -fx-control-inner-background: dodgerblue; + -fx-border-color: rgba(30, 144, 255, 0.44); + -fx-border-radius: 0.25em, 0.25em, 0.166667em; +} \ No newline at end of file diff --git a/racevisionGame/src/main/resources/images/nextMarkArrow2d.png b/racevisionGame/src/main/resources/images/nextMarkArrow2d.png new file mode 100644 index 00000000..ed9506c4 Binary files /dev/null and b/racevisionGame/src/main/resources/images/nextMarkArrow2d.png differ diff --git a/racevisionGame/src/main/resources/visualiser/scenes/hostGame.fxml b/racevisionGame/src/main/resources/visualiser/scenes/hostGame.fxml index cf82c285..3218c802 100644 --- a/racevisionGame/src/main/resources/visualiser/scenes/hostGame.fxml +++ b/racevisionGame/src/main/resources/visualiser/scenes/hostGame.fxml @@ -3,6 +3,7 @@ + @@ -12,19 +13,20 @@ - + - - - + + + - - - + + + + -