mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Fix for some movement on racestart issues
#bug
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user