Refactored Boat class to better fit the MVC model by moving all GUI parts to BoatPolygon. Changed the way animation works so that it will work with a constantly updated set of lats and lons.

TODO - Change Mark class to no longer store XY pixel data.
TODO - Add in a timer force updates boat position if a packet has not been recieved for a while.

#story30b #story30c #implement #refactor
This commit is contained in:
Calum
2017-04-24 23:06:30 +12:00
parent b5129c5c80
commit 46037b5aea
8 changed files with 392 additions and 234 deletions
+19 -115
View File
@@ -5,42 +5,26 @@ import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
import javafx.util.Pair;
/**
* Represents a boat in the race.
*/
public class Boat {
private static final double TEAMNAME_X_OFFSET = 15d;
private static final double TEAMNAME_Y_OFFSET = -20d;
private static final double VELOCITY_X_OFFSET = 15d;
private static final double VELOCITY_Y_OFFSET = -10d;
private static final double VELOCITY_WAKE_RATIO = 2d; //Ratio for deciding how long the wake will be wrt velocity
private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d;
private String teamName; // The name of the team, this is also the name of the boat
private double velocity; // In meters/second
private double lat; // Boats position
private double lon; // -
private double distanceToNextMark;
private Color color;
private int markLastPast;
private String teamName;
private double velocity;
private double lat;
private double lon;
private double heading;
private int markLastPast;
private String shortName;
//Graphical
private Polygon boatObject;
private Polygon wake;
private Text teamNameObject;
private Text velocityObject;
public Boat(String teamName) {
this.teamName = teamName;
this.velocity = 10; // Default velocity
this.lat = 0.0;
this.lon = 0.0;
this.distanceToNextMark = 0.0;
this.shortName = "";
}
@@ -54,16 +38,7 @@ public class Boat {
public Boat(String teamName, double boatVelocity, String shortName) {
this.teamName = teamName;
this.velocity = boatVelocity;
this.distanceToNextMark = 0.0;
this.color = Colors.getColor();
this.shortName = shortName;
this.boatObject = new Polygon();
this.boatObject.getPoints().addAll(BOAT_WIDTH /2,0.0,
BOAT_WIDTH, BOAT_HEIGHT,
0.0, BOAT_HEIGHT);
createWake();
this.teamNameObject = new Text(shortName);
this.velocityObject = new Text(Double.toString(boatVelocity) + "ms");
}
/**
@@ -113,8 +88,9 @@ public class Boat {
this.lon = lon;
}
public void setDistanceToNextMark(double distance){
this.distanceToNextMark = distance;
public Pair<Double, Double> getLocation ()
{
return new Pair<>(this.lat, this.lon);
}
public double getLatitude(){
@@ -125,8 +101,12 @@ public class Boat {
return this.lon;
}
public Color getColor() {
return color;
public void setLatitude (double latitude) {
this.lat = latitude;
}
public void setlongitude (double longitude) {
this.lon =longitude;
}
public double getSpeedInKnots(){
@@ -141,92 +121,16 @@ public class Boat {
return markLastPast;
}
public void setHeading(double heading){
boatObject.getTransforms().clear();
wake.getTransforms().clear();
wake.getTransforms().add(new Translate(0, BOAT_HEIGHT));
wake.getTransforms().add(new Rotate(heading, BOAT_WIDTH/2, -BOAT_HEIGHT));
boatObject.getTransforms().add(new Rotate(heading, BOAT_WIDTH/2, 0));
this.heading = heading;
}
public double getHeading(){
return this.heading;
}
public void setHeading(double heading) {
this.heading = heading;
}
public String getShortName(){
return this.shortName;
}
/**
* Moves the boat and its children annotations from its current coordinates by specified amounts.
* @param x The amount to move the X coordinate by
* @param y The amount to move the Y coordinate by
*/
void moveBoatBy(Double x, Double y) {
boatObject.setLayoutX(boatObject.getLayoutX() + x);
boatObject.setLayoutY(boatObject.getLayoutY() + y);
boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY());
teamNameObject.setX(teamNameObject.getX() + x);
teamNameObject.setY(teamNameObject.getY() + y);
teamNameObject.relocate(teamNameObject.getX(), teamNameObject.getY());
velocityObject.setX(velocityObject.getX() + x);
velocityObject.setY(velocityObject.getY() + y);
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
wake.setLayoutX(wake.getLayoutX() + x);
wake.setLayoutY(wake.getLayoutY() + y);
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
}
/**
* Moves the boat and its children annotations to coordinates specified
* @param x The X coordinate to move the boat to
* @param y The Y coordinate to move the boat to
*/
public void moveBoatTo(Double x, Double y) {
boatObject.setLayoutX(x);
boatObject.setLayoutY(y);
boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY());
teamNameObject.setX(x + TEAMNAME_X_OFFSET);
teamNameObject.setY(y + TEAMNAME_Y_OFFSET);
teamNameObject.relocate(teamNameObject.getX(), teamNameObject.getY());
velocityObject.setX(x + VELOCITY_X_OFFSET);
velocityObject.setY(y + VELOCITY_Y_OFFSET);
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
wake.setLayoutX(x);
wake.setLayoutY(y);
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
}
private void createWake(){
wake = new Polygon();
wake.setFill(Color.LIGHTSKYBLUE);
wake.getPoints().addAll(5.0,0.0,
10.0, velocity * VELOCITY_WAKE_RATIO,
0.0, velocity * VELOCITY_WAKE_RATIO);
}
public Polygon getWake() {
return wake;
}
public Polygon getBoatObject() {
return boatObject;
}
public Text getTeamNameObject() {
return teamNameObject;
}
public Text getVelocityObject() {
return velocityObject;
}
}
@@ -0,0 +1,171 @@
package seng302.models;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
/**
* Created by cir27 on 24/04/17.
*/
public class BoatPolygon extends Polygon {
private static final double TEAMNAME_X_OFFSET = 15d;
private static final double TEAMNAME_Y_OFFSET = -20d;
private static final double VELOCITY_X_OFFSET = 15d;
private static final double VELOCITY_Y_OFFSET = -10d;
private static final double VELOCITY_WAKE_RATIO = 2d;
private static final double BOAT_HEIGHT = 15d;
private static final double BOAT_WIDTH = 10d;
//Time between sections of race - Should be changed to 200 for actual program.
private static double expectedUpdateInterval = 5000;
private Boat boat;
private Polygon wake;
private Text teamNameObject;
private Text velocityObject;
private double rotation;
private double pixelVelocityX;
private double pixelVelocityY;
//private double destinationX;
//private double destinationY;
public BoatPolygon (Boat boat, Color color){
super();
super.setFill(color);
super.getPoints().addAll(
BOAT_WIDTH / 2, 0.0,
BOAT_WIDTH , BOAT_HEIGHT,
0.0 , BOAT_HEIGHT
);
this.boat = boat;
initAnnotations();
}
public BoatPolygon (Boat boat, Color color, double... points)
{
super(points);
super.setFill(color);
this.boat = boat;
initAnnotations();
}
private void initAnnotations ()
{
wake = new Polygon();
wake.setFill(Color.DARKBLUE);
wake.getPoints().addAll(
5.0,0.0,
10.0, boat.getVelocity() * VELOCITY_WAKE_RATIO,
0.0, boat.getVelocity() * VELOCITY_WAKE_RATIO
);
teamNameObject = new Text(boat.getShortName());
velocityObject = new Text(String.valueOf(boat.getVelocity()));
}
/**
* Moves the boat and its children annotations from its current coordinates by specified amounts.
* @param dx The amount to move the X coordinate by
* @param dy The amount to move the Y coordinate by
*/
void moveBy(Double dx, Double dy) {
super.setLayoutX(super.getLayoutX() + dx);
super.setLayoutY(super.getLayoutY() + dy);
super.relocate(super.getLayoutX(), super.getLayoutY());
teamNameObject.setX(teamNameObject.getX() + dx);
teamNameObject.setY(teamNameObject.getY() + dy);
teamNameObject.relocate(teamNameObject.getX(), teamNameObject.getY());
velocityObject.setX(velocityObject.getX() + dx);
velocityObject.setY(velocityObject.getY() + dy);
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
wake.setLayoutX(wake.getLayoutX() + dx);
wake.setLayoutY(wake.getLayoutY() + dy);
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
}
/**
* Moves the boat and its children annotations to coordinates specified
* @param x The X coordinate to move the boat to
* @param y The Y coordinate to move the boat to
*/
public void moveBoatTo(Double x, Double y) {
super.setLayoutX(x);
super.setLayoutY(y);
super.relocate(super.getLayoutX(), super.getLayoutY());
teamNameObject.setX(x + TEAMNAME_X_OFFSET);
teamNameObject.setY(y + TEAMNAME_Y_OFFSET);
teamNameObject.relocate(teamNameObject.getX(), teamNameObject.getY());
velocityObject.setX(x + VELOCITY_X_OFFSET);
velocityObject.setY(y + VELOCITY_Y_OFFSET);
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
wake.setLayoutX(x);
wake.setLayoutY(y);
wake.relocate(wake.getLayoutX(), wake.getLayoutY());
}
public void updatePosition (double timeInterval) {
double dx = pixelVelocityX * timeInterval;
double dy = pixelVelocityY * timeInterval;
moveBy(dx, dy);
}
public void setDestination (double newXValue, double newYValue) {
this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval;
this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval;
//this.destinationX = newXValue;
//this.destinationY = newYValue;
this.rotation = Math.abs(
Math.toDegrees(
Math.atan(
(newYValue - super.getLayoutY()) / (newXValue - super.getLayoutX())
)
)
);
if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue)
rotation = 90 - rotation;
else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue)
rotation = 90 + rotation;
else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue)
rotation = 270 + rotation;
else
rotation = 270 - rotation;
rotateBoat ();
}
private void rotateBoat () {
super.getTransforms().clear();
super.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, 0));
wake.getTransforms().clear();
wake.getTransforms().add(new Translate(0, BOAT_HEIGHT));
wake.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, -BOAT_HEIGHT));
}
public static double getExpectedUpdateInterval() {
return expectedUpdateInterval;
}
public static void setExpectedUpdateInterval(double expectedUpdateInterval) {
BoatPolygon.expectedUpdateInterval = expectedUpdateInterval;
}
public Polygon getWake() {
return wake;
}
public Text getTeamNameObject() {
return teamNameObject;
}
public Text getVelocityObject() {
return velocityObject;
}
}
+3 -4
View File
@@ -11,10 +11,9 @@ public enum Colors {
static Integer index = 0;
public static Color getColor() {
index++;
if (index > 6) {
index = 1;
if (index == 6) {
index = 0;
}
return Color.valueOf(values()[index-1].toString());
return Color.valueOf(values()[index++].toString());
}
}
+1
View File
@@ -9,6 +9,7 @@ import java.util.*;
* Created by mra106 on 8/3/2017.
*/
public class Race {
private ArrayList<Boat> boats; // The boats in the race
private ArrayList<Boat> finishingOrder; // The order in which the boats finish the race
private HashMap<Boat, List> events = new HashMap<>(); // The events that occur in the race
+4 -4
View File
@@ -42,7 +42,7 @@ public abstract class Mark {
Double longitude2 = pointTwo.getLongitude();
Double latitude1 = pointOne.getLatitude();
Double latitude2 = pointTwo.getLatitude();
return calculateHeadingRad(longitude1, longitude2, latitude1, latitude2);
return calculateHeadingRad(latitude1, longitude1, latitude2, longitude2);
}
/**
@@ -54,7 +54,7 @@ public abstract class Mark {
* @param latitude2 Latitude of first point in degrees
* @return Heading in radians
*/
public static double calculateHeadingRad (Double longitude1, Double longitude2, Double latitude1, Double latitude2) {
public static double calculateHeadingRad (Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
latitude1 = Math.toRadians(latitude1);
latitude2 = Math.toRadians(latitude2);
Double longDiff= Math.toRadians(longitude2-longitude1);
@@ -75,7 +75,7 @@ public abstract class Mark {
Double longitude2 = pointTwo.getLongitude();
Double latitude1 = pointOne.getLatitude();
Double latitude2 = pointTwo.getLatitude();
return calculateDistance(longitude1, longitude2, latitude1, latitude2);
return calculateDistance(latitude1, longitude1, latitude2, longitude2);
}
/**
@@ -88,7 +88,7 @@ public abstract class Mark {
* @param latitude2 Latitude of first point in degrees
* @return Distance in meters
*/
public static Double calculateDistance (Double longitude1, Double longitude2, Double latitude1, Double latitude2) {
public static Double calculateDistance (Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
Double theta = longitude1 - longitude2;
Double dist = Math.sin(Math.toRadians(latitude1)) * Math.sin(Math.toRadians(latitude2)) +
Math.cos(Math.toRadians(latitude1)) * Math.cos(Math.toRadians(latitude2)) *