Fix for some movement on racestart issues

#bug
This commit is contained in:
Calum
2017-05-04 10:38:04 +12:00
parent f0d6312fa5
commit a56e55ae70
6 changed files with 157 additions and 70 deletions
+7 -5
View File
@@ -5,6 +5,7 @@ import javafx.fxml.FXMLLoader;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import seng302.controllers.Controller;
import seng302.models.parsers.StreamParser; import seng302.models.parsers.StreamParser;
import seng302.models.parsers.StreamReceiver; import seng302.models.parsers.StreamReceiver;
import seng302.server.ServerThread; import seng302.server.ServerThread;
@@ -13,10 +14,11 @@ public class App extends Application
{ {
@Override @Override
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml")); // Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/MainView.fxml"));
primaryStage.setTitle("RaceVision"); primaryStage.setTitle("RaceVision");
primaryStage.setScene(new Scene(root)); primaryStage.setScene(new Scene(loader.load()));
((Controller) loader.getController()).setStage(primaryStage);
primaryStage.show(); primaryStage.show();
} }
@@ -34,8 +36,8 @@ public class App extends Application
sr = new StreamReceiver("localhost", 8085, "RaceStream"); sr = new StreamReceiver("localhost", 8085, "RaceStream");
} }
else{ else{
// sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"RaceStream"); sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"RaceStream");
sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream"); // sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
// sr = new StreamReceiver("localhost", 8085, "RaceStream"); // sr = new StreamReceiver("localhost", 8085, "RaceStream");
} }
@@ -5,11 +5,14 @@ import javafx.beans.property.SimpleDoubleProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.geometry.Point2D; import javafx.geometry.Point2D;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.canvas.Canvas; import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import javafx.stage.Stage;
import seng302.models.Boat; import seng302.models.Boat;
import seng302.models.BoatGroup; import seng302.models.BoatGroup;
import seng302.models.Colors; import seng302.models.Colors;
@@ -326,7 +329,7 @@ public class CanvasController {
for (Boat boat : boats) { for (Boat boat : boats) {
BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor()); BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor());
boatGroup.moveTo(startingX, startingY, 0d); boatGroup.moveTo(startingX, startingY, 0d);
boatGroup.forceRotation(); boatGroup.setStage(raceViewController.getStage());
raceObjects.add(boatGroup); raceObjects.add(boatGroup);
boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations()); boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations());
} }
@@ -7,6 +7,7 @@ import javafx.concurrent.Task;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn;
@@ -15,6 +16,7 @@ import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.stage.Stage;
import seng302.models.parsers.StreamParser; import seng302.models.parsers.StreamParser;
import seng302.models.parsers.XMLParser; import seng302.models.parsers.XMLParser;
@@ -48,12 +50,17 @@ public class Controller implements Initializable {
private TableColumn countryCol; private TableColumn countryCol;
@FXML @FXML
private Label realTime; private Label realTime;
private Stage stage;
private void setContentPane(String jfxUrl){ private void setContentPane(String jfxUrl){
try{ try{
contentPane.getChildren().removeAll(); contentPane.getChildren().removeAll();
contentPane.getChildren().clear(); contentPane.getChildren().clear();
contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl))); // contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl)));
FXMLLoader loader = new FXMLLoader(getClass().getResource(jfxUrl));
contentPane.getChildren().addAll((Node) loader.load());
RaceViewController r = (RaceViewController) loader.getController();
//((RaceViewController) loader.getController()).setStage(stage);
} }
catch(javafx.fxml.LoadException e){ catch(javafx.fxml.LoadException e){
System.err.println(e.getCause()); System.err.println(e.getCause());
@@ -145,4 +152,7 @@ public class Controller implements Initializable {
data.add(boat); data.add(boat);
} }
} }
public void setStage (Stage stage) {
this.stage = stage;
}
} }
@@ -15,6 +15,7 @@ import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration; import javafx.util.Duration;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import seng302.models.*; import seng302.models.*;
@@ -49,6 +50,7 @@ public class RaceViewController extends Thread{
private Map<Boat, TimelineInfo> timelineInfos = new HashMap<>(); private Map<Boat, TimelineInfo> timelineInfos = new HashMap<>();
private ArrayList<Boat> boatOrder = new ArrayList<>(); private ArrayList<Boat> boatOrder = new ArrayList<>();
private Race race; private Race race;
private Stage stage;
public void initialize() { public void initialize() {
@@ -397,4 +399,11 @@ public class RaceViewController extends Thread{
} }
} }
void setStage (Stage stage) {
this.stage = stage;
}
Stage getStage () {
return stage;
}
} }
+74 -11
View File
@@ -7,33 +7,46 @@ import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon; import javafx.scene.shape.Polygon;
import javafx.scene.text.Text; import javafx.scene.text.Text;
import javafx.scene.transform.Rotate; import javafx.scene.transform.Rotate;
import seng302.models.parsers.StreamParser; import javafx.stage.Stage;
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. * 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 * 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. * 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 BoatGroup extends RaceObject{ public class BoatGroup extends RaceObject{
//Constants for drawing
private static final double TEAMNAME_X_OFFSET = 10d; private static final double TEAMNAME_X_OFFSET = 10d;
private static final double TEAMNAME_Y_OFFSET = -15d; private static final double TEAMNAME_Y_OFFSET = -15d;
private static final double VELOCITY_X_OFFSET = 10d; private static final double VELOCITY_X_OFFSET = 10d;
private static final double VELOCITY_Y_OFFSET = -5d; private static final double VELOCITY_Y_OFFSET = -5d;
private static final double BOAT_HEIGHT = 15d; private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d; private static final double BOAT_WIDTH = 10d;
private static double expectedUpdateInterval = 200; //Variables for boat logic.
private boolean destinationSet;
private Point2D lastPoint; private Point2D lastPoint;
private int wakeGenerationDelay = 10; private int wakeGenerationDelay = 10;
private double distanceTravelled; private double distanceTravelled;
//Graphical objects
private Boat boat; private Boat boat;
private Group lineGroup = new Group(); private Group lineGroup = new Group();
private Polygon boatPoly; private Polygon boatPoly;
private Text teamNameObject; private Text teamNameObject;
private Text velocityObject; private Text velocityObject;
private Wake wake; private Wake wake;
//Handles boat moving when connecting to a stream
private boolean setToInitialLocation = false;
private boolean destinationSet;
//Variables for handling minimization
private Stage stage;
private boolean isMaximized= true;
private List<Line> lineStorage = new ArrayList<>();
private int setCallCount = 5;
/** /**
* Creates a BoatGroup with the default triangular boat polygon. * Creates a BoatGroup with the default triangular boat polygon.
@@ -146,6 +159,7 @@ public class BoatGroup extends RaceObject{
*/ */
public void updatePosition (long timeInterval) { public void updatePosition (long timeInterval) {
//Calculate the movement of the boat. //Calculate the movement of the boat.
if (isMaximized) {
double dx = pixelVelocityX * timeInterval; double dx = pixelVelocityX * timeInterval;
double dy = pixelVelocityY * timeInterval; double dy = pixelVelocityY * timeInterval;
double rotation = rotationalVelocity * timeInterval; double rotation = rotationalVelocity * timeInterval;
@@ -171,26 +185,28 @@ public class BoatGroup extends RaceObject{
} }
wake.updatePosition(timeInterval); wake.updatePosition(timeInterval);
} }
}
/** /**
* Sets the destination of the boat and the headng it should have once it reaches * Sets the destination of the boat and the headng it should have once it reaches
* @param newXValue * @param newXValue The X co-ordinate the boat needs to move to.
* @param newYValue * @param newYValue The Y co-ordinate the boat needs to move to.
* @param rotation Rotation to move graphics to. * @param rotation Rotation to move graphics to.
* @param raceIds RaceID of the object to move. * @param raceIds RaceID of the object to move.
*/ */
public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, int... raceIds) { public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, int... raceIds) {
if (hasRaceId(raceIds)) { if (hasRaceId(raceIds)) {
if (setToInitialLocation) {
destinationSet = true; destinationSet = true;
boat.setVelocity(groundSpeed); boat.setVelocity(groundSpeed);
if (currentRotation < 0) if (currentRotation < 0)
currentRotation = 360 - currentRotation; currentRotation = 360 - currentRotation;
double dx = newXValue - boatPoly.getLayoutX(); double dx = newXValue - boatPoly.getLayoutX();
if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) { // if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) {
pixelVelocityX = 0; // pixelVelocityX = 0;
} else { // } else {
pixelVelocityX = dx / expectedUpdateInterval; pixelVelocityX = dx / expectedUpdateInterval;
} // }
double dy = newYValue - boatPoly.getLayoutY(); double dy = newYValue - boatPoly.getLayoutY();
//Check movement is reasonable. Assumes a 1000 * 1000 canvas //Check movement is reasonable. Assumes a 1000 * 1000 canvas
if (Math.abs(dx) > 50 || Math.abs(dy) > 50) { if (Math.abs(dx) > 50 || Math.abs(dy) > 50) {
@@ -218,11 +234,40 @@ public class BoatGroup extends RaceObject{
calculateRotationalVelocity(); calculateRotationalVelocity();
if (wakeGenerationDelay > 0) { if (wakeGenerationDelay > 0) {
wake.rotate(rotationalGoal); wake.rotate(rotationalGoal);
rotateTo(rotationalGoal);
rotationalVelocity = 0;
wakeGenerationDelay--; wakeGenerationDelay--;
} else { } else {
wake.setRotationalVelocity(rotationalVelocity, currentRotation, boat.getVelocity()); wake.setRotationalVelocity(rotationalVelocity, currentRotation, boat.getVelocity());
} }
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity())); velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
} else {
setToInitialLocation = true;
rotationalGoal = rotation;
moveTo(newXValue, newYValue, rotation);
}
}
//If minimized generate lines every 5 calls to set destination.
if (!isMaximized) {
setToInitialLocation = false;
wakeGenerationDelay = 2;
if(setCallCount-- == 0) {
setCallCount = 5;
if (lastPoint != null) {
Line l = new Line(
lastPoint.getX(),
lastPoint.getY(),
newXValue,
newYValue
);
l.getStrokeDashArray().setAll(3d, 7d);
l.setStroke(boatPoly.getFill());
lineStorage.add(l);
}
if (destinationSet) { //Only begin drawing after the first destination is set
lastPoint = new Point2D(newXValue, newYValue);
}
}
} }
} }
@@ -307,4 +352,22 @@ public class BoatGroup extends RaceObject{
group.getChildren().addAll(wake, lineGroup); group.getChildren().addAll(wake, lineGroup);
return group; return group;
} }
/**
* Use this function to let the BoatGroup know about the stage it is in. If it knows about it's stage then it will
* listen to the iconified property of that stage and change it's behaviour upon minimization. Without setting the
* Stage there is guarantee that the BoatGroup will draw properly when the stage is minimized.
*
* @param stage The stage that the BoatGroup is added to.
*/
public void setStage (Stage stage) {
this.stage = stage;
this.stage.iconifiedProperty().addListener(e -> {
isMaximized = !stage.isIconified();
if (!lineStorage.isEmpty()) {
lineGroup.getChildren().addAll(lineStorage);
lineStorage.clear();
}
});
}
} }
+6 -6
View File
@@ -36,7 +36,7 @@ class Wake extends Group {
//Default triangle is -110 deg out of phase with a default wake and has angle of 40 deg. //Default triangle is -110 deg out of phase with a default wake and has angle of 40 deg.
arc = new Arc(0,0,0,0,-110,40); arc = new Arc(0,0,0,0,-110,40);
//Opacity increases from 0.5 -> 0 evenly over the 5 wake arcs. //Opacity increases from 0.5 -> 0 evenly over the 5 wake arcs.
arc.setFill(new Color(0.18, 0.7, 1.0, 0.50 + -0.1 * i)); arc.setFill(new Color(0.18, 0.7, 1.0, 1.0 + -0.175 * i));
arc.setType(ArcType.ROUND); arc.setType(ArcType.ROUND);
arcs[i] = arc; arcs[i] = arc;
} }
@@ -52,17 +52,17 @@ class Wake extends Group {
* @param velocity The real world velocity of the boat in m/s. * @param velocity The real world velocity of the boat in m/s.
*/ */
void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocity) { void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocity) {
// if (Math.abs(rotationalVelocity) > 0.5) {
// rotationalVelocity = 0;
// }
sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]); sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]);
sum += Math.abs(rotationalVelocity); sum += Math.abs(rotationalVelocity);
// System.out.println("sum = " + sum); // System.out.println("sum = " + sum);
max = Math.max(max, rotationalVelocity); max = Math.max(max, rotationalVelocity);
if (sum < max) // System.out.println("max = " + max);
if (sum < (max / 3))
rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position. rotate (rotationGoal); //In relatively straight segments the wake snaps to match the boats current position.
//This stops the wake from eventually becoming out of sync with the boat. //This stops the wake from eventually becoming out of sync with the boat.
// if (Math.abs(rotationalVelocity) > 0.5) {
// rotationalVelocity = 0;
// }
//Update the index of the array of recent velocities that each wake uses. Each wake is 3 velocities behind the //Update the index of the array of recent velocities that each wake uses. Each wake is 3 velocities behind the
//next smallest wake. //next smallest wake.
velocityIndices[0] = (13 + (velocityIndices[0] - 1) % 13) % 13; velocityIndices[0] = (13 + (velocityIndices[0] - 1) % 13) % 13;