Merge branch 'issue55-collision' into 'master'

Resolve issue #55 - only one collision displayed per boat

Resolves issues #55 and #57.

See merge request !47
main
Fraser Cope 8 years ago
commit 94b5f06ede

@ -366,10 +366,8 @@ public class MockRace extends RaceState {
//Checks if the current boat has finished the race or not. //Checks if the current boat has finished the race or not.
boolean finish = this.isLastLeg(boat.getCurrentLeg()); boolean finish = this.isLastLeg(boat.getCurrentLeg());
if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds) { if (!finish && totalElapsedMilliseconds >= updatePeriodMilliseconds && !boat.isColliding()) {
if(boat.isVelocityDefault()) setBoatSpeed(boat); if(boat.isVelocityDefault()) setBoatSpeed(boat);
//Calculates the distance travelled, in meters, in the current timeslice. //Calculates the distance travelled, in meters, in the current timeslice.
double distanceTravelledMeters = boat.calculateMetersTravelled(updatePeriodMilliseconds) * this.scaleFactor; double distanceTravelledMeters = boat.calculateMetersTravelled(updatePeriodMilliseconds) * this.scaleFactor;

@ -24,7 +24,8 @@ public abstract class Collider extends Observable implements Locatable {
// Direction of collider from heading // Direction of collider from heading
Bearing relative = Bearing.fromDegrees(absolute.degrees() - boat.getBearing().degrees()); Bearing relative = Bearing.fromDegrees(absolute.degrees() - boat.getBearing().degrees());
if(actualDistance <= distance) { if(!boat.isColliding() && actualDistance <= distance) {
boat.setColliding(true);
Collision collision = new Collision(boat, relative, distance); Collision collision = new Collision(boat, relative, distance);
// Notify object of collision // Notify object of collision
onCollisionEnter(collision); onCollisionEnter(collision);

@ -29,17 +29,18 @@ public class CollisionCommand extends ObserverCommand {
public void execute() { public void execute() {
this.azimuth = Azimuth.fromDegrees(boat.getBearing().degrees() - 180d); this.azimuth = Azimuth.fromDegrees(boat.getBearing().degrees() - 180d);
this.startingPosition = boat.getPosition(); this.startingPosition = boat.getPosition();
this.distance = 30; this.distance = 60;
boat.setVelocityDefault(false); boat.setVelocityDefault(false);
} }
@Override @Override
public void update(Observable o, Object arg) { public void update(Observable o, Object arg) {
if(GPSCoordinate.calculateDistanceMeters(boat.getPosition(), startingPosition) < distance) { if(GPSCoordinate.calculateDistanceMeters(boat.getPosition(), startingPosition) < distance) {
boat.setPosition(GPSCoordinate.calculateNewPosition(boat.getPosition(), 2, azimuth)); boat.setPosition(GPSCoordinate.calculateNewPosition(boat.getPosition(), 3, azimuth));
} else { } else {
race.deleteObserver(this); race.deleteObserver(this);
boat.setVelocityDefault(true); boat.setVelocityDefault(true);
boat.setColliding(false);
} }
} }
} }

@ -98,6 +98,11 @@ public class Boat extends Collider {
*/ */
private boolean sailsOut = true; private boolean sailsOut = true;
/**
* Indicates whether boat is currently involved in a collision
*/
private boolean isColliding = false;
/** /**
* Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table. * Constructs a boat object with a given sourceID, name, country/team abbreviation, and polars table.
* *
@ -407,7 +412,7 @@ public class Boat extends Collider {
@Override @Override
public boolean rayCast(Boat boat) { public boolean rayCast(Boat boat) {
if(boat != this) { if(boat != this) {
return rayCast(boat, 100); return rayCast(boat, 15);
} else return false; } else return false;
} }
@ -419,4 +424,12 @@ public class Boat extends Collider {
notifyObservers(e); notifyObservers(e);
} }
} }
public boolean isColliding() {
return isColliding;
}
public void setColliding(boolean colliding) {
isColliding = colliding;
}
} }

@ -29,11 +29,6 @@ public class Mark extends Collider{
*/ */
private GPSCoordinate position; private GPSCoordinate position;
/**
* Repulsion radius of the mark
*/
private double repulsionRadius = 50;
/** /**
* Constructs a mark with a given source ID, name, and position. * Constructs a mark with a given source ID, name, and position.
* @param sourceID The source ID of the mark. * @param sourceID The source ID of the mark.
@ -97,7 +92,7 @@ public class Mark extends Collider{
@Override @Override
public boolean rayCast(Boat boat) { public boolean rayCast(Boat boat) {
return rayCast(boat, repulsionRadius); return rayCast(boat, 15);
} }
@Override @Override

@ -323,16 +323,16 @@ public class RaceViewController extends Controller {
Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1)); Material markColor = new PhongMaterial(new Color(0.15,0.9,0.2,1));
CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark(); CompoundMark nextMark = boat.getCurrentLeg().getEndCompoundMark();
view3D.getShape(nextMark.getMark1().getSourceID()).setMaterial(markColor); view3D.getShape(nextMark.getMark1().getSourceID()).getMesh().setMaterial(markColor);
if(nextMark.getMark2() != null) { if(nextMark.getMark2() != null) {
view3D.getShape(nextMark.getMark2().getSourceID()).setMaterial(markColor); view3D.getShape(nextMark.getMark2().getSourceID()).getMesh().setMaterial(markColor);
} }
Subject3D shockwave = new Shockwave(10); Subject3D shockwave = new Shockwave(10);
viewSubjects.add(shockwave); viewSubjects.add(shockwave);
boat.legProperty().addListener((o, prev, curr) -> swapColours(curr)); boat.legProperty().addListener((o, prev, curr) -> Platform.runLater(() -> swapColours(curr)));
boat.hasCollidedProperty().addListener((o, prev, curr) -> showCollision(boatModel, shockwave)); boat.hasCollidedProperty().addListener((o, prev, curr) -> Platform.runLater(() -> showCollision(boat, shockwave)));
} }
// Fix initial bird's-eye position // Fix initial bird's-eye position
view3D.updatePivot(new Translate(250, 0, 210)); view3D.updatePivot(new Translate(250, 0, 210));
@ -341,7 +341,7 @@ public class RaceViewController extends Controller {
if(curr != null && visualiserRace.getVisualiserRaceState().isVisualiserBoat(curr.getSourceID())) { if(curr != null && visualiserRace.getVisualiserRaceState().isVisualiserBoat(curr.getSourceID())) {
addThirdPersonAnnotations(curr); addThirdPersonAnnotations(curr);
} else { } else {
removeThirdPersonAnnotations(prev); removeThirdPersonAnnotations();
} }
}); });
@ -390,18 +390,20 @@ public class RaceViewController extends Controller {
}); });
} }
private void showCollision(Subject3D boat, Subject3D shockwave) { private void showCollision(VisualiserBoat boat, Subject3D shockwave) {
Subject3D boatModel = view3D.getShape(boat.getSourceID());
AnimationTimer shockFront = new AnimationTimer() { AnimationTimer shockFront = new AnimationTimer() {
double opacity = 1; double opacity = 1;
@Override @Override
public void handle(long now) { public void handle(long now) {
shockwave.setX(boat.getPosition().getX()); shockwave.setX(boatModel.getPosition().getX());
shockwave.setY(boat.getPosition().getY()); shockwave.setY(boatModel.getPosition().getY());
shockwave.setZ(boat.getPosition().getZ()); shockwave.setZ(boatModel.getPosition().getZ());
if(opacity <= 0) { if(opacity <= 0) {
shockwave.getMesh().setMaterial(new PhongMaterial(new Color(1,0,0,0))); shockwave.getMesh().setMaterial(new PhongMaterial(Color.TRANSPARENT));
boat.setHasCollided(false);
this.stop(); this.stop();
} }
else { else {
@ -435,38 +437,14 @@ public class RaceViewController extends Controller {
} }
}; };
arrowToNextMark.start(); arrowToNextMark.start();
/*
try {
VisualiserBoat boat = visualiserRace.getVisualiserRaceState().getBoat(subject3D.getSourceID());
this.pointToMark = new AnimationTimer() {
@Override
public void handle(long now) {
CompoundMark target = boat.getCurrentLeg().getEndCompoundMark();
Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate());
nextMarkArrow.setX(view3D.getPivot().getX());
nextMarkArrow.setY(view3D.getPivot().getY());
nextMarkArrow.setZ(view3D.getPivot().getZ() + 10);
nextMarkArrow.setHeading(headingToMark.degrees());
}
};
pointToMark.start();
} catch (BoatNotFoundException e) {
e.printStackTrace();
}*/
} }
private void removeThirdPersonAnnotations(Subject3D subject3D) { private void removeThirdPersonAnnotations() {
viewSubjects.remove(nextMarkArrow); viewSubjects.remove(nextMarkArrow);
arrowToNextMark.stop(); if (arrowToNextMark != null) {
/* arrowToNextMark.stop();
try { }
VisualiserBoat boat = visualiserRace.getVisualiserRaceState().getBoat(subject3D.getSourceID());
boat.positionProperty().removeListener(pointToMark);
} catch (BoatNotFoundException e) {
e.printStackTrace();
}*/
//pointToMark.stop();
} }
/** /**
@ -477,21 +455,26 @@ public class RaceViewController extends Controller {
CompoundMark start = leg.getStartCompoundMark(); CompoundMark start = leg.getStartCompoundMark();
CompoundMark end = leg.getEndCompoundMark(); CompoundMark end = leg.getEndCompoundMark();
Shape3D start1 = view3D.getShape(start.getMark1().getSourceID()); //The last leg "finish" doesn't have compound marks.
Shape3D end1 = view3D.getShape(end.getMark1().getSourceID()); if (start == null || end == null ) {
return;
}
Shape3D start1 = view3D.getShape(start.getMark1().getSourceID()).getMesh();
Shape3D end1 = view3D.getShape(end.getMark1().getSourceID()).getMesh();
Material nextMark = start1.getMaterial(); Material nextMark = start1.getMaterial();
Material lastMark = end1.getMaterial(); Material lastMark = end1.getMaterial();
start1.setMaterial(lastMark); start1.setMaterial(lastMark);
if(start.getMark2() != null) { if(start.getMark2() != null) {
Shape3D start2 = view3D.getShape(start.getMark2().getSourceID()); Shape3D start2 = view3D.getShape(start.getMark2().getSourceID()).getMesh();
start2.setMaterial(lastMark); start2.setMaterial(lastMark);
} }
end1.setMaterial(nextMark); end1.setMaterial(nextMark);
if(end.getMark2() != null) { if(end.getMark2() != null) {
Shape3D end2 = view3D.getShape(end.getMark2().getSourceID()); Shape3D end2 = view3D.getShape(end.getMark2().getSourceID()).getMesh();
end2.setMaterial(nextMark); end2.setMaterial(nextMark);
} }
} }
@ -600,6 +583,7 @@ public class RaceViewController extends Controller {
/** /**
* Transition from the race view to the finish view. * Transition from the race view to the finish view.
* @throws IOException Thrown if the finish scene cannot be loaded.
*/ */
private void finishRace() throws IOException { private void finishRace() throws IOException {
RaceFinishController fc = RaceFinishController fc =

@ -80,8 +80,9 @@ public class ControllerServer implements RunnableWithFramePeriod {
try { try {
Command command = CommandFactory.createCommand(raceState, boatAction); Command command = CommandFactory.createCommand(raceState, boatAction);
compositeCommand.addCommand(command); if(command != null) {
compositeCommand.addCommand(command);
}
} catch (CommandConstructionException e) { } catch (CommandConstructionException e) {
Logger.getGlobal().log(Level.WARNING, "ControllerServer could not create a Command for BoatAction: " + boatAction + ".", e); Logger.getGlobal().log(Level.WARNING, "ControllerServer could not create a Command for BoatAction: " + boatAction + ".", e);

@ -35,7 +35,7 @@ public class Boundary3D {
if (points.size() < 2){ if (points.size() < 2){
return; return;
} }
System.out.println(points.size());
for (int i = 0; i < points.size(); i++){ for (int i = 0; i < points.size(); i++){
if (i + 1 != points.size()){ if (i + 1 != points.size()){
addBound(points.get(i), points.get(i + 1)); addBound(points.get(i), points.get(i + 1));

@ -32,6 +32,9 @@ public class SeaSurface extends Subject3D {
/** /**
* Creates the sea surface * Creates the sea surface
* @param size size of sea noise array.
* @param freq frequency of sea noise array.
* @return The sea surface.
*/ */
private static Shape3D createSurface(int size, double freq) { private static Shape3D createSurface(int size, double freq) {
float[][] noiseArray = PerlinNoiseGenerator.createNoise(size, freq); float[][] noiseArray = PerlinNoiseGenerator.createNoise(size, freq);

@ -33,6 +33,7 @@ public class Subject3D {
/** /**
* Constructor for view subject wrapper * Constructor for view subject wrapper
* @param mesh to be rendered * @param mesh to be rendered
* @param sourceID Source ID of the subject.
*/ */
public Subject3D(Shape3D mesh, int sourceID) { public Subject3D(Shape3D mesh, int sourceID) {
this.mesh = mesh; this.mesh = mesh;

@ -36,9 +36,9 @@ public class View3D extends Pane {
*/ */
private Map<Shape3D, Subject3D> shapeMap; private Map<Shape3D, Subject3D> shapeMap;
/** /**
* Map for selecting Shape3D from source ID * Map for selecting Subject3D from source ID
*/ */
private Map<Integer, Shape3D> sourceMap; private Map<Integer, Subject3D> sourceMap;
/** /**
* Subject tracked by camera * Subject tracked by camera
*/ */
@ -150,14 +150,14 @@ public class View3D extends Pane {
for (Subject3D shape : c.getAddedSubList()) { for (Subject3D shape : c.getAddedSubList()) {
world.getChildren().add(shape.getMesh()); world.getChildren().add(shape.getMesh());
shapeMap.put(shape.getMesh(), shape); shapeMap.put(shape.getMesh(), shape);
sourceMap.put(shape.getSourceID(), shape.getMesh()); sourceMap.put(shape.getSourceID(), shape);
} }
} }
} }
}); });
} }
public Shape3D getShape(int sourceID) { public Subject3D getShape(int sourceID) {
return sourceMap.get(sourceID); return sourceMap.get(sourceID);
} }

Loading…
Cancel
Save