Finished tweaking wakes. Made marker movement smooth.

#implement #story[818]
This commit is contained in:
Calum
2017-04-30 22:34:49 +12:00
parent 45b77c05d4
commit 0eb767b615
5 changed files with 153 additions and 134 deletions
+6 -16
View File
@@ -22,7 +22,7 @@ public class BoatGroup extends RaceObject{
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 final int LINE_INTERVAL = 180; private static final int LINE_INTERVAL = 30;
private static double expectedUpdateInterval = 200; private static double expectedUpdateInterval = 200;
private double framesForNewLine = 0; private double framesForNewLine = 0;
private boolean destinationSet; private boolean destinationSet;
@@ -150,7 +150,6 @@ public class BoatGroup extends RaceObject{
double dx = pixelVelocityX * timeInterval; double dx = pixelVelocityX * timeInterval;
double dy = pixelVelocityY * timeInterval; double dy = pixelVelocityY * timeInterval;
double rotation = rotationalVelocity * timeInterval; double rotation = rotationalVelocity * timeInterval;
moveGroupBy(dx, dy, rotation); moveGroupBy(dx, dy, rotation);
if (framesForNewLine-- == 0) { if (framesForNewLine-- == 0) {
@@ -176,9 +175,11 @@ public class BoatGroup extends RaceObject{
} }
public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) { public void setDestination (double newXValue, double newYValue, double rotation, int... raceIds) {
destinationSet = true;
boat.setVelocity(StreamParser.boatSpeeds.get((long)boat.getId()));
if (hasRaceId(raceIds)) { if (hasRaceId(raceIds)) {
destinationSet = true;
boat.setVelocity(StreamParser.boatSpeeds.get((long)boat.getId()));
if (currentRotation < 0)
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;
@@ -191,24 +192,13 @@ public class BoatGroup extends RaceObject{
} else { } else {
pixelVelocityY = dy / expectedUpdateInterval; pixelVelocityY = dy / expectedUpdateInterval;
} }
// this.pixelVelocityX = (newXValue - boatPoly.getLayoutX()) / expectedUpdateInterval;
// this.pixelVelocityY = (newYValue - boatPoly.getLayoutY()) / expectedUpdateInterval;
rotationalGoal = rotation; rotationalGoal = rotation;
calculateRotationalVelocity(); calculateRotationalVelocity();
//Sometimes rotations are way too big.
//if (Math.abs(rotationalVelocity) > 0.00003)
// rotationalVelocity = 0;
//
if (wakeGenerationDelay > 0) { if (wakeGenerationDelay > 0) {
wake.rotate(rotationalGoal); wake.rotate(rotationalGoal);
wakeGenerationDelay--; wakeGenerationDelay--;
} else { } else {
if (Math.abs(rotationalVelocity) > 0.1) wake.setRotationalVelocity(rotationalVelocity, currentRotation, pixelVelocityX, pixelVelocityY);
// rotationalVelocity = 0;
//
wake.setRotationalVelocity(0, rotationalGoal, pixelVelocityX, pixelVelocityY);
else
wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, pixelVelocityX, pixelVelocityY);
} }
} }
} }
@@ -18,6 +18,8 @@ public abstract class RaceObject extends Group {
protected double pixelVelocityX; protected double pixelVelocityX;
protected double pixelVelocityY; protected double pixelVelocityY;
static double max = 0;
public Point2D getPosition () { public Point2D getPosition () {
return new Point2D(super.getLayoutX(), getLayoutY()); return new Point2D(super.getLayoutX(), getLayoutY());
} }
@@ -40,6 +42,13 @@ public abstract class RaceObject extends Group {
} else { } else {
this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval; this.rotationalVelocity = (rotationalGoal - currentRotation) / expectedUpdateInterval;
} }
//Sometimes the rotation is too large to be realistic. In that case just do it instantly.
if (Math.abs(rotationalVelocity) > 1) {
rotationalVelocity = 0;
rotateTo(rotationalGoal);
}
// max = Math.max(max, Math.abs(rotationalVelocity));
// System.out.println("max = " + max);
} }
/** /**
+13 -2
View File
@@ -21,6 +21,8 @@ class Wake extends Group {
private double[] rotations = new double[numWakes]; private double[] rotations = new double[numWakes];
private int[] velocityIndices = new int[numWakes]; private int[] velocityIndices = new int[numWakes];
private double sum = 0; private double sum = 0;
static double max = 0;
static double min = Double.MAX_VALUE;
/** /**
* Create a wake at the given location. * Create a wake at the given location.
@@ -48,12 +50,21 @@ class Wake extends Group {
* @param rotationalVelocity The rotationalVelocity the wake should move at. * @param rotationalVelocity The rotationalVelocity the wake should move at.
*/ */
void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocityX, double velocityY) { void setRotationalVelocity (double rotationalVelocity, double rotationGoal, double velocityX, double velocityY) {
sum -= Math.abs(velocities[velocityIndices[0]]); if (Math.abs(rotationalVelocity) > 0.5) {
rotationalVelocity = 0;
}
sum -= Math.abs(velocities[(velocityIndices[0] + 10) % 13]);
// sum -= Math.abs(velocities[velocityIndices[0]]);
sum += Math.abs(rotationalVelocity); sum += Math.abs(rotationalVelocity);
if (sum < 0.00002) System.out.println("sum = " + sum);
if (sum < 0.9)
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.
max = Math.max(max, sum);
min = Math.min(max, sum);
System.out.println("max = " + max);
System.out.println("min = " + min);
//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;
+124 -115
View File
@@ -28,6 +28,9 @@ public class MarkGroup extends RaceObject {
private Point2D[] nodeDestinations; private Point2D[] nodeDestinations;
public MarkGroup (Mark mark, Point2D... points) { public MarkGroup (Mark mark, Point2D... points) {
nodePixelVelocitiesX = new double[points.length];
nodePixelVelocitiesY = new double[points.length];
nodeDestinations = new Point2D[points.length];
marks.add(mark); marks.add(mark);
mainMark = mark; mainMark = mark;
Color color = Color.BLACK; Color color = Color.BLACK;
@@ -36,36 +39,58 @@ public class MarkGroup extends RaceObject {
} else if (mark.getName().equals("Finish")){ } else if (mark.getName().equals("Finish")){
color = Color.RED; color = Color.RED;
} }
System.out.println("HERE ARE THE CHILDREN LOL"); Circle markCircle;
if (mark.getMarkType() == MarkType.SINGLE_MARK) { if (mark.getMarkType() == MarkType.SINGLE_MARK) {
super.getChildren().add(new Circle(0, 0, MARK_RADIUS, color)); markCircle = new Circle(
nodeDestinations = new Point2D[]{ points[0].getX(),
new Point2D(super.getChildren().get(0).getLayoutX() points[0].getY(),
, super.getChildren().get(0).getLayoutY())}; MARK_RADIUS,
color
);
nodeDestinations = new Point2D[]{
new Point2D(markCircle.getCenterX(), markCircle.getCenterY()
)
};
super.getChildren().add(markCircle);
} else { } else {
marks.add(((GateMark) mark).getSingleMark1()); marks.add(((GateMark) mark).getSingleMark1());
marks.add(((GateMark) mark).getSingleMark2()); marks.add(((GateMark) mark).getSingleMark2());
super.getChildren().add( nodePixelVelocitiesX = new double[]{0d,0d};
new Circle( nodePixelVelocitiesY = new double[]{0d,0d};
(points[1].getX() - points[0].getX()) / 2d, nodeDestinations = new Point2D[2];
(points[1].getY() - points[0].getY()) / 2d, // markCircle = new Circle(
MARK_RADIUS, // (points[1].getX() - points[0].getX()) / 2d,
color // (points[1].getY() - points[0].getY()) / 2d,
) // MARK_RADIUS,
// color
//
markCircle = new Circle(
points[0].getX(),
points[0].getY(),
MARK_RADIUS,
color
); );
super.getChildren().add( nodeDestinations[0] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
new Circle( super.getChildren().add(markCircle);
-(points[1].getX() - points[0].getX()) / 2d, // markCircle = new Circle(
-(points[1].getY() - points[0].getY()) / 2d, // -(points[1].getX() - points[0].getX()) / 2d,
MARK_RADIUS, // -(points[1].getY() - points[0].getY()) / 2d,
color // MARK_RADIUS,
) // color
// );
markCircle = new Circle(
points[1].getX(),
points[1].getY(),
MARK_RADIUS,
color
); );
nodeDestinations[1] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
super.getChildren().add(markCircle);
Line line = new Line( Line line = new Line(
(points[1].getX() - points[0].getX()) / 2d, points[0].getX(),
(points[1].getY() - points[0].getY()) / 2d, points[0].getY(),
-(points[1].getX() - points[0].getX()) / 2d, points[1].getX(),
-(points[1].getY() - points[0].getY()) / 2d points[1].getY()
); );
line.setStrokeWidth(LINE_THICKNESS); line.setStrokeWidth(LINE_THICKNESS);
line.setStroke(color); line.setStroke(color);
@@ -73,14 +98,8 @@ public class MarkGroup extends RaceObject {
line.getStrokeDashArray().addAll(DASHED_GAP_LEN, DASHED_LINE_LEN); line.getStrokeDashArray().addAll(DASHED_GAP_LEN, DASHED_LINE_LEN);
} }
super.getChildren().add(line); super.getChildren().add(line);
nodePixelVelocitiesX = new double[]{0d,0d};
nodePixelVelocitiesY = new double[]{0d,0d};
nodeDestinations = new Point2D[]{
new Point2D(super.getChildren().get(0).getLayoutX(), super.getChildren().get(0).getLayoutY()),
new Point2D(super.getChildren().get(1).getLayoutX(), super.getChildren().get(1).getLayoutY())
};
} }
moveTo(points[0].getX(), points[0].getY()); //moveTo(points[0].getX(), points[0].getY());
} }
public void setDestination (double x, double y, double rotation, int... raceIds) { public void setDestination (double x, double y, double rotation, int... raceIds) {
@@ -90,110 +109,90 @@ public class MarkGroup extends RaceObject {
} }
public void setDestination (double x, double y, int... raceIds) { public void setDestination (double x, double y, int... raceIds) {
int childrenIndex = -1; for (int i = 0; i < marks.size(); i++)
for (Mark mark : marks) {
for (int id : raceIds) for (int id : raceIds)
if (id == mark.getId() && childrenIndex != -1) if (id == marks.get(i).getId())
setDestinationChild(x, y, childrenIndex); setDestinationChild(x, y, Math.max(0, i-1));
else if (id == mark.getId())
setDestinationGroup(x, y);
childrenIndex++;
}
updateChildren();
} }
private void setDestinationChild (double x, double y, int childIndex) { private void setDestinationChild (double x, double y, int childIndex) {
double relativeX = x - super.getLayoutX(); //double relativeX = x - super.getLayoutX();
double relativeY = y - super.getLayoutY(); //double relativeY = y - super.getLayoutY();
this.nodeDestinations[childIndex] = new Point2D(relativeX, relativeY); Circle markCircle = (Circle) super.getChildren().get(childIndex);
this.nodePixelVelocitiesX[childIndex] = (relativeX - super.getChildren().get(childIndex).getLayoutX()) / expectedUpdateInterval; this.nodeDestinations[childIndex] = new Point2D(x, y);
this.nodePixelVelocitiesY[childIndex] = (relativeY - super.getChildren().get(childIndex).getLayoutY()) / expectedUpdateInterval; //if (Math.abs(relativeX - markCircle.getCenterX()) > 30 && Math.abs(relativeY - markCircle.getCenterY()) > 30) {
this.nodePixelVelocitiesX[childIndex] = (x - markCircle.getCenterX()) / expectedUpdateInterval;
this.nodePixelVelocitiesY[childIndex] = (y - markCircle.getCenterY()) / expectedUpdateInterval;
//}
} }
private void setDestinationGroup (double x, double y) {
double relativeX = x - super.getLayoutX();
double relativeY = y - super.getLayoutY();
this.nodeDestinations[0] = new Point2D(relativeX, relativeY);
pixelVelocityX = (x - super.getLayoutX()) / expectedUpdateInterval;
pixelVelocityY = (y - super.getLayoutY()) / expectedUpdateInterval;
}
public void rotateTo (double rotation) { public void rotateTo (double rotation) {
super.getTransforms().clear(); if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
super.getTransforms().add(new Rotate(rotation)); Line line = (Line) super.getChildren().get(2);
double xCenter = Math.abs(line.getEndX() - line.getStartX());
double yCenter = Math.abs(line.getEndY() - line.getStartY());
super.getTransforms().setAll(new Rotate(rotation, xCenter, yCenter));
}
} }
public void updatePosition (long timeInterval) { public void updatePosition (long timeInterval) {
// double x = pixelVelocityX * timeInterval; Circle markCircle = (Circle) super.getChildren().get(0);
// double y = pixelVelocityY * timeInterval;
// double rotation = rotationalVelocity * timeInterval; if (nodePixelVelocitiesX[0] > 0 && markCircle.getCenterX() > nodeDestinations[0].getX() ||
// moveGroupBy(x, y, rotation); nodePixelVelocitiesX[0] < 0 && markCircle.getCenterX() < nodeDestinations[0].getY())
// updateChildren(timeInterval); nodePixelVelocitiesX[0] = 0;
else
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[0] * timeInterval);
if (nodePixelVelocitiesY[0] > 0 && markCircle.getCenterY() > nodeDestinations[0].getY() ||
nodePixelVelocitiesY[0] < 0 && markCircle.getCenterY() < nodeDestinations[0].getY())
nodePixelVelocitiesY[0] = 0;
else
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[0] * timeInterval);
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
Line line = (Line) super.getChildren().get(2);
line.setStartX(markCircle.getCenterX());
line.setStartY(markCircle.getCenterY());
markCircle = (Circle) super.getChildren().get(1);
if (nodePixelVelocitiesX[1] > 0 && markCircle.getCenterX() >= nodeDestinations[1].getX() ||
nodePixelVelocitiesX[1] < 0 && markCircle.getCenterX() <= nodeDestinations[1].getX())
nodePixelVelocitiesX[1] = 0;
else
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[1] * timeInterval);
if (nodePixelVelocitiesY[1] > 0 && markCircle.getCenterY() > nodeDestinations[1].getY() ||
nodePixelVelocitiesY[1] < 0 && markCircle.getCenterY() < nodeDestinations[1].getY())
nodePixelVelocitiesY[1] = 0;
else
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[1] * timeInterval);
line.setEndX(markCircle.getCenterX());
line.setEndY(markCircle.getCenterY());
}
} }
public void moveGroupBy (double x, double y, double rotation) { public void moveGroupBy (double x, double y, double rotation) {
super.setLayoutX(super.getLayoutX() + x);
super.setLayoutY(super.getLayoutY() + y);
rotateTo(rotation);
}
private void updateChildren () {
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) { if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
Line line = (Line) super.getChildren().get(2); Line line = (Line) super.getChildren().get(2);
for (int childIndex = 0; childIndex < 2; childIndex++){ for (int childIndex = 0; childIndex < 2; childIndex++){
Circle mark = (Circle) super.getChildren().get(childIndex); Circle mark = (Circle) super.getChildren().get(childIndex);
Point2D dest = nodeDestinations[childIndex]; mark.setCenterY(mark.getCenterY() + y);
mark.setCenterY(dest.getY()); mark.setCenterX(mark.getCenterX() + x);
mark.setCenterX(dest.getX());
} }
line.setStartX(nodeDestinations[0].getX()); line.setStartX(line.getStartX() + x);
line.setStartY(nodeDestinations[0].getY()); line.setStartY(line.getStartY() + y);
line.setEndX(nodeDestinations[1].getX()); line.setEndX(line.getEndX() + x);
line.setEndY(nodeDestinations[1].getY()); line.setEndY(line.getEndY() + y);
// 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);
// }
} else { } else {
Circle mark = (Circle) super.getChildren().get(0); Circle mark = (Circle) super.getChildren().get(0);
Point2D dest = nodeDestinations[0]; mark.setCenterY(mark.getCenterY() + y);
mark.setCenterY(dest.getY()); mark.setCenterX(mark.getCenterX() + x);
mark.setCenterX(dest.getX());
} }
rotateTo(currentRotation + rotation);
} }
public void moveTo (double x, double y, double rotation) { public void moveTo (double x, double y, double rotation) {
@@ -202,8 +201,19 @@ public class MarkGroup extends RaceObject {
} }
public void moveTo (double x, double y) { public void moveTo (double x, double y) {
super.setLayoutX(x); Circle markCircle = (Circle) super.getChildren().get(0);
super.setLayoutY(y); markCircle.setCenterX(x);
markCircle.setCenterY(y);
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
markCircle = (Circle) super.getChildren().get(1);
markCircle.setCenterX(x);
markCircle.setCenterY(y);
Line line = (Line) super.getChildren().get(2);
line.setStartX(x);
line.setStartY(y);
line.setEndX(x);
line.setEndY(y);
}
} }
public boolean hasRaceId (int... raceIds) { public boolean hasRaceId (int... raceIds) {
@@ -232,5 +242,4 @@ public class MarkGroup extends RaceObject {
idArray[i++] = mark.getId(); idArray[i++] = mark.getId();
return idArray; return idArray;
} }
} }
@@ -22,7 +22,7 @@ public class StreamPacket {
// if (this.type == PacketType.XML_MESSAGE){ // if (this.type == PacketType.XML_MESSAGE){
// //System.out.println("--------"); // //System.out.println("--------");
// System.out.println(new String(payload)); // System.out.println(new String(payload));
// StreamParser.parsePacket(this); // //StreamParser.parsePacket(this);
// } // }
} }