diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index b5d76432..3891f3a1 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -6,6 +6,7 @@ import javafx.fxml.FXML; import javafx.geometry.Point2D; import javafx.geometry.Point3D; import javafx.scene.Group; +import javafx.scene.Node; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.AnchorPane; @@ -15,10 +16,8 @@ import javafx.util.Pair; import seng302.models.Boat; import seng302.models.BoatGroup; import seng302.models.Colors; -import seng302.models.mark.GateMark; -import seng302.models.mark.Mark; -import seng302.models.mark.MarkType; -import seng302.models.mark.SingleMark; +import seng302.models.RaceObject; +import seng302.models.mark.*; import seng302.models.parsers.StreamParser; import seng302.models.parsers.StreamReceiver; @@ -59,6 +58,7 @@ public class CanvasController { private double referencePointX; private double referencePointY; private double metersToPixels; + private List raceObjects = new ArrayList<>(); public AnimationTimer timer; @@ -154,39 +154,51 @@ public class CanvasController { Mark nextMark; //if (countdown == 0) { - for (BoatGroup boatGroup : boatGroups) { + for (RaceObject raceObject : raceObjects) { //if (currentRaceMarker[boatIndex] < marks.size()) { //if (currentRaceMarker[boatIndex] == 6) { // int debugLine = 4; //} - double xb4 = boatGroup.getLayoutX(); - double yb4 = boatGroup.getLayoutY(); - nextMark = marks.get(currentRaceMarker[boatIndex]); + //double xb4 = boatGroup.getLayoutX(); + //double yb4 = boatGroup.getLayoutY(); + //nextMark = marks.get(currentRaceMarker[boatIndex]); //descending = nextMark.getY() > boatGroup.getLayoutY(); //leftToRight = nextMark.getX() < boatGroup.getLayoutX(); - boatGroup.updatePosition(1000 / 60); - Point3D p = StreamParser.boatPositions.get((long)boatGroup.getBoat().getId()); + raceObject.updatePosition(1000 / 60); + for (int id : raceObject.getRaceIds()) { + if (StreamParser.boatPositions.containsKey(id)) { + Point3D p = StreamParser.boatPositions.get((long) id); + Point2D p2d = latLonToXY(p.getX(), p.getY()); + //System.out.println("p2d = " + p2d); + //System.out.println("p.toString() = " + p.toString()); + double heading = 360.0 / 0xffff * p.getZ(); + //System.out.println("heading = " + heading); + raceObject.setDestination(p2d.getX(), p2d.getY(), heading, id); + } + StreamParser.boatPositions.remove((long) id); + } + //Point3D p = StreamParser.boatPositions.get((long) raceObject.getRaceIds()[0]); //System.out.println("boatGroup = " + boatGroup.getBoat().getId()); //System.out.println("StreamParser.boatPositions.toString() = " + StreamParser.boatPositions.toString()); - if (p != null) { - Point2D p2d = latLonToXY(p.getX(), p.getY()); - //System.out.println("p2d = " + p2d); - if (!boatGroup.isSamePos(p2d)) { - //System.out.println("p.toString() = " + p.toString()); - double heading = 360.0 / 0xffff * p.getZ(); - //System.out.println("heading = " + heading); - - - - boatGroup.setDestination(p2d.getX(), p2d.getY(), heading); +// if (p != null) { +// Point2D p2d = latLonToXY(p.getX(), p.getY()); +// //System.out.println("p2d = " + p2d); +// if (!boatGroup.isSamePos(p2d)) { +// //System.out.println("p.toString() = " + p.toString()); +// double heading = 360.0 / 0xffff * p.getZ(); +// //System.out.println("heading = " + heading); +// +// +// +// boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, boatGroup.getRaceIds()[0]); //boatGroup.setDestination(p2d.getX(), p2d.getY()); - } - } + // } + //} // if (descending && nextMark.getY() < boatGroup.getLayoutY()) { // currentRaceMarker[boatIndex]++; @@ -208,14 +220,14 @@ public class CanvasController { // boatGroup.setDestination( // marks.get(currentRaceMarker[boatIndex]).getX(), marks.get(currentRaceMarker[boatIndex]).getY() // ); -// } - double xnew = boatGroup.getLayoutX(); - double ynew = boatGroup.getLayoutY(); - double dx = xnew - xb4; - double dy = ynew -yb4; - raceFinished = false; - boatIndex++; + +// double xnew = boatGroup.getLayoutX(); +// double ynew = boatGroup.getLayoutY(); +// double dx = xnew - xb4; +// double dy = ynew -yb4; +// raceFinished = false; +// boatIndex++; } //} //if (raceFinished) { @@ -280,11 +292,10 @@ public class CanvasController { private void drawBoats() { // Map timelineInfos = raceViewController.getTimelineInfos(); List boats = raceViewController.getStartingBoats(); - List marks = raceViewController.getRace().getCourse(); - Double startingX = (double) marks.get(0).getX(); - Double startingY = (double) marks.get(0).getY(); - Double firstMarkX = (double) marks.get(1).getX(); - Double firstMarkY = (double) marks.get(1).getY(); + Double startingX = group.getChildren().get(0).getLayoutX(); + Double startingY = group.getChildren().get(0).getLayoutY(); + Double firstMarkX = group.getChildren().get(1).getLayoutX(); + Double firstMarkY = group.getChildren().get(1).getLayoutY(); for (Boat boat : boats) { BoatGroup boatGroup = new BoatGroup(boat, Colors.getColor()); @@ -324,67 +335,67 @@ public class CanvasController { */ private void drawCourse() { fitToCanvas(); - for (Mark mark : raceViewController.getRace().getCourse()) { - if (mark.getMarkType() == MarkType.SINGLE_MARK) { - drawSingleMark((SingleMark) mark, Color.BLACK); - } else { - drawGateMark((GateMark) mark); - } - } - System.out.println("MIN/MAX POINTS"); - System.out.println(minLatPoint.getName() + " " + minLatPoint.getX() + " " + minLatPoint.getY()); - System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getX() + " " + maxLatPoint.getY()); - System.out.println(minLonPoint.getName() + " " + minLonPoint.getX() + " " + minLonPoint.getY()); - System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getX() + " " + maxLonPoint.getY()); - System.out.println(referencePointX); - System.out.println(referencePointY); +// for (Mark mark : raceViewController.getRace().getCourse()) { +// if (mark.getMarkType() == MarkType.SINGLE_MARK) { +// drawSingleMark((SingleMark) mark, Color.BLACK); +// } else { +// drawGateMark((GateMark) mark); +// } +// } +// System.out.println("MIN/MAX POINTS"); +// System.out.println(minLatPoint.getName() + " " + minLatPoint.getX() + " " + minLatPoint.getY()); +// System.out.println(maxLatPoint.getName() + " " + maxLatPoint.getX() + " " + maxLatPoint.getY()); +// System.out.println(minLonPoint.getName() + " " + minLonPoint.getX() + " " + minLonPoint.getY()); +// System.out.println(maxLonPoint.getName() + " " + maxLonPoint.getX() + " " + maxLonPoint.getY()); +// System.out.println(referencePointX); +// System.out.println(referencePointY); } - /** - * Draw a given mark on canvas - * - * @param singleMark - */ - private void drawSingleMark(SingleMark singleMark, Color color) { - gc.setFill(color); - System.out.println("DRAWING " + singleMark.getName() + " at " + singleMark.getX() + ", " + singleMark.getY()); - gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE); - } - - /** - * Draw a gate mark which contains two single marks - * - * @param gateMark - */ - private void drawGateMark(GateMark gateMark) { - Color color = Color.BLUE; - - if (gateMark.getName().equals("Start")){ - color = Color.GREEN; - } - - if (gateMark.getName().equals("Finish")){ - color = Color.RED; - } - - drawSingleMark(gateMark.getSingleMark1(), color); - drawSingleMark(gateMark.getSingleMark2(), color); - - GraphicsContext gc = canvas.getGraphicsContext2D(); - gc.save(); - gc.setStroke(color); - if (gateMark.getMarkType() == MarkType.OPEN_GATE) - gc.setLineDashes(3, 5); - - gc.setLineWidth(2); - gc.strokeLine( - gateMark.getSingleMark1().getX() + MARK_SIZE / 2, - gateMark.getSingleMark1().getY() + MARK_SIZE / 2, - gateMark.getSingleMark2().getX() + MARK_SIZE / 2, - gateMark.getSingleMark2().getY() + MARK_SIZE / 2 - ); - gc.restore(); - } +// /** +// * Draw a given mark on canvas +// * +// * @param singleMark +// */ +// private void drawSingleMark(SingleMark singleMark, Color color) { +// gc.setFill(color); +// System.out.println("DRAWING " + singleMark.getName() + " at " + singleMark.getX() + ", " + singleMark.getY()); +// gc.fillOval(singleMark.getX(), singleMark.getY(),MARK_SIZE,MARK_SIZE); +// } +// +// /** +// * Draw a gate mark which contains two single marks +// * +// * @param gateMark +// */ +// private void drawGateMark(GateMark gateMark) { +// Color color = Color.BLUE; +// +// if (gateMark.getName().equals("Start")){ +// color = Color.GREEN; +// } +// +// if (gateMark.getName().equals("Finish")){ +// color = Color.RED; +// } +// +// drawSingleMark(gateMark.getSingleMark1(), color); +// drawSingleMark(gateMark.getSingleMark2(), color); +// +// GraphicsContext gc = canvas.getGraphicsContext2D(); +// gc.save(); +// gc.setStroke(color); +// if (gateMark.getMarkType() == MarkType.OPEN_GATE) +// gc.setLineDashes(3, 5); +// +// gc.setLineWidth(2); +// gc.strokeLine( +// gateMark.getSingleMark1().getX() + MARK_SIZE / 2, +// gateMark.getSingleMark1().getY() + MARK_SIZE / 2, +// gateMark.getSingleMark2().getX() + MARK_SIZE / 2, +// gateMark.getSingleMark2().getY() + MARK_SIZE / 2 +// ); +// gc.restore(); +// } /** * Calculates x and y location for every marker that fits it to the canvas the race will be drawn on. @@ -478,8 +489,8 @@ public class CanvasController { } referencePointX = Math.round(referencePointX); referencePointY = Math.round(referencePointY); - referencePoint.setX((int) referencePointX); - referencePoint.setY((int) referencePointY); +// referencePoint.setX((int) referencePointX); +// referencePoint.setY((int) referencePointY); } /** @@ -517,27 +528,31 @@ public class CanvasController { * are scaled according to the distanceScaleFactor variable. */ private void givePointsXY() { - Point2D canvasLocation; - List allPoints = new ArrayList<>(raceViewController.getRace().getCourse()); + //Point2D canvasLocation; +// List allPoints = new ArrayList<>(raceViewController.getRace().getCourse()); + Set unqiuePoints = new HashSet<>(raceViewController.getRace().getCourse()); + System.out.println("unqiuePoints = " + unqiuePoints); + RaceObject markGroup; - for (Mark mark : allPoints) { + for (Mark mark : unqiuePoints) { if (mark.getMarkType() != MarkType.SINGLE_MARK) { GateMark gateMark = (GateMark) mark; +// canvasLocation = findScaledXY(gateMark.getSingleMark1()); +// gateMark.getSingleMark1().setX((int) canvasLocation.getX()); +// gateMark.getSingleMark1().setY((int) canvasLocation.getY()); +// +// canvasLocation = findScaledXY(gateMark.getSingleMark2()); +// gateMark.getSingleMark2().setX((int) canvasLocation.getX()); +// gateMark.getSingleMark2().setY((int) canvasLocation.getY()); - canvasLocation = findScaledXY(gateMark.getSingleMark1()); - gateMark.getSingleMark1().setX((int) canvasLocation.getX()); - gateMark.getSingleMark1().setY((int) canvasLocation.getY()); - - canvasLocation = findScaledXY(gateMark.getSingleMark2()); - gateMark.getSingleMark2().setX((int) canvasLocation.getX()); - gateMark.getSingleMark2().setY((int) canvasLocation.getY()); + markGroup = new MarkGroup(mark, findScaledXY(gateMark.getSingleMark1()), findScaledXY(gateMark.getSingleMark2())); + group.getChildren().add(markGroup); } - if (mark.getMarkType() == MarkType.CLOSED_GATE) - ((GateMark) mark).assignXYCentered(); else { - canvasLocation = findScaledXY(mark); - mark.setX((int) canvasLocation.getX()); - mark.setY((int) canvasLocation.getY()); +// canvasLocation = findScaledXY(mark); +// mark.setX((int) canvasLocation.getX()); +// mark.setY((int) canvasLocation.getY()); + markGroup = new MarkGroup(mark, findScaledXY(mark)); } } } diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index b46f4783..a37f1852 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -20,9 +20,11 @@ public class BoatGroup extends RaceObject{ 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 = 2000; + private static double expectedUpdateInterval = 200; + private static int WAKE_FRAME_INTERVAL = 40; private Boat boat; + private int wakeCounter = WAKE_FRAME_INTERVAL; public BoatGroup (Boat boat, Color color){ this.boat = boat; @@ -60,11 +62,7 @@ public class BoatGroup extends RaceObject{ velocityObject.setY(VELOCITY_Y_OFFSET); velocityObject.relocate(velocityObject.getX(), velocityObject.getY()); - wake.setLayoutX(0); - wake.setLayoutY(0); - wake.relocate(wake.getLayoutX(), wake.getLayoutY()); - - super.getChildren().addAll(boatPoly, wake, teamNameObject, velocityObject); + super.getChildren().addAll(boatPoly, teamNameObject, velocityObject); } private void initChildren (Color color) { @@ -78,10 +76,10 @@ public class BoatGroup extends RaceObject{ * @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, double rotation) { + public void moveGroupBy(double dx, double dy, double rotation) { super.setLayoutX(super.getLayoutX() + dx); super.setLayoutY(super.getLayoutY() + dy); - rotateBoat(rotation); + rotateTo(currentRotation + rotation); } /** @@ -90,8 +88,7 @@ public class BoatGroup extends RaceObject{ * @param y The Y coordinate to move the boat to */ public void moveTo (double x, double y, double rotation) { - super.currentRotation = 0; - rotateBoat(rotation); + rotateTo(rotation); moveTo(x, y); } @@ -109,98 +106,77 @@ public class BoatGroup extends RaceObject{ } else if (rotationalGoal < currentRotation && rotationalVelocity < 0) { rotation = rotationalVelocity * timeInterval; } - moveBy(dx, dy, rotation); - } - - public void setDestination (double newXValue, double newYValue, double rotation) { - this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval; - this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval; - //this.destinationX = newXValue; - //this.destinationY = newYValue; - this.rotationalGoal = rotation; -// if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue) -// rotationalGoal = 90 - rotationalGoal; -// else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue) -// rotationalGoal = 90 + rotationalGoal; -// else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue) -// rotationalGoal = 270 + rotationalGoal; -// else -// rotationalGoal = 270 - rotationalGoal; -// if (Math.abs(360 - rotationalGoal + currentRotation) < Math.abs(rotationalGoal - currentRotation)) { -// System.out.println("ROTATE"); -// this.rotationalVelocity = (360 - rotationalGoal + currentRotation) / expectedUpdateInterval; -// } else { -// this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; -// } - if (Math.abs(rotationalGoal - currentRotation) > 180) { - if (rotationalGoal - currentRotation >= 0) { - this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval; - } else { - this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval; - } - } else { - this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; + moveGroupBy(dx, dy, rotation); + for (Node wake : super.getChildren().subList(4, super.getChildren().size())) { + if (!((Wake) wake).updatePosition(timeInterval)) + super.getChildren().remove(wake); + } + if (wakeCounter-- == 0) { + wakeCounter = WAKE_FRAME_INTERVAL; + super.getChildren().add( + new Wake( + super.getLayoutX(), super.getLayoutY(), pixelVelocityX, pixelVelocityY + ) + ); } } - 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.rotationalGoal = Math.abs( - Math.toDegrees( - Math.atan( - (newYValue - super.getLayoutY()) / (newXValue - super.getLayoutX()) - ) - ) - ); - if (super.getLayoutY() >= newYValue && super.getLayoutX() <= newXValue) - rotationalGoal = 90 - rotationalGoal; - else if (super.getLayoutY() < newYValue && super.getLayoutX() <= newXValue) - rotationalGoal = 90 + rotationalGoal; - else if (super.getLayoutY() >= newYValue && super.getLayoutX() > newXValue) - rotationalGoal = 270 + rotationalGoal; - else - rotationalGoal = 270 - rotationalGoal; - if (Math.abs(rotationalGoal - currentRotation) > 180) { - if (rotationalGoal - currentRotation >= 0) { - this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval; + public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) { + if (hasRaceId(raceIds)) { + this.pixelVelocityX = (newXValue - super.getLayoutX()) / expectedUpdateInterval; + this.pixelVelocityY = (newYValue - super.getLayoutY()) / expectedUpdateInterval; + this.rotationalGoal = rotation; + if (Math.abs(rotationalGoal - currentRotation) > 180) { + if (rotationalGoal - currentRotation >= 0) { + this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval; + } else { + this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval; + } } else { - this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval; + this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; } - } else { - this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; } } - public void rotateBoat (double rotationDeg) { - currentRotation += rotationDeg; + public void setDestination (double newXValue, double newYValue, int... raceIDs) { + if (hasRaceId(raceIDs)) { + double 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; + setDestination(newXValue, newYValue, rotation, raceIDs); + } + } + + public void rotateTo (double rotation) { Node boatPoly = super.getChildren().get(0); boatPoly.getTransforms().clear(); - boatPoly.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, 0)); + boatPoly.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, 0)); Node wake = super.getChildren().get(1); wake.getTransforms().clear(); wake.getTransforms().add(new Translate(0, BOAT_HEIGHT)); - wake.getTransforms().add(new Rotate(currentRotation, BOAT_WIDTH/2, -BOAT_HEIGHT)); - } - - public static double getExpectedUpdateInterval() { - return expectedUpdateInterval; - } - - public static void setExpectedUpdateInterval(double expectedUpdateInterval) { - BoatGroup.expectedUpdateInterval = expectedUpdateInterval; + wake.getTransforms().add(new Rotate(rotation, BOAT_WIDTH/2, -BOAT_HEIGHT)); } public void forceRotation () { - rotateBoat (rotationalGoal - currentRotation); + rotateTo (rotationalGoal); } public void toggleAnnotations () { - super.getChildren().get(1).setVisible(false); - super.getChildren().get(2).setVisible(false); - super.getChildren().get(3).setVisible(false); + for (Node node : super.getChildren().subList(1, super.getChildren().size())) { + node.setVisible(false); + } } public Boat getBoat() { @@ -214,4 +190,8 @@ public class BoatGroup extends RaceObject{ } return false; } + + public int[] getRaceIds () { + return new int[] {boat.getId()}; + } } diff --git a/src/main/java/seng302/models/RaceObject.java b/src/main/java/seng302/models/RaceObject.java index ab831025..70a015ac 100644 --- a/src/main/java/seng302/models/RaceObject.java +++ b/src/main/java/seng302/models/RaceObject.java @@ -8,11 +8,14 @@ import javafx.scene.Group; */ public abstract class RaceObject extends Group { - double rotationalGoal; - double currentRotation; - double rotationalVelocity; - double pixelVelocityX; - double pixelVelocityY; + //Time between sections of race - Should be changed to 200 for actual program. + protected static double expectedUpdateInterval = 2000; + + protected double rotationalGoal; + protected double currentRotation; + protected double rotationalVelocity; + protected double pixelVelocityX; + protected double pixelVelocityY; public boolean isSamePos (Point2D point) { return point.getX() == super.getLayoutX() && point.getY() == super.getLayoutY(); @@ -21,12 +24,33 @@ public abstract class RaceObject extends Group { public Point2D getPosition () { return new Point2D(super.getLayoutX(), getLayoutY()); } - public abstract void setDestination (double x, double y, double rotation); - public abstract void setDestination (double x, double y); + + public static double getExpectedUpdateInterval() { + return expectedUpdateInterval; + } + + public static void setExpectedUpdateInterval(double expectedUpdateInterval) { + RaceObject.expectedUpdateInterval = expectedUpdateInterval; + } + + public abstract void setDestination (double x, double y, double rotation, int... raceIds); + + public abstract void setDestination (double x, double y, int... raceIds); + public abstract void updatePosition (double timeInterval); + public abstract void moveTo (double x, double y, double rotation); + public abstract void moveTo (double x, double y); + + public abstract void moveGroupBy(double x, double y, double rotation); + + public abstract void rotateTo (double rotation); + public abstract boolean hasRaceId (int... raceIds); + + public abstract int[] getRaceIds (); + public abstract void toggleAnnotations (); } diff --git a/src/main/java/seng302/models/Wake.java b/src/main/java/seng302/models/Wake.java new file mode 100644 index 00000000..25e5ea59 --- /dev/null +++ b/src/main/java/seng302/models/Wake.java @@ -0,0 +1,37 @@ +package seng302.models; + +import javafx.scene.paint.Color; +import javafx.scene.shape.Arc; +import javafx.scene.shape.ArcType; + +/** + * Created by CJIRWIN on 27/04/2017. + */ +class Wake extends Arc { + + private static int VELOCITY_SCALE_FACTOR = 3; + private static int MAX_LIFESPAN = 180; + private static double LIFESPAN_PER_FRAME = 1.0 / MAX_LIFESPAN; + + private double velocityX; + private double velocityY; + private int lifespan = MAX_LIFESPAN; + + Wake (double startingX, double startingY, double velocityX, double velocityY) { + super(startingX, startingY, 25, 15, 160, 40); + super.setFill(Color.BLUE); + super.setType(ArcType.OPEN); + super.setStrokeWidth(2.0); + this.velocityX = -velocityX; + this.velocityY = -velocityY; + } + + boolean updatePosition (double timeInterval) { + lifespan--; + super.setLayoutX(super.getLayoutX() + velocityX * timeInterval); + super.setLayoutX(super.getLayoutX() + velocityX * timeInterval); + super.setOpacity(LIFESPAN_PER_FRAME * lifespan * super.getOpacity()); + return lifespan == 0; + } + +} diff --git a/src/main/java/seng302/models/mark/GateMark.java b/src/main/java/seng302/models/mark/GateMark.java index 2dfb9fdd..ffcf2b51 100644 --- a/src/main/java/seng302/models/mark/GateMark.java +++ b/src/main/java/seng302/models/mark/GateMark.java @@ -48,15 +48,4 @@ public class GateMark extends Mark { return (this.getSingleMark1().getLongitude()); } - public void assignXYCentered () { - System.out.println("POSSIBLE GOOF " + xValue + " " + yValue); - System.out.println(singleMark1.getX() + " " + singleMark1.getY()); - System.out.println(singleMark2.getX() + " " + singleMark2.getY()); - double dx = singleMark2.getX() - singleMark1.getX(); - System.out.println("dx + " + dx); - double dy = singleMark2.getY() - singleMark1.getY(); - xValue = (int) Math.round(singleMark1.getX() + dx / 2); - yValue = (int) Math.round(singleMark1.getY() + dy / 2); - System.out.println("PROBABLE GAAF " + xValue + " " + yValue); - } } diff --git a/src/main/java/seng302/models/mark/Mark.java b/src/main/java/seng302/models/mark/Mark.java index 57de9ac4..2c086b80 100644 --- a/src/main/java/seng302/models/mark/Mark.java +++ b/src/main/java/seng302/models/mark/Mark.java @@ -11,8 +11,6 @@ public abstract class Mark { private double latitude; private double longitude; private int id; - Integer xValue; - Integer yValue; /** * Create a mark instance by passing its name and type @@ -127,22 +125,6 @@ public abstract class Mark { return longitude; } - public int getX () { - return xValue; - } - - public int getY () { - return yValue; - } - - public void setX (int x) { - this.xValue = x; - } - - public void setY (int y) { - this.yValue = y; - } - public int getId() { return id; } diff --git a/src/main/java/seng302/models/mark/MarkGroup.java b/src/main/java/seng302/models/mark/MarkGroup.java index 1a56b336..c15d8f8c 100644 --- a/src/main/java/seng302/models/mark/MarkGroup.java +++ b/src/main/java/seng302/models/mark/MarkGroup.java @@ -1,27 +1,35 @@ package seng302.models.mark; import javafx.geometry.Point2D; +import javafx.scene.Node; import javafx.scene.paint.Color; import javafx.scene.shape.Circle; import javafx.scene.shape.Line; import javafx.scene.transform.Rotate; import seng302.models.RaceObject; +import java.util.ArrayList; +import java.util.List; + /** * Created by CJIRWIN on 26/04/2017. */ public class MarkGroup extends RaceObject { - private static int MARK_RADIUS = 5; - - private Mark mark; - private double pixelVelocityXM1; - private double pixelVelocityYM1; - private double pixelVelocityXM2; - private double pixelVelocityYM3; + private static int MARK_RADIUS = 5; + private static int LINE_THICKNESS = 2; + private static double DASHED_GAP_LEN = 2d; + private static double DASHED_LINE_LEN = 5d; + private List marks = new ArrayList<>(); + private Mark mainMark; + private double[] nodePixelVelocitiesX; + private double[] nodePixelVelocitiesY; + private Point2D[] nodeDestinations; public MarkGroup (Mark mark, Point2D... points) { + marks.add(mark); + mainMark = mark; Color color = Color.BLACK; if (mark.getName().equals("Start")){ color = Color.GREEN; @@ -31,11 +39,20 @@ public class MarkGroup extends RaceObject { if (mark.getMarkType() == MarkType.SINGLE_MARK) { super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); } else { - super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); + marks.add(((GateMark) mark).getSingleMark1()); + marks.add(((GateMark) mark).getSingleMark2()); super.getChildren().add( new Circle( - points[1].getX() - points[0].getX(), - points[1].getY() - points[0].getY(), + (points[1].getX() - points[0].getX() / 2), + (points[1].getY() - points[0].getY() / 2), + MARK_RADIUS, + color + ) + ); + super.getChildren().add( + new Circle( + -(points[1].getX() - points[0].getX() / 2), + -(points[1].getY() - points[0].getY() / 2), MARK_RADIUS, color ) @@ -46,33 +63,60 @@ public class MarkGroup extends RaceObject { points[1].getX() - points[0].getX(), points[1].getY() - points[0].getY() ); - line.setStrokeWidth(2); + line.setStrokeWidth(LINE_THICKNESS); if (mark.getMarkType() == MarkType.OPEN_GATE) { - line.getStrokeDashArray().addAll(3d, 5d); + line.getStrokeDashArray().addAll(DASHED_GAP_LEN, DASHED_LINE_LEN); } super.getChildren().add(line); + nodePixelVelocitiesX = new double[2]; + nodePixelVelocitiesY = new double[2]; + nodeDestinations = new Point2D[2]; } - this.mark = mark; moveTo(points[0].getX(), points[0].getY()); } - public void setDestination (double x, double y, double rotation) { - + public void setDestination (double x, double y, double rotation, int... raceIds) { + setDestination(x, y, raceIds); + this.rotationalGoal = rotation; + if (Math.abs(rotationalGoal - currentRotation) > 180) { + if (rotationalGoal - currentRotation >= 0) { + this.rotationalVelocity = ((rotationalGoal - currentRotation) - 360) / expectedUpdateInterval; + } else { + this.rotationalVelocity = (360 + (rotationalGoal - currentRotation)) / expectedUpdateInterval; + } + } else { + this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; + } } - public void setDestination (double x, double y) { - + public void setDestination (double x, double y, int... raceIds) { + int childrenIndex = -1; + for (Mark mark : marks) { + for (int id : raceIds) + if (id == mark.getId() && childrenIndex != -1) + setDestinationChild(x, y, childrenIndex); + else if (id == mark.getId()) + setDestinationGroup(x, y); + childrenIndex++; + } } - public void setMarkDestination (int markId, double x, double y) { - - } - public void updatePosition (double timeInterval) { + private void setDestinationChild (double x, double y, int childIndex) { + double relativeX = x - super.getLayoutX(); + double relativeY = y - super.getLayoutY(); + this.nodeDestinations[childIndex] = new Point2D(relativeX, relativeY); + this.nodePixelVelocitiesX[childIndex] = (relativeX - super.getChildren().get(childIndex).getLayoutX()) / expectedUpdateInterval; + this.nodePixelVelocitiesY[childIndex] = (relativeY - super.getChildren().get(childIndex).getLayoutY()) / expectedUpdateInterval; } - public void moveTo (double x, double y, double rotation) { - moveTo(x, y); + private void setDestinationGroup (double x, double y) { + pixelVelocityX = (x - super.getLayoutX()) / expectedUpdateInterval; + pixelVelocityY = (y - super.getLayoutY()) / expectedUpdateInterval; + } + + + public void rotateTo (double rotation) { super.getTransforms().clear(); super.getTransforms().add( new Rotate( @@ -83,20 +127,74 @@ public class MarkGroup extends RaceObject { ); } + public void updatePosition (double timeInterval) { + double x = pixelVelocityX * timeInterval; + double y = pixelVelocityY * timeInterval; + double rotation = rotationalVelocity * timeInterval; + moveGroupBy(x, y, rotation); + updateChildren(timeInterval); + } + + public void moveGroupBy (double x, double y, double rotation) { + super.setLayoutX(super.getLayoutX() + x); + super.setLayoutY(super.getOpacity() + y); + rotateTo(rotation + currentRotation); + } + + private void updateChildren (double timeInterval) { + if (mainMark.getMarkType() != MarkType.SINGLE_MARK) { + Circle mark = (Circle) super.getChildren().get(0); + if (nodePixelVelocitiesX[0] > 0 && mark.getLayoutX() >= nodeDestinations[0].getX()) { + nodePixelVelocitiesX[0] = 0; + } else if (nodePixelVelocitiesX[0] < 0 && mark.getLayoutX() <= nodeDestinations[0].getX()) { + nodePixelVelocitiesX[0] = 0; + } else { + mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[0] * timeInterval); + mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[0] * timeInterval); + } + if (nodePixelVelocitiesY[0] >= 0 && mark.getLayoutY() > nodeDestinations[0].getY()) { + nodePixelVelocitiesY[0] = 0; + } else if (nodePixelVelocitiesY[0] < 0 && mark.getLayoutY() <= nodeDestinations[0].getY()) { + nodePixelVelocitiesY[0] = 0; + } else { + mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[0] * timeInterval); + mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[0] * timeInterval); + } + mark = (Circle) super.getChildren().get(1); + if (nodePixelVelocitiesX[1] > 0 && mark.getLayoutX() >= nodeDestinations[1].getX()) { + nodePixelVelocitiesX[1] = 0; + } else if (nodePixelVelocitiesX[1] < 0 && mark.getLayoutX() <= nodeDestinations[1].getX()) { + nodePixelVelocitiesX[1] = 0; + } else { + mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[1] * timeInterval); + mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[1] * timeInterval); + } + if (nodePixelVelocitiesY[1] >= 0 && mark.getLayoutY() > nodeDestinations[1].getY()) { + nodePixelVelocitiesY[1] = 0; + } else if (nodePixelVelocitiesY[1] < 0 && mark.getLayoutY() <= nodeDestinations[1].getY()) { + nodePixelVelocitiesY[1] = 0; + } else { + mark.setLayoutX(mark.getLayoutX() + nodePixelVelocitiesX[1] * timeInterval); + mark.setLayoutY(mark.getLayoutY() + nodePixelVelocitiesY[1] * timeInterval); + } + } + } + + public void moveTo (double x, double y, double rotation) { + moveTo(x, y); + rotateTo(rotation); + } + public void moveTo (double x, double y) { super.setLayoutX(x); super.setLayoutY(y); } public boolean hasRaceId (int... raceIds) { - for (int id : raceIds) { + for (int id : raceIds) + for (Mark mark : marks) if (id == mark.getId()) return true; - if (mark.getMarkType() != MarkType.SINGLE_MARK) { - if (id == ((GateMark) mark).getSingleMark1().getId() || id == ((GateMark) mark).getSingleMark2().getId()) - return true; - } - } return false; } public void toggleAnnotations () { @@ -111,4 +209,12 @@ public class MarkGroup extends RaceObject { MARK_RADIUS = markRadius; } + public int[] getRaceIds () { + int[] idArray = new int[marks.size()]; + int i = 0; + for (Mark mark : marks) + idArray[i++] = mark.getId(); + return idArray; + } + }