diff --git a/src/main/java/seng302/models/BoatGroup.java b/src/main/java/seng302/models/BoatGroup.java index 80491fc9..961cc012 100644 --- a/src/main/java/seng302/models/BoatGroup.java +++ b/src/main/java/seng302/models/BoatGroup.java @@ -10,7 +10,9 @@ import javafx.scene.transform.Rotate; import seng302.models.parsers.StreamParser; /** - * Created by CJIRWIN on 25/04/2017. + * 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 + * annotate the boat teams name and the boats velocity. */ public class BoatGroup extends RaceObject{ @@ -20,7 +22,7 @@ public class BoatGroup extends RaceObject{ private static final double VELOCITY_Y_OFFSET = -5d; private static final double BOAT_HEIGHT = 15d; private static final double BOAT_WIDTH = 10d; - private static final int LINE_INTERVAL = 30; + private static final int LINE_INTERVAL = 180; private static double expectedUpdateInterval = 200; private double framesForNewLine = 0; private boolean destinationSet; @@ -34,16 +36,34 @@ public class BoatGroup extends RaceObject{ private Text velocityObject; private Wake wake; + /** + * Creates a BoatGroup with the default triangular boat polygon. + * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used to tell which + * BoatGroup to update. + * @param color The colour of the boat polygon and the trailing line. + */ public BoatGroup (Boat boat, Color color){ this.boat = boat; initChildren(color); } + /** + * Creates a BoatGroup with the boat being the default polygon. The head of the boat should be at point (0,0). + * @param boat The boat that the BoatGroup will represent. Must contain an ID which will be used to tell which + * BoatGroup to update. + * @param color The colour of the boat polygon and the trailing line. + * @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat polygon. + */ public BoatGroup (Boat boat, Color color, double... points) { initChildren(color, points); } + /** + * Creates the javafx objects that will be the in the group by default. + * @param color The colour of the boat polygon and the trailing line. + * @param points An array of co-ordinates x1,y1,x2,y2,x3,y3... that will make up the boat polygon. + */ private void initChildren (Color color, double... points) { boatPoly = new Polygon(points); boatPoly.setFill(color); @@ -60,16 +80,20 @@ public class BoatGroup extends RaceObject{ velocityObject.relocate(velocityObject.getX(), velocityObject.getY()); destinationSet = false; - wake = new Wake(0, 0); + wake = new Wake(0, -BOAT_HEIGHT); wakeGenerationDelay = wake.numWakes; super.getChildren().addAll(teamNameObject, velocityObject, boatPoly); } + /** + * Creates the javafx objects that will be the in the group by default. + * @param color The colour of the boat polygon and the trailing line. + */ private void initChildren (Color color) { - initChildren(color, - -BOAT_WIDTH / 2, BOAT_HEIGHT, - 0.0, 0.0, - BOAT_WIDTH / 2, BOAT_HEIGHT); + initChildren(color, + -BOAT_WIDTH / 2, BOAT_HEIGHT / 2, + 0.0, -BOAT_HEIGHT / 2, + BOAT_WIDTH / 2, BOAT_HEIGHT / 2); } /** @@ -93,12 +117,18 @@ public class BoatGroup extends RaceObject{ * 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 + * @param rotation The heading in degrees from north the boat should rotate to. */ public void moveTo (double x, double y, double rotation) { rotateTo(rotation); moveTo(x, y); } + /** + * 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 moveTo (double x, double y) { boatPoly.setLayoutX(x); boatPoly.setLayoutY(y); @@ -108,13 +138,18 @@ public class BoatGroup extends RaceObject{ velocityObject.setLayoutY(y); wake.setLayoutX(x); wake.setLayoutY(y); - //wake.rotate(currentRotation); + wake.rotate(currentRotation); } + /** + * Updates the position of all graphics in the BoatGroup based off of the given time interval. + * @param timeInterval The interval, in microseconds, the boat should update it's position based on. + */ public void updatePosition (long timeInterval) { + //Calculate the movement of the boat. double dx = pixelVelocityX * timeInterval; double dy = pixelVelocityY * timeInterval; - double rotation = 0d; + double rotation = rotationalVelocity * timeInterval; moveGroupBy(dx, dy, rotation); @@ -134,7 +169,7 @@ public class BoatGroup extends RaceObject{ if (destinationSet){ lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY()); } - if (lineGroup.getChildren().size() > 80) + if (lineGroup.getChildren().size() > 60) lineGroup.getChildren().remove(0); } wake.updatePosition(timeInterval); @@ -143,20 +178,38 @@ public class BoatGroup extends RaceObject{ public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) { destinationSet = true; boat.setVelocity(StreamParser.boatSpeeds.get((long)boat.getId())); - velocityObject.setText(String.valueOf(boat.getVelocity())); if (hasRaceId(raceIds)) { - this.pixelVelocityX = (newXValue - boatPoly.getLayoutX()) / expectedUpdateInterval; - this.pixelVelocityY = (newYValue - boatPoly.getLayoutY()) / expectedUpdateInterval; - this.rotationalGoal = rotation; + double dx = newXValue - boatPoly.getLayoutX(); + if ((dx > 0 && pixelVelocityX < 0) || (dx < 0 && pixelVelocityX > 0)) { + pixelVelocityX = 0; + } else { + pixelVelocityX = dx / expectedUpdateInterval; + } + double dy = newYValue - boatPoly.getLayoutY(); + if ((dy > 0 && pixelVelocityY < 0) || (dy < 0 && pixelVelocityY > 0)) { + pixelVelocityY = 0; + } else { + pixelVelocityY = dy / expectedUpdateInterval; + } +// this.pixelVelocityX = (newXValue - boatPoly.getLayoutX()) / expectedUpdateInterval; +// this.pixelVelocityY = (newYValue - boatPoly.getLayoutY()) / expectedUpdateInterval; + rotationalGoal = rotation; calculateRotationalVelocity(); - System.out.println("rotationalVelocity = " + rotationalVelocity); - rotateTo(rotation); -// if (wakeGenerationDelay > 0) { -// wake.rotate(rotationalGoal); -// wakeGenerationDelay--; -// } else { - wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, pixelVelocityX, pixelVelocityY); -// } + //Sometimes rotations are way too big. + //if (Math.abs(rotationalVelocity) > 0.00003) + // rotationalVelocity = 0; +// + if (wakeGenerationDelay > 0) { + wake.rotate(rotationalGoal); + wakeGenerationDelay--; + } else { + if (Math.abs(rotationalVelocity) > 0.1) +// rotationalVelocity = 0; +// + wake.setRotationalVelocity(0, rotationalGoal, pixelVelocityX, pixelVelocityY); + else + wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, pixelVelocityX, pixelVelocityY); + } } } @@ -181,11 +234,9 @@ public class BoatGroup extends RaceObject{ boatPoly.getTransforms().add(new Rotate(rotation)); } - - public void forceRotation () { rotateTo (rotationalGoal); - //wake.rotate(rotationalGoal); + wake.rotate(rotationalGoal); } public void toggleAnnotations () { diff --git a/src/main/java/seng302/models/Wake.java b/src/main/java/seng302/models/Wake.java index 44c8d538..897f5919 100644 --- a/src/main/java/seng302/models/Wake.java +++ b/src/main/java/seng302/models/Wake.java @@ -50,13 +50,10 @@ class Wake extends Group { void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocityX, double velocityY) { sum -= Math.abs(velocities[velocityIndices[0]]); sum += Math.abs(rotationalVelocity); - if (sum < 0.0001) { - System.out.println("***************************************************************************"); - System.out.println(sum); - System.out.println("***************************************************************************"); - 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. - } + if (sum < 0.00002) + 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. + //Update the index of the array of recent velocities that each wake uses. Each wake is 3 velocities behind the //next smallest wake. velocityIndices[0] = (13 + (velocityIndices[0] - 1) % 13) % 13; @@ -66,9 +63,9 @@ class Wake extends Group { //Scale wakes based on velocity. Assumes boats are always moving at a decent pace. double scaleFactor = Math.abs(Math.log10(Math.abs(velocityX) + Math.abs(velocityY))); - double baseRad = 30; + double baseRad = 25; for (Arc arc :arcs) { - double rad = Math.min(baseRad + 4 * scaleFactor, baseRad + 12); + double rad = Math.min(baseRad + 5 * scaleFactor, baseRad + 15); arc.setRadiusX(rad); arc.setRadiusY(rad); baseRad += 10; @@ -84,12 +81,6 @@ class Wake extends Group { rotations[i] = rotations[i] + velocities[velocityIndices[i]] * timeInterval; arcs[i].getTransforms().setAll(new Rotate(rotations[i])); } - System.out.println("rotations[0] = " + rotations[0]); - System.out.println("rotations[1] = " + rotations[1]); - System.out.println("rotations[2] = " + rotations[2]); - System.out.println("rotations[3] = " + rotations[3]); - System.out.println("rotations[4] = " + rotations[4]); - } /** diff --git a/src/main/java/seng302/models/parsers/StreamReceiver.java b/src/main/java/seng302/models/parsers/StreamReceiver.java index 74ce4748..5df8a1ab 100644 --- a/src/main/java/seng302/models/parsers/StreamReceiver.java +++ b/src/main/java/seng302/models/parsers/StreamReceiver.java @@ -4,6 +4,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; +import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; import java.util.concurrent.PriorityBlockingQueue; import java.util.zip.CRC32; @@ -13,8 +15,8 @@ import java.util.zip.Checksum; public class StreamReceiver extends Thread { private InputStream stream; private Socket host; - private ByteArrayOutputStream crcBuffer; - private Thread thread; + private ByteArrayOutputStream crcBuffer; + private Thread t; private String threadName; public static PriorityBlockingQueue packetBuffer; @@ -29,20 +31,21 @@ public class StreamReceiver extends Thread { } public void run(){ - packetBuffer = new PriorityBlockingQueue<>(256, new Comparator() { + PriorityBlockingQueue pq = new PriorityBlockingQueue<>(256, new Comparator() { @Override public int compare(StreamPacket s1, StreamPacket s2) { return (int) (s1.getTimeStamp() - s2.getTimeStamp()); } }); + packetBuffer = pq; connect(); } public void start () { System.out.println("Starting " + threadName ); - if (thread == null) { - thread = new Thread (this, threadName); - thread.start (); + if (t == null) { + t = new Thread (this, threadName); + t.start (); } } @@ -138,4 +141,15 @@ public class StreamReceiver extends Thread { } return partialLong; } + + + + + public static void main(String[] args) { + + StreamReceiver sr = new StreamReceiver("csse-s302staff.canterbury.ac.nz", 4941,"TestThread1"); + //StreamReceiver sr = new StreamReceiver("livedata.americascup.com", 4941, "TestThread2"); + sr.start(); + + } }