Merged annotation toggle and DNF features with heading visualisation.
This commit is contained in:
@@ -2,15 +2,12 @@ package seng302.Controllers;
|
|||||||
|
|
||||||
|
|
||||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.SplitPane;
|
|
||||||
import javafx.scene.control.TableColumn;
|
|
||||||
import javafx.scene.control.TableView;
|
|
||||||
import javafx.scene.control.TitledPane;
|
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
@@ -39,6 +36,11 @@ public class RaceController extends Controller {
|
|||||||
@FXML
|
@FXML
|
||||||
SplitPane ongoingRacePane;
|
SplitPane ongoingRacePane;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
CheckBox showFPS;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
CheckBox showAnno;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
Label timer;
|
Label timer;
|
||||||
@@ -67,8 +69,7 @@ public class RaceController extends Controller {
|
|||||||
public void updateMap(ObservableList<BoatInRace> boats) {
|
public void updateMap(ObservableList<BoatInRace> boats) {
|
||||||
BoatInRace[] boatInRaces = new BoatInRace[boats.size()];
|
BoatInRace[] boatInRaces = new BoatInRace[boats.size()];
|
||||||
raceMap.setBoats(boats.toArray(boatInRaces));
|
raceMap.setBoats(boats.toArray(boatInRaces));
|
||||||
raceMap.drawRaceMap();
|
raceMap.update();
|
||||||
raceMap.updateBoats();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,7 +115,17 @@ public class RaceController extends Controller {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
//listener for fps
|
||||||
|
showFPS.selectedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
|
public void changed(ObservableValue<? extends Boolean> ov,
|
||||||
|
Boolean old_val, Boolean new_val) {
|
||||||
|
if (showFPS.isSelected()){
|
||||||
|
FPS.setVisible(true);
|
||||||
|
} else {
|
||||||
|
FPS.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,6 +137,7 @@ public class RaceController extends Controller {
|
|||||||
private void startRace(int scaleFactor) {
|
private void startRace(int scaleFactor) {
|
||||||
BoatInRace[] boats = generateAC35Competitors();
|
BoatInRace[] boats = generateAC35Competitors();
|
||||||
raceMap = new ResizableRaceCanvas();
|
raceMap = new ResizableRaceCanvas();
|
||||||
|
raceMap.setMouseTransparent(true);
|
||||||
raceMap.widthProperty().bind(canvasBase.widthProperty());
|
raceMap.widthProperty().bind(canvasBase.widthProperty());
|
||||||
raceMap.heightProperty().bind(canvasBase.heightProperty());
|
raceMap.heightProperty().bind(canvasBase.heightProperty());
|
||||||
raceMap.setBoats(boats);
|
raceMap.setBoats(boats);
|
||||||
@@ -142,6 +154,15 @@ public class RaceController extends Controller {
|
|||||||
|
|
||||||
|
|
||||||
new Thread((race)).start();
|
new Thread((race)).start();
|
||||||
|
|
||||||
|
//listener for annotation
|
||||||
|
showAnno.selectedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
|
public void changed(ObservableValue<? extends Boolean> ov,
|
||||||
|
Boolean old_val, Boolean new_val) {
|
||||||
|
raceMap.toggleAnno();
|
||||||
|
raceMap.update();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class Boat {
|
|||||||
*/
|
*/
|
||||||
public Boat(String name, double velocity, String abbrev) {
|
public Boat(String name, double velocity, String abbrev) {
|
||||||
this.velocity = velocity;
|
this.velocity = velocity;
|
||||||
this.velocityProp = new SimpleStringProperty(String.valueOf(velocity* 1.94384));
|
this.velocityProp = new SimpleStringProperty(String.valueOf(Math.round(velocity)));
|
||||||
this.abbrev = abbrev;
|
this.abbrev = abbrev;
|
||||||
this.name = new SimpleStringProperty(name);
|
this.name = new SimpleStringProperty(name);
|
||||||
}
|
}
|
||||||
@@ -48,6 +48,10 @@ public class Boat {
|
|||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the speed of the boat in knots.
|
||||||
|
* @param velocity speed in knots
|
||||||
|
*/
|
||||||
public void setVelocity(double velocity) {
|
public void setVelocity(double velocity) {
|
||||||
this.velocity = velocity;
|
this.velocity = velocity;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,12 @@ public class BoatInRace extends Boat {
|
|||||||
return calculateHeading(azimuth);
|
return calculateHeading(azimuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the position of the end of the boat's wake, which is 180 degrees
|
||||||
|
* from the boat's heading, and whose length is proportional to the boat's
|
||||||
|
* speed.
|
||||||
|
* @return GPSCoordinate of wake endpoint.
|
||||||
|
*/
|
||||||
public GPSCoordinate getWake() {
|
public GPSCoordinate getWake() {
|
||||||
double reverseHeading = calculateHeading() - 180;
|
double reverseHeading = calculateHeading() - 180;
|
||||||
double distance = Constants.wakeScale * getVelocity();
|
double distance = Constants.wakeScale * getVelocity();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import javafx.collections.ObservableList;
|
|||||||
import seng302.Controllers.RaceController;
|
import seng302.Controllers.RaceController;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent class for races
|
* Parent class for races
|
||||||
@@ -164,10 +165,19 @@ public abstract class Race implements Runnable {
|
|||||||
Platform.runLater(() -> {controller.setTimer(time);});
|
Platform.runLater(() -> {controller.setTimer(time);});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the calculated fps to the fps label
|
||||||
|
* @param fps The new calculated fps value
|
||||||
|
*/
|
||||||
private void updateFPS(int fps) {
|
private void updateFPS(int fps) {
|
||||||
Platform.runLater(() -> {controller.setFrames("FPS: " + fps);});
|
Platform.runLater(() -> {controller.setFrames("FPS: " + fps);});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean doNotFinish() {
|
||||||
|
Random rand = new Random();
|
||||||
|
return rand.nextInt(100) < 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the Race Simulation, playing the race start to finish with the timescale.
|
* Starts the Race Simulation, playing the race start to finish with the timescale.
|
||||||
* This prints the boats participating, the order that the events occur in time order, and the respective information of the events.
|
* This prints the boats participating, the order that the events occur in time order, and the respective information of the events.
|
||||||
@@ -203,6 +213,11 @@ public abstract class Race implements Runnable {
|
|||||||
if (controller != null) controller.updateMap(startingBoats);
|
if (controller != null) controller.updateMap(startingBoats);
|
||||||
if (timerEnabled)
|
if (timerEnabled)
|
||||||
updateTime(calcTimer());
|
updateTime(calcTimer());
|
||||||
|
} else {
|
||||||
|
//Exit animation timer
|
||||||
|
updateTime(calcTimer());
|
||||||
|
updateFPS(0); //race ended so fps = 0
|
||||||
|
stop(); //exit animation timer
|
||||||
}
|
}
|
||||||
fps++;
|
fps++;
|
||||||
if ((System.currentTimeMillis()-timeCurrent) > 1000){
|
if ((System.currentTimeMillis()-timeCurrent) > 1000){
|
||||||
@@ -240,6 +255,10 @@ public abstract class Race implements Runnable {
|
|||||||
boatsFinished++;
|
boatsFinished++;
|
||||||
boat.setFinished(true);
|
boat.setFinished(true);
|
||||||
boat.setTimeFinished(timeElapsed);
|
boat.setTimeFinished(timeElapsed);
|
||||||
|
} else if(doNotFinish()) {
|
||||||
|
boatsFinished++;
|
||||||
|
boat.setFinished(true);
|
||||||
|
boat.setCurrentLeg(new Leg("DNF",-1));
|
||||||
} else {
|
} else {
|
||||||
//Calculate how much the boat overshot the marker by
|
//Calculate how much the boat overshot the marker by
|
||||||
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance());
|
boat.setDistanceTravelledInLeg(boat.getDistanceTravelledInLeg() - boat.getCurrentLeg().getDistance());
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class ResizableRaceCanvas extends Canvas {
|
|||||||
private GraphicsContext gc;
|
private GraphicsContext gc;
|
||||||
private RaceMap map;
|
private RaceMap map;
|
||||||
private BoatInRace[] boats;
|
private BoatInRace[] boats;
|
||||||
|
private boolean raceAnno = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the boats that are to be displayed in this race.
|
* Sets the boats that are to be displayed in this race.
|
||||||
@@ -141,6 +142,14 @@ public class ResizableRaceCanvas extends Canvas {
|
|||||||
gc.fillText(text, xCoord, yCoord);
|
gc.fillText(text, xCoord, yCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws race map with up to date data.
|
||||||
|
*/
|
||||||
|
public void update() {
|
||||||
|
this.drawRaceMap();
|
||||||
|
this.updateBoats();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the Race Map
|
* Draws the Race Map
|
||||||
*/
|
*/
|
||||||
@@ -177,18 +186,36 @@ public class ResizableRaceCanvas extends Canvas {
|
|||||||
displayArrow(new GraphCoordinate(500, 20), 100);
|
displayArrow(new GraphCoordinate(500, 20), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws boats while race in progress, when leg heading is set.
|
||||||
|
*/
|
||||||
public void updateBoats() {
|
public void updateBoats() {
|
||||||
if (boats != null) {
|
if (boats != null) {
|
||||||
for (BoatInRace boat : boats) {
|
for (BoatInRace boat : boats) {
|
||||||
if (boat != null && !boat.getCurrentLeg().getName().equals("Finish")) {
|
boolean finished = boat.getCurrentLeg().getName().equals("Finish") || boat.getCurrentLeg().getName().equals("DNF");
|
||||||
|
if (!finished) {
|
||||||
displayBoat(boat, boat.calculateHeading());
|
displayBoat(boat, boat.calculateHeading());
|
||||||
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition());
|
GraphCoordinate wakeFrom = this.map.convertGPS(boat.getCurrentPosition());
|
||||||
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
|
GraphCoordinate wakeTo = this.map.convertGPS(boat.getWake());
|
||||||
displayLine(wakeFrom, wakeTo, boat.getColour());
|
displayLine(wakeFrom, wakeTo, boat.getColour());
|
||||||
}
|
}
|
||||||
else displayBoat(boat, 0);
|
else {
|
||||||
displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
displayBoat(boat, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (raceAnno) displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the raceAnno value
|
||||||
|
*/
|
||||||
|
public void toggleAnno(){
|
||||||
|
if (raceAnno){
|
||||||
|
raceAnno = false;
|
||||||
|
} else {
|
||||||
|
raceAnno = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,12 +251,15 @@ public class ResizableRaceCanvas extends Canvas {
|
|||||||
return getHeight();
|
return getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws boats during race setup, when leg heading is not set.
|
||||||
|
*/
|
||||||
public void drawBoats() {
|
public void drawBoats() {
|
||||||
if (boats != null) {
|
if (boats != null) {
|
||||||
for (BoatInRace boat : boats) {
|
for (BoatInRace boat : boats) {
|
||||||
if (boat != null) {
|
if (boat != null) {
|
||||||
displayBoat(boat, 0);
|
displayBoat(boat, 0);
|
||||||
displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
if (raceAnno) displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,18 @@
|
|||||||
<items>
|
<items>
|
||||||
<AnchorPane fx:id="canvasBase" prefHeight="581.0" prefWidth="537.0">
|
<AnchorPane fx:id="canvasBase" prefHeight="581.0" prefWidth="537.0">
|
||||||
<children>
|
<children>
|
||||||
<Label fx:id="timer" layoutX="45.0" layoutY="146.0" text="0:0" AnchorPane.bottomAnchor="0.0"
|
<Label fx:id="FPS" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" />
|
||||||
AnchorPane.rightAnchor="0.0"/>
|
<Label fx:id="timer" layoutX="45.0" layoutY="146.0" text="0:0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0" />
|
||||||
<Label fx:id="FPS" layoutX="-20.0" layoutY="153.0" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="-0.0" />
|
<TitledPane fx:id="userControl" animated="false" text="User Control" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
|
<content>
|
||||||
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
|
<children>
|
||||||
|
<CheckBox fx:id="showFPS" mnemonicParsing="false" selected="true" text="Show FPS" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
|
||||||
|
<CheckBox fx:id="showAnno" mnemonicParsing="false" selected="true" text="Show Annotations" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="25.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
</TitledPane>
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0"
|
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user