Implemented Animation Timer, FPS counter and modified display boat names and speed
-Race now uses Animation Timer to simulate the race in Race class -FPS counter displayed in bottom left corner. TODO: Toggle fps view -Boat names and speed will now reposition so it is not blocked by the border of the canvas #story [18, 20]
This commit is contained in:
@@ -25,12 +25,12 @@ public class Constants {
|
||||
public static final GPSCoordinate finishLineMarker2 = new GPSCoordinate(32.317257, -64.836260);
|
||||
|
||||
public static final BoatInRace[] OFFICIAL_AC35_COMPETITORS = new BoatInRace[]
|
||||
{new BoatInRace("Oracle Team USA", 200.0, Color.BLUEVIOLET, "USA"),
|
||||
new BoatInRace("Land Rover BAR", 180.0, Color.BLACK, "BAR"),
|
||||
new BoatInRace("SoftBank Team Japan", 190.0, Color.RED, "JAP"),
|
||||
new BoatInRace("Groupama Team France", 210.0, Color.ORANGE, "FRN"),
|
||||
new BoatInRace("Artemis Racing", 220.0, Color.DARKOLIVEGREEN, "ART"),
|
||||
new BoatInRace("Emirates Team New Zealand", 310, Color.LIMEGREEN, "ENZ")};
|
||||
{new BoatInRace("Oracle Team USA", 700.0, Color.BLUEVIOLET, "USA"),
|
||||
new BoatInRace("Land Rover BAR", 680.0, Color.BLACK, "BAR"),
|
||||
new BoatInRace("SoftBank Team Japan", 690.0, Color.RED, "JAP"),
|
||||
new BoatInRace("Groupama Team France", 710.0, Color.ORANGE, "FRN"),
|
||||
new BoatInRace("Artemis Racing", 720.0, Color.DARKOLIVEGREEN, "ART"),
|
||||
new BoatInRace("Emirates Team New Zealand", 810, Color.LIMEGREEN, "ENZ")};
|
||||
|
||||
//public static final Leg bermudaCourseStartToMark1 = new Leg(0, , new )
|
||||
}
|
||||
|
||||
@@ -5,13 +5,17 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.TitledPane;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Callback;
|
||||
import org.geotools.referencing.GeodeticCalculator;
|
||||
@@ -38,6 +42,10 @@ public class RaceController extends Controller{
|
||||
@FXML
|
||||
Label timer;
|
||||
|
||||
@FXML
|
||||
Label FPS;
|
||||
|
||||
|
||||
@FXML
|
||||
TableView<BoatInRace> boatInfoTable;
|
||||
@FXML
|
||||
@@ -54,7 +62,6 @@ public class RaceController extends Controller{
|
||||
* @param boats boats that are to be displayed in the race
|
||||
* @see ResizableRaceCanvas
|
||||
*/
|
||||
|
||||
public void updateMap(ObservableList<BoatInRace> boats) {
|
||||
BoatInRace[] boatInRaces = new BoatInRace[boats.size()];
|
||||
raceMap.setBoats(boats.toArray(boatInRaces));
|
||||
@@ -96,9 +103,10 @@ public class RaceController extends Controller{
|
||||
ArrayList<Leg> legs = generateBermudaCourseLegs();
|
||||
ConstantVelocityRace race = new ConstantVelocityRace(boats, legs, this);
|
||||
|
||||
(new Thread(race)).start();
|
||||
new Thread((race)).start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function for the Bermuda Race.
|
||||
* @return legs in the Bermuda Race.
|
||||
@@ -134,5 +142,7 @@ public class RaceController extends Controller{
|
||||
timer.setText(time);
|
||||
}
|
||||
|
||||
public void setFrames(String fps) { FPS.setText((fps)); }
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public class Boat {
|
||||
*/
|
||||
public Boat(String name, double velocity, String abbrev){
|
||||
this.velocity = velocity;
|
||||
this.velocityProp = new SimpleStringProperty(String.valueOf(velocity));
|
||||
this.velocityProp = new SimpleStringProperty(String.valueOf(velocity* 1.94384));
|
||||
this.abbrev = abbrev;
|
||||
this.name = new SimpleStringProperty(name);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package seng302.Model;
|
||||
|
||||
|
||||
import javafx.animation.AnimationTimer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
@@ -24,7 +25,7 @@ public abstract class Race implements Runnable {
|
||||
protected long totalTimeElapsed;
|
||||
|
||||
|
||||
private int SLEEP_TIME = 50; //time in milliseconds to pause in a paced loop
|
||||
private int SLEEP_TIME = 25; //time in milliseconds to pause in a paced loop
|
||||
private int PRERACE_TIME = 10000;//Integer.MAX_VALUE; //time in milliseconds to pause during pre-race
|
||||
private boolean timerEnabled = true;
|
||||
|
||||
@@ -59,6 +60,9 @@ public abstract class Race implements Runnable {
|
||||
simulateRace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the timer
|
||||
*/
|
||||
public void disableTimer() {
|
||||
timerEnabled = false;
|
||||
}
|
||||
@@ -72,14 +76,16 @@ public abstract class Race implements Runnable {
|
||||
System.out.println("====================");
|
||||
for (int i = 0; i < startingBoats.size(); i++) {
|
||||
if (startingBoats.get(i) != null) {
|
||||
System.out.println(i + 1 + ". " + startingBoats.get(i).getName() + ", Speed: "
|
||||
System.out.println(i + 1 + ". " + startingBoats.get(i).toString() + ", Speed: "
|
||||
+ Math.round(startingBoats.get(i).getVelocity() * 1.94384) + "kn");
|
||||
startingBoats.get(i).setCurrentLeg(legs.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Countdown timer until race starts. Use PRERACE_TIME to set countdown duration.
|
||||
*/
|
||||
private void countdownTimer() {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
long startTime = currentTime + PRERACE_TIME;
|
||||
@@ -108,6 +114,10 @@ public abstract class Race implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes total time elapsed and format to hour:minute:second
|
||||
* @return Formatted time as string
|
||||
*/
|
||||
private String calcTimer() {
|
||||
long minutes;
|
||||
long currentTimeInSeconds;
|
||||
@@ -122,28 +132,43 @@ public abstract class Race implements Runnable {
|
||||
return String.format("Race clock: %02d:%02d:%02d", hours, minutes, remainingSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the calculated time to the timer label
|
||||
* @param time The calculated time from calcTimer() method
|
||||
*/
|
||||
private void updateTime(String time){
|
||||
|
||||
Platform.runLater(() -> {controller.setTimer(time);});
|
||||
}
|
||||
|
||||
private void updateFPS(int fps) {
|
||||
Platform.runLater(() -> {controller.setFrames("FPS: " + fps);});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private void simulateRace() {
|
||||
|
||||
System.setProperty("javafx.animation.fullspeed", "true");
|
||||
|
||||
new AnimationTimer() {
|
||||
|
||||
long timeRaceStarted = System.currentTimeMillis();
|
||||
int fps = 0;
|
||||
long timeCurrent = System.currentTimeMillis();
|
||||
|
||||
long timeLoopStarted;
|
||||
@Override
|
||||
public void handle(long arg0) {
|
||||
|
||||
/*long timeLoopStarted;
|
||||
long timeLoopEnded;
|
||||
int fps = 0;*/
|
||||
|
||||
|
||||
while (boatsFinished < startingBoats.size()) {
|
||||
timeLoopStarted = System.currentTimeMillis();
|
||||
if (boatsFinished < startingBoats.size()) {
|
||||
//timeLoopStarted = System.currentTimeMillis();
|
||||
totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted;
|
||||
|
||||
|
||||
for (BoatInRace boat : startingBoats) {
|
||||
if (boat != null && !boat.isFinished()) {
|
||||
updatePosition(boat, SLEEP_TIME);
|
||||
@@ -151,15 +176,29 @@ public abstract class Race implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
if(controller != null) controller.updateMap(startingBoats);
|
||||
if(timerEnabled) updateTime(calcTimer());
|
||||
if (controller != null) controller.updateMap(startingBoats);
|
||||
if (timerEnabled)
|
||||
updateTime(calcTimer());
|
||||
}
|
||||
fps++;
|
||||
if ((System.currentTimeMillis()-timeCurrent) > 1000){
|
||||
updateFPS(fps);
|
||||
fps = 0;
|
||||
timeCurrent = System.currentTimeMillis();
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/*fps++;
|
||||
try {
|
||||
timeLoopEnded = System.currentTimeMillis();
|
||||
Thread.sleep(SLEEP_TIME - (timeLoopEnded - timeLoopStarted));
|
||||
} catch (InterruptedException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
};
|
||||
//System.out.println("Avg fps:" + fps/(totalTimeElapsed/1000));
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,8 @@ import seng302.GPSCoordinate;
|
||||
import seng302.GraphCoordinate;
|
||||
import seng302.RaceMap;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -23,6 +25,8 @@ public class ResizableRaceCanvas extends Canvas {
|
||||
private GraphicsContext gc;
|
||||
private RaceMap map;
|
||||
private BoatInRace[] boats;
|
||||
private Graphics graphics;
|
||||
private Font font;
|
||||
|
||||
/**
|
||||
* Sets the boats that are to be displayed in this race.
|
||||
@@ -107,6 +111,7 @@ public class ResizableRaceCanvas extends Canvas {
|
||||
public void displayArrow(GraphCoordinate coordinate, int angle){
|
||||
gc.save();
|
||||
rotate(angle, coordinate.getX(),coordinate.getY());
|
||||
gc.setFill(Color.BLACK);
|
||||
gc.fillPolygon(new double[]{coordinate.getX()-12, coordinate.getX()-6, coordinate.getX(), coordinate.getX()-4, coordinate.getX()-4, coordinate.getX()-8, coordinate.getX()-8},
|
||||
new double[]{coordinate.getY()-5, coordinate.getY()-20, coordinate.getY()-5, coordinate.getY()-5, coordinate.getY()+20, coordinate.getY()+20, coordinate.getY()-5},
|
||||
7);
|
||||
@@ -131,8 +136,17 @@ public class ResizableRaceCanvas extends Canvas {
|
||||
* @param coordinate coordinate the text appears
|
||||
*/
|
||||
public void displayText(String name, double speed, GraphCoordinate coordinate){
|
||||
String text = name + ", " + speed + " knots";
|
||||
gc.fillText(text, coordinate.getX()+20, coordinate.getY());
|
||||
String text = String.format("%s, %2$.2f knots", name, speed);
|
||||
//System.out.println(text.length()*7);
|
||||
long xCoord = coordinate.getX()+20;
|
||||
long yCoord = coordinate.getY();
|
||||
if (xCoord+(text.length()*7) >= getWidth()){
|
||||
xCoord -= text.length()*7;
|
||||
}
|
||||
if (yCoord-(text.length()*2) <= 0){
|
||||
yCoord += 30;
|
||||
}
|
||||
gc.fillText(text, xCoord, yCoord);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,6 +154,8 @@ public class ResizableRaceCanvas extends Canvas {
|
||||
*/
|
||||
public void drawRaceMap() {
|
||||
|
||||
|
||||
|
||||
double width = getWidth();
|
||||
double height = getHeight();
|
||||
|
||||
@@ -171,13 +187,12 @@ public class ResizableRaceCanvas extends Canvas {
|
||||
|
||||
displayLine(startline1, startline2, Color.GREEN);
|
||||
|
||||
|
||||
if (boats != null) {
|
||||
for (BoatInRace boat : boats) {
|
||||
if (boat != null) {
|
||||
// System.out.print("Drawing Boat At: " + boat.getCurrentPosition());
|
||||
// System.out.print("Drawing Boat At: " + boat.getCurrentPosition());
|
||||
displayMark(this.map.convertGPS(boat.getCurrentPosition()), boat.getColour());
|
||||
displayText(boat.getAbbrev(), boat.getVelocity(), this.map.convertGPS(boat.getCurrentPosition()));
|
||||
displayText(boat.getName().getValue(), boat.getVelocity()* 1.94384, this.map.convertGPS(boat.getCurrentPosition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
<AnchorPane fx:id="canvasBase">
|
||||
<children>
|
||||
<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" />
|
||||
</children></AnchorPane>
|
||||
<AnchorPane layoutX="450.0" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
|
||||
<TableView fx:id="boatInfoTable" prefHeight="400.0" prefWidth="146.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<columns>
|
||||
<TableColumn fx:id="boatPlacingColumn" prefWidth="50.0" text="Place" />
|
||||
|
||||
Reference in New Issue
Block a user